示例#1
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();
        }
示例#2
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();
        }
示例#3
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.");
        }
        /// <summary>
        /// Analyze 1 step, using femm window
        /// </summary>
        /// <param name="data"></param>
        /// <param name="step"></param>
        /// <param name="femm"></param>
        private void AnalyzeOne(int step, FEMM femm = null)
        {
            if (femm == null)
            {
                femm = FEMM.DefaultFEMM;
            }

            double t          = Results.Times[step];
            double rotorAngle = RotorSpeedDegreeSecond * t + StartAngle;

            // run script to update IA,IB,IC
            NLua.Lua lua_state                   = LuaHelper.GetLuaState();
            String[] currentFormulas             = { IA, IB, IC };
            String[] circuitNames                = { "A", "B", "C" };
            Dictionary <String, double> currents = new Dictionary <string, double>();

            try
            {
                lua_state["step"]  = step;
                lua_state["time"]  = t;
                lua_state["omega"] = RotorSpeedRadSecond;

                for (int i = 0; i < currentFormulas.Length; i++)
                {
                    double Ix = (double)lua_state.DoString("return " + currentFormulas[i])[0];
                    currents[circuitNames[i]] = Ix;
                }
            }
            catch (Exception ex)
            {
                log.Error("Lua error :" + ex.Message);
                //TODO: maybe halt analysis since there maybe big problem
            }

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

            // 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 using args passed from OnBeginAnalyzeOne
            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);

            //String bmpFile = config.OutDir + "\\bmp\\" + Path.GetFileNameWithoutExtension(stepfileFEM) + ".bmp";
            //femm.mo_savebitmap(bmpFile);

            // get circuits properties from stator
            TransientStepResult result = new TransientStepResult();

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

            result.Torque            = torque;
            result.RotorAngle        = rotorAngle;
            result.CircuitProperties = cps;

            Results[step] = result;

            OnFinishAnalyzeOneStep(this, result);

            log.Info(String.Format("Time {0:F5}: {1}", t, torque));

            femm.mo_close();
        }
示例#5
0
        private void AnalyzeOne(int step, FEMM femm = null)
        {
            if (femm == null)
            {
                femm = FEMM.DefaultFEMM;
            }

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

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

            // normalize, make rotorAngle inside (-2alpha,2alpha) to build FEMM model
            double femmRotorAngle = Motor.GetNormalizedRotorAngle(RotorAngle);

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

            // modify airgap (in case partial build)
            Motor.Airgap.AddBoundaryAtAngle(femmRotorAngle, femm);

            // modify stator currents
            // testing iq=const, id change to see how inductance d,q change
            //double id = 80.0 / StepCount * (step - StepCount);
            //double iq = 40.0;
            //double current = Math.Sqrt(id * id + iq * iq);
            //double Beta = Math.Abs(id) > 1e-8 ? Math.Atan(iq / id) * 180 / Math.PI : 90.0;
            //if (Beta < 0)
            //    Beta += 180;

            // Test change beta, not current
            //double beta = (this.Beta - 100) / StepCount * step + 100;
            //double current = MaxCurrent;

            var stator = Motor.Stator as Stator3Phase;

            // Change current
            double current;

            if (Only2ndQuarter)
            {
                int c = NotIncludeCurrentZero ? 1 : 0;
                current = MaxCurrent * (step + c) / StepCount;
            }
            else
            {
                int c = NotIncludeCurrentZero ? (step < StepCount ? 0 : 1) : 0;
                current = MaxCurrent / StepCount * ((step + c) - StepCount);
            }

            // correction beta with current rotor angle and original angle (0)
            double beta = this.Beta + (RotorAngle - stator.VectorMMFAngle) * Motor.Rotor.p;//in degree

            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 = Path_ToAnalysisVariant + "\\" + 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);
            double t = Motor.Rotor.getTorqueInAns(femm);

            PMMMAnalysisOneStepResult result = new PMMMAnalysisOneStepResult();

            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
            var Results = this.Results as PM_MMAnalysisResults;

            result.torque        = t;
            result.FluxLinkage_M = Results.FluxLinkageM;
            result.theta_e       = (RotorAngle - stator.VectorMMFAngle) * Motor.Rotor.p * Math.PI / 180;//in radian

            Results[step] = result;

            femm.mo_close();
        }
示例#6
0
        /// <summary>
        /// Analyze 1 step, using femm window
        /// </summary>
        /// <param name="data"></param>
        /// <param name="step"></param>
        /// <param name="femm"></param>
        private void AnalyzeOne(int step, FEMM femm = null)
        {
            if (femm == null)
            {
                femm = FEMM.DefaultFEMM;
            }

            if (SkewAngle <= 0 || NSkewSegment <= 0)
            {
                // prepare arguments for this step
                TransientStepArgs args = PrepareStepArgs(step);

                // before analyzing
                OnStartAnalyzeOneStep(this, args);

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

                // modify rotor: rotate, or other things that we can think of
                DoModifyRotor(args, femm);

                // modify stator: change current, or something else?
                DoModifyStator(args, femm);

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

                // analyze
                femm.mi_analyze(true);

                // close
                femm.mi_close();

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

                // do measure torque or anything else
                DoMeasureData(args, femm);

                // put in the list
                var Results = this.Results as Transient3PhaseMotorResults;
                Results[step] = args;

                //log.Info(String.Format("Time {0:F5}: {1}", t, torque));

                // save as bitmap
                if (ExportGif)
                {
                    femm.mo_clearblock();
                    femm.mo_zoom(0, -Motor.Stator.RYoke, Motor.Stator.RYoke, Motor.Stator.RYoke);
                    femm.mo_showdensityplot(true, false, 0, 2.1, FEMM.DensityPlotType.bmag);
                    femm.mo_savebitmap(Path.GetDirectoryName(stepfileFEM) + "\\" + Path.GetFileNameWithoutExtension(stepfileFEM) + ".bmp");
                }

                // close
                femm.mo_close();

                // after analyzing
                OnFinishAnalyzeOneStep(this, args);
            }
            else // has skewangle
            {
                // prepare arguments for this step
                TransientStepArgs total_args = PrepareStepArgs(step);

                // before analyzing
                OnStartAnalyzeOneStep(this, total_args);

                for (int k = 0; k < 2 * NSkewSegment + 1; k++)
                {
                    TransientStepArgs args = PrepareStepArgs(step);
                    double            sk   = (k - NSkewSegment) * SkewAngle / (2 * NSkewSegment);
                    args.skewAngleAdded = sk;
                    args.RotorAngle    += sk;

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

                    // modify rotor: rotate, or other things that we can think of
                    DoModifyRotor(args, femm);

                    // modify stator: change current, or something else?
                    DoModifyStator(args, femm);

                    // save as new file fem (temp only)
                    String stepfileFEM = Path_ToAnalysisVariant + "\\" + String.Format("{0:D4}_{1}.FEM", step, k);
                    femm.mi_saveas(stepfileFEM);

                    // analyze
                    femm.mi_analyze(true);

                    // close
                    femm.mi_close();

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

                    // do measure torque or anything else
                    DoMeasureData(args, femm);

                    // initialize data for total
                    if (k == 0)
                    {
                        total_args        = JSON.DeepCopy(args);
                        total_args.Torque = 0;
                        foreach (string key in total_args.CircuitProperties.Keys)
                        {
                            total_args.CircuitProperties[key].fluxlinkage = 0;
                        }
                    }

                    femm.mo_close();

                    total_args.Torque += args.Torque / (2 * NSkewSegment + 1);
                    foreach (string key in total_args.CircuitProperties.Keys)
                    {
                        total_args.CircuitProperties[key].fluxlinkage += args.CircuitProperties[key].fluxlinkage / (2 * NSkewSegment + 1);
                    }
                }

                // put in the list
                var Results = this.Results as Transient3PhaseMotorResults;
                Results[step] = total_args;

                //log.Info(String.Format("Time {0:F5}: {1}", t, torque));

                // after analyzing
                OnFinishAnalyzeOneStep(this, total_args);
            }
        }