├── .github
└── workflows
│ ├── python-package.yml
│ └── python-publish.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── MANIFEST.in
├── README.md
├── docs
├── Makefile
├── _templates
│ ├── custom-class-template.rst
│ └── custom-module-template.rst
├── afpm
│ ├── S1R1.svg
│ ├── S1R2.svg
│ └── S2R1.svg
├── amela.rst
├── api.rst
├── bchreader.rst
├── conf.py
├── dakota.rst
├── dxfsl-converter
│ ├── BspStator.png
│ ├── BspWindings.png
│ ├── airgap.png
│ ├── dxf-orig.png
│ ├── dxfsl-converter-manual.tex
│ ├── femag-model.png
│ ├── mesh.png
│ ├── semafor.png
│ ├── step1.png
│ ├── step2.png
│ └── step4.png
├── engine.rst
├── femag.rst
├── femagtools
│ ├── airgap.rst
│ ├── dxfsl.rst
│ ├── femag.rst
│ ├── machine.rst
│ ├── machine
│ │ ├── afpm.rst
│ │ ├── im.rst
│ │ ├── pm.rst
│ │ └── sm.rst
│ ├── mcv.rst
│ ├── moo.rst
│ ├── parstudy.rst
│ ├── plot.rst
│ └── poc.rst
├── forcedens.rst
├── img
│ ├── airgapinduc.png
│ ├── femagtools-dakota.drawio
│ ├── femagtools-dakota.png
│ ├── femagtools.png
│ ├── fluxdens.png
│ ├── geom.png
│ ├── loss.png
│ ├── mcv.png
│ ├── mesh.png
│ ├── mmf.png
│ ├── mmf_fft.png
│ ├── ncformat.dot
│ ├── ncformat.dot.png
│ ├── ncformat.png
│ ├── plot.png
│ ├── shortcircuit.png
│ ├── spel.png
│ ├── spoke-diagram.png
│ ├── spoke.png
│ ├── winding.png
│ └── zoneplan.png
├── index.rst
├── intro.rst
├── models.rst
├── models
│ ├── afpm.rst
│ ├── dxf.rst
│ ├── machine.rst
│ ├── magnet.rst
│ ├── material.rst
│ ├── rotor.rst
│ ├── simulation.rst
│ ├── stator.rst
│ ├── userspec.rst
│ └── windings.rst
├── ncisa.rst
├── pyplots
│ ├── example.PLT1
│ ├── forcedens.py
│ ├── pmchar.py
│ └── pmfieldweak.py
├── requirements.txt
├── sizing.rst
├── slot-parameters
│ ├── FEMAG-FSL.jrn
│ ├── FEMAG-FSL.log
│ ├── afm_rotor.svg
│ ├── afm_stator.svg
│ ├── asynRotor.svg
│ ├── magnetIron.svg
│ ├── magnetIron3.svg
│ ├── magnetIron4.svg
│ ├── magnetIron5.svg
│ ├── magnetIronV.svg
│ ├── magnetSector.svg
│ ├── magntype1.png
│ ├── magntype2.png
│ ├── magntype3.png
│ ├── magntype4.png
│ ├── magntype5.png
│ ├── magv.PROT
│ ├── rot_hsm.svg
│ ├── rotorKS2.svg
│ ├── srm.svg
│ ├── stat1.PROT
│ ├── stator1.svg
│ ├── stator4.svg
│ └── statorRotor3.svg
├── tspost.rst
├── userspec.fsl
└── windings.rst
├── examples
├── README
├── amela
│ ├── magnetfsl.mako
│ ├── pm_sym_fast_amela.py
│ └── statorfsl.mako
├── analytical-model
│ ├── fieldweakening.py
│ └── pmchar.py
├── bch-erg
│ ├── TEST_001.BCH
│ ├── TEST_002.BCH
│ ├── erg-torque-mtpa.py
│ ├── ldlq.erg
│ ├── phasor_plot.py
│ ├── read_ldq-bch-plot-torque.py
│ └── read_pm_sim-bch-plot-torque.py
├── calculation
│ ├── afpm-24-20.py
│ ├── asyn_motor.py
│ ├── cogg_calc_mcv.py
│ ├── fieldcalc.mako
│ ├── fieldcalc.py
│ ├── ld_lq_fast.py
│ ├── pm_sym_fast.py
│ ├── pm_sym_fast_linear.py
│ ├── pm_sym_fast_shortcircuit.py
│ ├── pm_sym_loss.py
│ ├── psd_psq_fast.py
│ ├── torq_calc.py
│ └── torq_calc_linear.py
├── dakota
│ └── moat.py
├── docker-zmq
│ ├── README
│ └── cogg_calc_mcv.py
├── magnetcurves
│ ├── BM38H.MC
│ ├── BM38H.MCV
│ ├── M270-35A.MC
│ ├── M270-35A.MCV
│ ├── M330-35A.MCV
│ ├── M330-50A.MC
│ ├── M330-50A.MCV
│ ├── M400_50A.MC
│ ├── M400_50A.MCV
│ ├── M800-65A.MC
│ ├── M800-65A.MCV
│ ├── Stahl37.MC
│ ├── Stahl37.MCV
│ ├── V800-50A_aniso.MC
│ └── V800-50A_aniso.MCV
├── mcv
│ ├── plot_mcv.py
│ └── write_mcv.py
├── modal-analysis
│ ├── magnetfsl.mako
│ ├── modal_analysis_me.py
│ └── statorfsl.mako
├── model-creation
│ ├── createall.py
│ ├── cust-wdg.py
│ ├── dualairgap
│ │ ├── dualairg.py
│ │ ├── magnet.mako
│ │ └── stator.mako
│ ├── dxf
│ │ ├── dxf-ipm.py
│ │ └── ipm4.dxf
│ ├── fsl-fml
│ │ ├── ipmfml.mako
│ │ ├── spokefml.mako
│ │ ├── stator1-spoke.py
│ │ ├── statorRotor3-ipm-fml.py
│ │ ├── statorfsl-ringmagnet.py
│ │ └── statorfsl.mako
│ ├── stator1-magnetIron3.py
│ ├── stator1-magnetIron4.py
│ ├── stator1-magnetIron5.py
│ ├── stator1-magnetIronV.py
│ ├── stator1-magnetSector-pm-sym-fast.py
│ ├── stator2-magnetSector.py
│ ├── stator4-magnetSector.py
│ ├── statorBG-magnetSector.py
│ └── statorRotor3-magnetIron.py
├── optimization
│ └── pmopt.py
├── parameter-ident-characteristics
│ ├── README
│ ├── afpm
│ │ ├── char.py
│ │ ├── effmap.py
│ │ ├── machine.py
│ │ └── parident.py
│ ├── eesm
│ │ ├── char.py
│ │ ├── eesm.dxf
│ │ ├── effmap.py
│ │ ├── lamination
│ │ │ ├── M270-35A.json
│ │ │ ├── M330-35A.json
│ │ │ ├── M400-50A.json
│ │ │ ├── M530-50A.json
│ │ │ └── M800-65A.json
│ │ ├── machine.py
│ │ └── parident.py
│ ├── im
│ │ ├── char.py
│ │ ├── effmap.py
│ │ ├── im.dxf
│ │ ├── machine.py
│ │ └── parident.py
│ └── vmag
│ │ ├── char.py
│ │ ├── effmap.py
│ │ ├── machine.py
│ │ ├── parident.py
│ │ └── vmag.dxf
├── parameter-variation
│ ├── parvar.py
│ ├── psidq-magntemp-list.py
│ └── torq_calc_linear.py
└── ts
│ ├── machine.py
│ ├── pmts.py
│ └── templates
│ ├── simplemagnet.mako
│ └── simplestator.mako
├── notebooks
├── 0-Introduction.ipynb
├── 1-ModelsAndFemag.ipynb
├── 2-MaterialHandling.ipynb
├── 3-Windings.ipynb
├── 4-BchFileReader.ipynb
├── 5-MachineCharacteristicsEfficiencyMaps.ipynb
├── 6-MagnetLosses.ipynb
├── 7-ParameterVariationAndOptimization.ipynb
├── 8-IronLosses.ipynb
├── 9-Eccentricity-Analysis.ipynb
├── M400-50A.MC
├── M400-50A.MCV
├── PM270L8.vtu
├── Run_amela.ipynb
├── TEST_001.BCH
├── TKS_M270-50_A.txt
├── TKS_M_330-35_A.txt
├── VTK-Postprocessing.ipynb
├── femag
│ ├── LDQ-0-90.BCH
│ ├── PM_130_L10.BATCH
│ ├── PM_270_L8_001.BATCH
│ ├── TEST_002.BCH
│ ├── ldlq.erg
│ └── xxx.BCH
├── femagtools.png
├── laminations
│ ├── M270-35A.MC
│ ├── M270-35A.MCV
│ └── TKS-M400-65A.txt
└── templates
│ ├── magnetfsl.mako
│ ├── spokefml.mako
│ └── statorfsl.mako
├── pyproject.toml
├── requirements.txt
├── src
├── femagtools
│ ├── __init__.py
│ ├── airgap.py
│ ├── amazon.py
│ ├── amela.py
│ ├── asm.py
│ ├── bch.py
│ ├── bchxml.py
│ ├── condor.py
│ ├── conductor.py
│ ├── config.py
│ ├── convert.py
│ ├── dakota.py
│ ├── dakota_femag.py
│ ├── dakotaout.py
│ ├── docker.py
│ ├── dxfsl
│ │ ├── __init__.py
│ │ ├── area.py
│ │ ├── areabuilder.py
│ │ ├── concat.py
│ │ ├── conv.py
│ │ ├── converter.py
│ │ ├── corner.py
│ │ ├── dumprenderer.py
│ │ ├── dxfparser.py
│ │ ├── femparser.py
│ │ ├── fslrenderer.py
│ │ ├── functions.py
│ │ ├── geom.py
│ │ ├── journal.py
│ │ ├── machine.py
│ │ ├── plotrenderer.py
│ │ ├── shape.py
│ │ ├── svgparser.py
│ │ └── symmetry.py
│ ├── ecloss.py
│ ├── erg.py
│ ├── femag.py
│ ├── forcedens.py
│ ├── fsl.py
│ ├── getset.py
│ ├── gmsh.py
│ ├── google.py
│ ├── grid.py
│ ├── heat_source_network.py
│ ├── hxy.py
│ ├── isa7.py
│ ├── jhb.py
│ ├── job.py
│ ├── leakinduc.py
│ ├── losscoeffs.py
│ ├── machine
│ │ ├── __init__.py
│ │ ├── afpm.py
│ │ ├── effloss.py
│ │ ├── im.py
│ │ ├── pm.py
│ │ ├── sizing.py
│ │ ├── sm.py
│ │ └── utils.py
│ ├── magnet.py
│ ├── mcv.py
│ ├── me.py
│ ├── model.py
│ ├── moo
│ │ ├── __init__.py
│ │ ├── algorithm.py
│ │ ├── population.py
│ │ ├── problem.py
│ │ └── test
│ │ │ ├── AlgorithmTest.py
│ │ │ ├── PopulationTest.py
│ │ │ └── ProblemTest.py
│ ├── moproblem.py
│ ├── multiproc.py
│ ├── mxw2msh.py
│ ├── nc.py
│ ├── netlist.py
│ ├── ntib.py
│ ├── opt.py
│ ├── parstudy.py
│ ├── plot
│ │ ├── __init__.py
│ │ ├── bch.py
│ │ ├── char.py
│ │ ├── fieldlines.py
│ │ ├── fluxdens.py
│ │ ├── forcedens.py
│ │ ├── machine.py
│ │ ├── mcv.py
│ │ ├── nc.py
│ │ ├── phasor.py
│ │ └── wdg.py
│ ├── poc.py
│ ├── semi_fea.py
│ ├── shortcircuit.py
│ ├── svgfsl
│ │ └── converter.py
│ ├── templates
│ │ ├── FE-losses.mako
│ │ ├── afm_rotor.mako
│ │ ├── afm_stator.mako
│ │ ├── airgapinduc.mako
│ │ ├── asyn_motor.mako
│ │ ├── basic_modpar.mako
│ │ ├── bertotti.mako
│ │ ├── calc_field_ts.mako
│ │ ├── calc_therm_field.mako
│ │ ├── cogg_calc.mako
│ │ ├── colorgrad.mako
│ │ ├── com_motor_sim.mako
│ │ ├── conduct-data.mako
│ │ ├── connect_models.mako
│ │ ├── cu_losses.mako
│ │ ├── dakota
│ │ │ └── moga.mako
│ │ ├── displ_stator_rotor.mako
│ │ ├── ec-rotorbar.mako
│ │ ├── fe-contr.mako
│ │ ├── fieldcalc.mako
│ │ ├── gen_hairpin_winding.mako
│ │ ├── gen_winding.mako
│ │ ├── inductances.mako
│ │ ├── ld_lq_fast.mako
│ │ ├── leak_dist_wind.mako
│ │ ├── leak_evol_wind.mako
│ │ ├── leak_tooth_wind.mako
│ │ ├── magnet-data.mako
│ │ ├── magnetFC2.mako
│ │ ├── magnetIron.mako
│ │ ├── magnetIron2.mako
│ │ ├── magnetIron3.mako
│ │ ├── magnetIron4.mako
│ │ ├── magnetIron5.mako
│ │ ├── magnetIronV.mako
│ │ ├── magnetSector.mako
│ │ ├── magnetSectorLinear.mako
│ │ ├── magnetShell.mako
│ │ ├── magnetShell2.mako
│ │ ├── mesh-airgap.mako
│ │ ├── modal_analysis.mako
│ │ ├── modified_steinmetz.mako
│ │ ├── mult_cal_fast.mako
│ │ ├── new_model.mako
│ │ ├── noloadflux-rot.mako
│ │ ├── noloadflux.mako
│ │ ├── noloadfluxdc.mako
│ │ ├── open.mako
│ │ ├── plots.mako
│ │ ├── pm_sym_f_cur.mako
│ │ ├── pm_sym_fast.mako
│ │ ├── pm_sym_loss.mako
│ │ ├── prepare_thermal.mako
│ │ ├── psd_psq_fast.mako
│ │ ├── psi-torq-rem-rot.mako
│ │ ├── psi-torq-rem.mako
│ │ ├── psi-torq-rot.mako
│ │ ├── ring.mako
│ │ ├── rot_hsm.mako
│ │ ├── rotorAsyn.mako
│ │ ├── rotorKs2.mako
│ │ ├── rotor_msh.mako
│ │ ├── rotor_winding.mako
│ │ ├── shortcircuit.mako
│ │ ├── srm.mako
│ │ ├── stator1.mako
│ │ ├── stator2.mako
│ │ ├── stator3Linear.mako
│ │ ├── stator4.mako
│ │ ├── statorBG.mako
│ │ ├── statorRing.mako
│ │ ├── statorRotor3.mako
│ │ ├── stator_msh.mako
│ │ ├── therm-dynamic.mako
│ │ ├── therm_static.mako
│ │ └── torq_calc.mako
│ ├── tks.py
│ ├── ts.py
│ ├── utils.py
│ ├── vbf.py
│ ├── vtu.py
│ ├── windings.py
│ └── zmq.py
└── tests
│ ├── __init__.py
│ ├── data
│ ├── AMELA
│ ├── AMELA.bat
│ ├── FERRIT_20gC.MCV
│ ├── IPM-130-4.dxf
│ ├── M270-50A_1000Hz_L.jhb
│ ├── Mode_001.txt
│ ├── PLT.0
│ ├── PM-4p-distleak.BATCH
│ ├── PM-with-asterisks_001.BATCH
│ ├── PMREL-4p-skewed.BATCH
│ ├── PM_270_L8_001.BATCH
│ ├── TKM270-50A-LOSS.MCV
│ ├── TKS-M400-65A.txt
│ ├── TKS_NO_20.MCV
│ ├── V800-50A_aniso.MCV
│ ├── aniso.jhb
│ ├── bag.dat
│ ├── bag2.dat
│ ├── char.BATCH
│ ├── cogging.BATCH
│ ├── convert
│ │ ├── Designer.jplot
│ │ ├── quads.ISA7
│ │ ├── quads.nas
│ │ ├── superelements.nas
│ │ ├── triangles.ISA7
│ │ └── triangles.nas
│ ├── demag-vtu
│ │ └── PM_130_L10_0000.vtu
│ ├── dq.BATCH
│ ├── hxy
│ │ └── PM270L8_011.hxy
│ ├── ldlq.erg
│ ├── ldlq_outer_rotor.BATCH
│ ├── ldq-losses.BATCH
│ ├── ldq.BATCH
│ ├── ldqlosses-2024b2.BATCH
│ ├── linearForce.BATCH
│ ├── linmot_z.BATCH
│ ├── m270_35.vbf
│ ├── magnsec.AUX7
│ ├── magnsec.ISA7
│ ├── minimal.AUX7
│ ├── minimal.ISA7
│ ├── minimal.nc
│ ├── parident
│ │ ├── bar.dat
│ │ ├── noloadbag-1.dat
│ │ ├── noloadbag-2.dat
│ │ ├── noloadbag-3.dat
│ │ ├── noloadbag-4.dat
│ │ ├── noloadbag-5.dat
│ │ └── psi-rot-mag.dat
│ ├── pm_data.nc
│ ├── pm_data
│ │ ├── pm_data_se38.json
│ │ └── pm_data_se38
│ │ │ └── EClosses.tab
│ ├── pm_sym_fast_outer_rotor.BATCH
│ ├── pmsim-9.BATCH
│ ├── pmsim-external.BATCH
│ ├── pmsim.BATCH
│ ├── psdqlosses-2024b2.BATCH
│ ├── psidpsiq.BATCH
│ ├── psidq-losses.BATCH
│ ├── rel-felosses.BATCH
│ ├── relsim.BATCH
│ ├── sctest.BATCH
│ ├── temp_model.hsn
│ ├── test.ASM
│ ├── test.poc
│ ├── test_disp_stat.ISA7
│ ├── test_disp_stat.nc
│ ├── test_func.poc
│ ├── zzz_pm_model_ts.nc
│ └── zzz_pm_model_ts_results_1
│ │ ├── zzz_pm_model_ts_0000.vtu
│ │ ├── zzz_pm_model_ts_0001.vtu
│ │ ├── zzz_pm_model_ts_0002.vtu
│ │ ├── zzz_pm_model_ts_0003.vtu
│ │ ├── zzz_pm_model_ts_0004.vtu
│ │ ├── zzz_pm_model_ts_0005.vtu
│ │ ├── zzz_pm_model_ts_0006.vtu
│ │ ├── zzz_pm_model_ts_0007.vtu
│ │ ├── zzz_pm_model_ts_0008.vtu
│ │ ├── zzz_pm_model_ts_0009.vtu
│ │ ├── zzz_pm_model_ts_0010.vtu
│ │ ├── zzz_pm_model_ts_0011.vtu
│ │ ├── zzz_pm_model_ts_0012.vtu
│ │ ├── zzz_pm_model_ts_0013.vtu
│ │ ├── zzz_pm_model_ts_0014.vtu
│ │ ├── zzz_pm_model_ts_0015.vtu
│ │ ├── zzz_pm_model_ts_0016.vtu
│ │ ├── zzz_pm_model_ts_0017.vtu
│ │ ├── zzz_pm_model_ts_0018.vtu
│ │ ├── zzz_pm_model_ts_0019.vtu
│ │ ├── zzz_pm_model_ts_0020.vtu
│ │ ├── zzz_pm_model_ts_0021.vtu
│ │ ├── zzz_pm_model_ts_0022.vtu
│ │ ├── zzz_pm_model_ts_0023.vtu
│ │ ├── zzz_pm_model_ts_0024.vtu
│ │ ├── zzz_pm_model_ts_0025.vtu
│ │ ├── zzz_pm_model_ts_0026.vtu
│ │ ├── zzz_pm_model_ts_0027.vtu
│ │ ├── zzz_pm_model_ts_0028.vtu
│ │ ├── zzz_pm_model_ts_0029.vtu
│ │ ├── zzz_pm_model_ts_0030.vtu
│ │ ├── zzz_pm_model_ts_0031.vtu
│ │ ├── zzz_pm_model_ts_0032.vtu
│ │ ├── zzz_pm_model_ts_0033.vtu
│ │ ├── zzz_pm_model_ts_0034.vtu
│ │ ├── zzz_pm_model_ts_0035.vtu
│ │ ├── zzz_pm_model_ts_0036.vtu
│ │ ├── zzz_pm_model_ts_0037.vtu
│ │ ├── zzz_pm_model_ts_0038.vtu
│ │ └── zzz_pm_model_ts_0039.vtu
│ ├── engines
│ ├── __init__.py
│ ├── config.ini
│ ├── data
│ │ └── cloud_init.txt
│ ├── test_amazon.py
│ └── test_config.py
│ ├── geom
│ ├── __init__.py
│ ├── test_functions.py
│ └── test_point_inside.py
│ ├── mcvwriter
│ ├── moo
│ ├── __init__.py
│ ├── test_algorithm.py
│ ├── test_population.py
│ └── test_problem.py
│ ├── test_afpm.py
│ ├── test_airgap_induction.py
│ ├── test_amela.py
│ ├── test_asm.py
│ ├── test_bchreader.py
│ ├── test_conductor.py
│ ├── test_convert.py
│ ├── test_dxfsl.py
│ ├── test_effloss.py
│ ├── test_erg.py
│ ├── test_femag.py
│ ├── test_forcedens.py
│ ├── test_fsl.py
│ ├── test_heat_source_network.py
│ ├── test_hxy.py
│ ├── test_im.py
│ ├── test_isa7.py
│ ├── test_jhb.py
│ ├── test_job.py
│ ├── test_losscoeffs.py
│ ├── test_machine.py
│ ├── test_magncurv.py
│ ├── test_magnet.py
│ ├── test_mcv.py
│ ├── test_mcvreader.py
│ ├── test_me.py
│ ├── test_model.py
│ ├── test_nc.py
│ ├── test_parident.py
│ ├── test_parstudy.py
│ ├── test_pocfile.py
│ ├── test_sizing.py
│ ├── test_sm.py
│ ├── test_tksreader.py
│ ├── test_ts.py
│ ├── test_vbfreader.py
│ ├── test_vtu.py
│ └── test_windings.py
└── tox.ini
/.github/workflows/python-package.yml:
--------------------------------------------------------------------------------
1 | # This workflow will install Python dependencies, run tests and lint with a variety of Python versions
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
3 |
4 | name: Python package
5 |
6 | on:
7 | push:
8 | branches: [ master, development ]
9 | pull_request:
10 | branches: [ master, development ]
11 |
12 | jobs:
13 | build:
14 |
15 | runs-on: ubuntu-latest
16 | strategy:
17 | fail-fast: false
18 | matrix:
19 | python-version: ["3.10", "3.11", "3.12"]
20 |
21 | steps:
22 | - uses: actions/checkout@v4
23 | - name: Set up Python ${{ matrix.python-version }}
24 | uses: actions/setup-python@v5
25 | with:
26 | python-version: ${{ matrix.python-version }}
27 | - name: Install dependencies
28 | run: |
29 | python -m pip install --upgrade pip
30 | python -m pip install flake8 pytest
31 | if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
32 | # - name: Lint with flake8
33 | # run: |
34 | # # stop the build if there are Python syntax errors or undefined names
35 | # flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
36 | # # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
37 | # flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
38 | - name: Test with pytest
39 | run: |
40 | python -m pytest
41 |
--------------------------------------------------------------------------------
/.github/workflows/python-publish.yml:
--------------------------------------------------------------------------------
1 | # This workflow will upload a Python Package using Twine when a release is created
2 | # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
3 |
4 | name: Upload Python Package
5 |
6 | on:
7 | release:
8 | types: [created]
9 |
10 | jobs:
11 | deploy:
12 | if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
13 | name: Build Python distribution and publish to PyPI
14 | runs-on: ubuntu-latest
15 |
16 | steps:
17 | - uses: actions/checkout@v2
18 | - name: Set up Python
19 | uses: actions/setup-python@v2
20 | with:
21 | python-version: '3.x'
22 | - name: Install dependencies
23 | run: |
24 | python -m pip install --upgrade pip
25 | pip install build
26 | - name: Build package
27 | run: python -m build
28 | - name: Publish package
29 | uses: pypa/gh-action-pypi-publish@release/v1
30 | with:
31 | user: __token__
32 | password: ${{ secrets.PYPI_API_TOKEN }}
33 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | build/
3 | *egg-info/
4 | docs/_build/
5 | dist/
6 | __pycache__/
7 | .cache/
8 | .coverage
9 |
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016-2023, Semafor Informatik & Energie AG, Basel
2 | Copyright (c) 2023-2024, Gamma Technology LLC
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions
7 | are met:
8 |
9 | Redistributions of source code must retain the above copyright notice,
10 | this list of conditions and the following disclaimer.
11 |
12 | Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
20 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26 | THE POSSIBILITY OF SUCH DAMAGE.
27 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include src/femagtools/templates/*.mako
--------------------------------------------------------------------------------
/docs/_templates/custom-class-template.rst:
--------------------------------------------------------------------------------
1 | {{ fullname | escape | underline}}
2 |
3 | .. currentmodule:: {{ module }}
4 |
5 | .. autoclass:: {{ objname }}
6 | :members:
7 | :show-inheritance:
8 | :inherited-members:
9 | :special-members: __call__, __add__, __mul__
10 |
11 | {% block methods %}
12 | {% if methods %}
13 | .. rubric:: {{ _('Methods') }}
14 |
15 | .. autosummary::
16 | :nosignatures:
17 | {% for item in methods %}
18 | {%- if not item.startswith('_') %}
19 | ~{{ name }}.{{ item }}
20 | {%- endif -%}
21 | {%- endfor %}
22 | {% endif %}
23 | {% endblock %}
24 |
25 | {% block attributes %}
26 | {% if attributes %}
27 | .. rubric:: {{ _('Attributes') }}
28 |
29 | .. autosummary::
30 | {% for item in attributes %}
31 | ~{{ name }}.{{ item }}
32 | {%- endfor %}
33 | {% endif %}
34 | {% endblock %}
35 |
--------------------------------------------------------------------------------
/docs/_templates/custom-module-template.rst:
--------------------------------------------------------------------------------
1 | {{ fullname | escape | underline}}
2 |
3 | .. automodule:: {{ fullname }}
4 |
5 | {% block attributes %}
6 | {% if attributes %}
7 | .. rubric:: Module attributes
8 |
9 | .. autosummary::
10 | :toctree:
11 | {% for item in attributes %}
12 | {{ item }}
13 | {%- endfor %}
14 | {% endif %}
15 | {% endblock %}
16 |
17 | {% block functions %}
18 | {% if functions %}
19 | .. rubric:: {{ _('Functions') }}
20 |
21 | .. autosummary::
22 | :toctree:
23 | :nosignatures:
24 | {% for item in functions %}
25 | {{ item }}
26 | {%- endfor %}
27 | {% endif %}
28 | {% endblock %}
29 |
30 | {% block classes %}
31 | {% if classes %}
32 | .. rubric:: {{ _('Classes') }}
33 |
34 | .. autosummary::
35 | :toctree:
36 | :template: custom-class-template.rst
37 | :nosignatures:
38 | {% for item in classes %}
39 | {{ item }}
40 | {%- endfor %}
41 | {% endif %}
42 | {% endblock %}
43 |
44 | {% block exceptions %}
45 | {% if exceptions %}
46 | .. rubric:: {{ _('Exceptions') }}
47 |
48 | .. autosummary::
49 | :toctree:
50 | {% for item in exceptions %}
51 | {{ item }}
52 | {%- endfor %}
53 | {% endif %}
54 | {% endblock %}
55 |
56 | {% block modules %}
57 | {% if modules %}
58 | .. autosummary::
59 | :toctree:
60 | :template: custom-module-template.rst
61 | :recursive:
62 | {% for item in modules %}
63 | {{ item }}
64 | {%- endfor %}
65 | {% endif %}
66 | {% endblock %}
67 |
--------------------------------------------------------------------------------
/docs/amela.rst:
--------------------------------------------------------------------------------
1 | Amela
2 | *****
3 |
4 | AMELA can be executed as a batch process in femagtools. Amela object will search the
5 | AMELA batch file and the FEMAG model file in the given directories. The magnet data
6 | for the loss calculation will be extracted from the FEMAG model file.
7 |
8 | * If the FEMAG model file (nc file) is located in the same directory as AMELA.
9 | Only the workdir is needed.
10 |
11 | Example::
12 |
13 | amela = Amela(workdir, dict(name='example'))
14 | r = amela()
15 | loss = r['pm_data_se38']['total_loss']
16 | print(f'loss in the superelement 38 is: {loss} W')
17 |
18 | * If the FEMAG model file (nc file) is located in a different directory as AMELA.
19 | Both the workdir (nc file) and amela_dir (AMELA.bat or AMELA.sh) need to be input.
20 |
21 | Example::
22 |
23 | amela = Amela(workdir, dict(name='example'), \
24 | amela_dir)
25 | r = amela()
26 | loss = r['pm_data_se38']['total_loss']
27 | print(f'loss in the superelement 38 is: {loss} W')
28 |
29 | The circumferential and axial segmentation are optional parameters and can be
30 | passed in the same dictionary.
31 |
32 | Example::
33 |
34 | magnet_data = dict(name='example',
35 | nseglen=3)
36 | amela = Amela(workdir, magnet_data, \
37 | amela_dir)
38 |
39 | list of all the optional parameters:
40 |
41 | ========= ===================================
42 | speed rotational speed (1/min)
43 | sigma electrical conductivity (S/m)
44 | nsegwid number of circumferential segments
45 | nseglen number of axial segments
46 | ========= ===================================
47 |
48 | The return values of the Amela object is a dictionary that contains the loss data:
49 |
50 | ========== ========================================================
51 | loss_data time dependable loss value
52 | total_loss total loss in the superelement (averaged over time step)
53 | ========== ========================================================
54 |
--------------------------------------------------------------------------------
/docs/api.rst:
--------------------------------------------------------------------------------
1 | ..
2 | DO NOT DELETE THIS FILE! It contains the all-important `.. autosummary::` directive with `:recursive:` option, without
3 | which API documentation wouldn't get extracted from docstrings by the `sphinx.ext.autosummary` engine. It is hidden
4 | (not declared in any toctree) to remove an unnecessary intermediate page; index.rst instead points directly to the
5 | package page. DO NOT REMOVE THIS FILE!
6 |
7 | .. autosummary::
8 | :toctree: _autosummary
9 | :template: custom-module-template.rst
10 | :recursive:
11 |
12 | femagtools
13 |
--------------------------------------------------------------------------------
/docs/dxfsl-converter/BspStator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/dxfsl-converter/BspStator.png
--------------------------------------------------------------------------------
/docs/dxfsl-converter/BspWindings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/dxfsl-converter/BspWindings.png
--------------------------------------------------------------------------------
/docs/dxfsl-converter/airgap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/dxfsl-converter/airgap.png
--------------------------------------------------------------------------------
/docs/dxfsl-converter/dxf-orig.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/dxfsl-converter/dxf-orig.png
--------------------------------------------------------------------------------
/docs/dxfsl-converter/femag-model.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/dxfsl-converter/femag-model.png
--------------------------------------------------------------------------------
/docs/dxfsl-converter/mesh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/dxfsl-converter/mesh.png
--------------------------------------------------------------------------------
/docs/dxfsl-converter/semafor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/dxfsl-converter/semafor.png
--------------------------------------------------------------------------------
/docs/dxfsl-converter/step1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/dxfsl-converter/step1.png
--------------------------------------------------------------------------------
/docs/dxfsl-converter/step2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/dxfsl-converter/step2.png
--------------------------------------------------------------------------------
/docs/dxfsl-converter/step4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/dxfsl-converter/step4.png
--------------------------------------------------------------------------------
/docs/femagtools/airgap.rst:
--------------------------------------------------------------------------------
1 | .. automodule:: femagtools.airgap
2 | :members:
3 |
--------------------------------------------------------------------------------
/docs/femagtools/dxfsl.rst:
--------------------------------------------------------------------------------
1 | .. automodule:: femagtools.dxfsl
2 | :members:
3 |
--------------------------------------------------------------------------------
/docs/femagtools/femag.rst:
--------------------------------------------------------------------------------
1 | .. automodule:: femagtools.femag
2 | :members: Femag, ZmqFemag
3 |
--------------------------------------------------------------------------------
/docs/femagtools/machine.rst:
--------------------------------------------------------------------------------
1 | .. automodule:: femagtools.machine
2 | :members:
3 |
4 | .. toctree::
5 | :maxdepth: 2
6 |
7 | machine/pm
8 | machine/sm
9 | machine/im
10 | machine/afpm
11 |
--------------------------------------------------------------------------------
/docs/femagtools/machine/afpm.rst:
--------------------------------------------------------------------------------
1 | .. automodule:: femagtools.machine.afpm
2 | :members:
3 |
--------------------------------------------------------------------------------
/docs/femagtools/machine/im.rst:
--------------------------------------------------------------------------------
1 | .. automodule:: femagtools.machine.im
2 | :members: parident, InductionMachine
3 |
--------------------------------------------------------------------------------
/docs/femagtools/machine/pm.rst:
--------------------------------------------------------------------------------
1 | .. automodule:: femagtools.machine.pm
2 | :members:
3 |
--------------------------------------------------------------------------------
/docs/femagtools/machine/sm.rst:
--------------------------------------------------------------------------------
1 | .. automodule:: femagtools.machine.sm
2 | :members:
3 |
--------------------------------------------------------------------------------
/docs/femagtools/mcv.rst:
--------------------------------------------------------------------------------
1 | .. automodule:: femagtools.mcv
2 | :members: MagnetizingCurve, read
3 |
--------------------------------------------------------------------------------
/docs/femagtools/moo.rst:
--------------------------------------------------------------------------------
1 | .. automodule:: femagtools.moo
2 | :members:
3 |
--------------------------------------------------------------------------------
/docs/femagtools/parstudy.rst:
--------------------------------------------------------------------------------
1 | .. automodule:: femagtools.parstudy
2 | :members:
3 |
--------------------------------------------------------------------------------
/docs/femagtools/plot.rst:
--------------------------------------------------------------------------------
1 | .. automodule:: femagtools.plot
2 | :members:
3 |
--------------------------------------------------------------------------------
/docs/femagtools/poc.rst:
--------------------------------------------------------------------------------
1 | .. automodule:: femagtools.poc
2 | :members:
3 |
--------------------------------------------------------------------------------
/docs/forcedens.rst:
--------------------------------------------------------------------------------
1 | ForceDensity
2 | ************
3 |
4 | The ForceDensity object contains the PLT file results. It has
5 | following attributes which mostly correspond to the text sections in the file:
6 |
7 | ================ =======================================================
8 | Attribute Description
9 | ================ =======================================================
10 | project Name of model file
11 | filename Name of PLT file
12 | date calculation date
13 | version FEMAG version
14 | nodes number of nodes
15 | elements number of elements
16 | quality meshing quality
17 | positions Position properties
18 | ================ =======================================================
19 |
20 | Positions
21 | =========
22 |
23 | list of dictionaries for each position
24 |
25 | ========= =======================================================
26 | position rotor position
27 | X list of angles
28 | FN list of normal component of force
29 | FT list tangential component of force
30 | Radius list of radius
31 | B_N list normal component of flux density
32 | B_T list tangential component of flux density
33 | ========= =======================================================
34 |
35 | Example::
36 |
37 | fdens = ForceDensity()
38 | fdens.read('example.PLT0')
39 | pl.title('{}, Rotor Position {}'.format(
40 | fdens.title, fdens.positions[0]['position']))
41 | pl.plot(fdens.positions[0]['X'], fdens.positions[0]['FT'])
42 |
43 | .. plot:: pyplots/forcedens.py
44 |
45 |
--------------------------------------------------------------------------------
/docs/img/airgapinduc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/img/airgapinduc.png
--------------------------------------------------------------------------------
/docs/img/femagtools-dakota.drawio:
--------------------------------------------------------------------------------
1 | 7Vpbc+MmFP41foxHd8uPsZMm2zY72abd7uaNSFhWIwsPQo6dX1+Q0AWBZa0txUm3zkwGDhfBdy6cc2BkzlfbGwzWyzvkw2hkaP52ZF6NDMM1TPqfEXY5wTHtnBDg0M9JekV4CF8hJ2qcmoY+TISOBKGIhGuR6KE4hh4RaABj9CJ2W6BI/OoaBFAiPHggkql/hz5Z8m3ZWkW/hWGwLL6sa7xlBYrOnJAsgY9eaiTzemTOMUIkL622cxgx7Apc8nG/7GktF4ZhTLoMmEE/xp6/WzxvFt5duvnjq4sudCefZgOilO+Yr5bsCggwSmMfslm0kTl7WYYEPqyBx1pfKM8pbUlWEa3ptCivii90AzGB2xqJr/IGohUkeEe78FZH5yJSiAwH8KXC3yhQXtaxtzgRcJ4H5dQVLLTAkVGj9Hi59O6/eL9+fY0/fzFuFuZu4124EibQp1LCqwiTJQpQDKLrijoTUav6/I7QmmP1DyRkx0UepASJSMJtSL7Vyt/ZVGOb1662fOassisqMd3ut3qlNopVq2FZrRiX749taq9wcVKCUuzBNoniSgpwAElbP0stBBhGgIQbcSG9c1Q3T2KpfiRLB2dPHXb1xrUTYedD71FIP13qbGmvuc7aDVXMxYYPqhupxjy2Kc7TVOl8f9I8mQyUu+kkFm3CW7OGC7gCATtxktPs4iKMojmKEM7Gmj6A7sKj9IRg9AxrLY7nwqdFP5a0PIw4mqZsSXV9KEuqBNiY/Bym9BjLaXW1nI7SHpzLlDrn5GjFxe+1lkMcHTsiTzXTPMDVrHYPcUgxg7j/U7Mz7803YnXbKmvm0QfPiICLzEp+QANpWaKrWVrDQxZyMFfT/oDaZNiCOr2dr+l01Jq3cjXbFllTGrpVsErGYSzxmsaIa1ZkPaIIRiigPSlm65rlEdpqJumwgm1hEWD3FKlZhuhfOLasPapIzRzKvZhKWJ9mlHrAyLFEjFwFRoYCI2cojApz9q5AskWQpmcHSY4Ezg+SI4Kka2dHyZBQyjyBCy8CSRJ6vXoEUPdtOFF5BFNnYgKnJ5AnDZD1c4NcnobnSVXowtk+nhyKf0pf4gdireM9gCKPI7kTw+efsqGXGINdrcOaZSaS2syN/EbzxNT5cbAvHyL1F5O8tJCvQD3anFri6LdOp5iSfcAwSSOSjFFKJLH+aN6P2QgeJorgYSj3R53cOy0WP9ZUKLMrRheV7yfj3DV4dk7U+NPOSjl4HhlORNc7e6KFgBXyaLog08+ULb2epAub/Slj6+zHRqCY1Oj5rx+1MdxG0CBrzVShNO5gTsxEYswdNVGhhzAcGXRObR6h1M+Lt3+yOop9ioyhjccSXygIRARfBDlGMWxwhJNAFAYxrXoU2syiMUhDD0SXvGEV+n6msSpui/LQA5vsqWjdLJlNhsoPMnrg02+f57ep83r7OPvr8RN5+pRs0I0iN5+ry38gji4D5+IkUQXSKrD7OEmUYKuMVfNkif1LdsHORJa7+w25B5hwnPJ8q1+r8QuhAnYGdxgHtNGljdwtUTeqj5vJe8vmK/zQNrE+mMyviYKtkISCduI9niXdGB15kWc1InrpRnCP6/mjDrXR+I5utjvUUn+3xaE+wg9W8lg+Yd6PNlVpXCGLqx9QDHXKWGtVwk7K1KYkHYO6/7XphEBOHVgoBPYtn0vU0g7DXTG0vJd4R3cMrausWZhV/hLv9Jyl5MYogNzvRTZiZMULBEehf4Ndr+muDBTwlmHMXf0kXKWMYUj2KWXPvrvHjmESvoKnbCoGPD/V6Lz2bGRfsbmo9CeVU9k1aOiBRc2nO6pHItZAjr6aR/ItDt3NBuCfhyVa81pajgdUanMES2i1eoKaHxfVO17z+l8=
--------------------------------------------------------------------------------
/docs/img/femagtools-dakota.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/img/femagtools-dakota.png
--------------------------------------------------------------------------------
/docs/img/femagtools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/img/femagtools.png
--------------------------------------------------------------------------------
/docs/img/fluxdens.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/img/fluxdens.png
--------------------------------------------------------------------------------
/docs/img/geom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/img/geom.png
--------------------------------------------------------------------------------
/docs/img/loss.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/img/loss.png
--------------------------------------------------------------------------------
/docs/img/mcv.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/img/mcv.png
--------------------------------------------------------------------------------
/docs/img/mesh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/img/mesh.png
--------------------------------------------------------------------------------
/docs/img/mmf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/img/mmf.png
--------------------------------------------------------------------------------
/docs/img/mmf_fft.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/img/mmf_fft.png
--------------------------------------------------------------------------------
/docs/img/ncformat.dot:
--------------------------------------------------------------------------------
1 | digraph g {
2 | graph [
3 | rankdir = "LR"
4 | ];
5 | node [
6 | fontsize = "16"
7 | shape = "record"
8 | ];
9 |
10 | #general [
11 | # label="FC_RADIUS | pole_pairs, poles_sim | delta_node_angle | num_slots | arm_length | pos_el_fe_induction"
12 | #];
13 |
14 | node0 [
15 | label="Node | key | x, y, r, phi | bndcnd | pernod | vpot"
16 | ];
17 |
18 | element [
19 | label="Element | key | area | center | reluc | mag | permeability() | flux_density() | demagnetization() | iron_loss_density() | mag_loss_density() | wdg_loss_density()"
20 | ];
21 |
22 | superelement [
23 | label = "SuperElement | key | length | mcvtype | condtype | curd"
24 | ];
25 |
26 | nodechain [
27 | label = "NodeChain | key | node1, nodmid, node2"
28 | ];
29 |
30 | subregion [
31 | label="Subregion | key | name | curdir | num_turns "
32 | ];
33 | winding [
34 | label="Winding | key | name | cur | flux | volt"
35 | ];
36 | nodechain -> node0
37 | element -> node0
38 | element -> superelement
39 | superelement -> element
40 | superelement -> nodechain
41 | superelement -> subregion
42 | subregion -> superelement
43 | subregion -> nodechain
44 | winding -> subregion
45 | subregion -> winding
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/docs/img/ncformat.dot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/img/ncformat.dot.png
--------------------------------------------------------------------------------
/docs/img/ncformat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/img/ncformat.png
--------------------------------------------------------------------------------
/docs/img/plot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/img/plot.png
--------------------------------------------------------------------------------
/docs/img/shortcircuit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/img/shortcircuit.png
--------------------------------------------------------------------------------
/docs/img/spel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/img/spel.png
--------------------------------------------------------------------------------
/docs/img/spoke-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/img/spoke-diagram.png
--------------------------------------------------------------------------------
/docs/img/spoke.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/img/spoke.png
--------------------------------------------------------------------------------
/docs/img/winding.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/img/winding.png
--------------------------------------------------------------------------------
/docs/img/zoneplan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/img/zoneplan.png
--------------------------------------------------------------------------------
/docs/models.rst:
--------------------------------------------------------------------------------
1 | Models
2 | ******
3 |
4 | The models are dictionaries with the properties of a material, a machine or a simulation.
5 |
6 | .. toctree::
7 | :maxdepth: 2
8 |
9 | models/machine
10 | models/material
11 | models/simulation
12 |
--------------------------------------------------------------------------------
/docs/models/afpm.rst:
--------------------------------------------------------------------------------
1 |
2 | .. _afpm:
3 |
4 | Axial Flux Machines (AFPM)
5 | ~~~~~~~~~~~~~~~~~~~~~~~~~~
6 |
7 | Axial flux machines have an airgap between stator and rotor that
8 | is aligned parallel with the axis of rotation. Three types of
9 | configurations are distinguished which are defined by the parameter afmtype:
10 |
11 | +-----------------------------+-----------------------------+-----------------------------+
12 | | S1R1 | S2R1 | S1R2 |
13 | | | | |
14 | | .. image:: ../afpm/S1R1.svg | .. image:: ../afpm/S1R1.svg | .. image:: ../afpm/S1R2.svg |
15 | | :width: 200 | :width: 200 | :width: 200 |
16 | +-----------------------------+-----------------------------+-----------------------------+
17 |
18 | For the simulation the AFPM is split into a number of slices (usually 3) each of which is treated as a linear machine.
19 |
20 | .. Note::
21 |
22 | Machine models with any of the above listed types must use the models :ref:`afm_stator`
23 | and :ref:`afm_rotor`.
24 |
--------------------------------------------------------------------------------
/docs/models/dxf.rst:
--------------------------------------------------------------------------------
1 |
2 | .. _model_creation_with_dxf:
3 |
4 | Model Creation with DXF
5 | =======================
6 |
7 | The goal of the dxfsl modules is to create a complete FE model for rotating PM and Reluctance Machines on the basis of a DXF file with
8 | as little restrictions as possible.
9 | This has the consequence that symmetries, subregions, magnets, windings, boundary conditions need to be identified.
10 |
11 | The procedure is as follows:
12 |
13 | 1. Read the DXF file and create a graph object with nodes and edges.
14 | 2. Identify the areas stator, rotor and airgap and their symmetry axis.
15 | 3. Add auxiliary lines if required by the meshing process.
16 | 4. Convert the graph object into FSL code including the identified subregions.
17 |
18 | For monitoring and trouble-shooting purposes it is possible to create plots that display the intermediate results.
19 |
20 | Example with a single dxf file motor.dxf::
21 |
22 | machine = dict(
23 | name="Motor",
24 | lfe=0.001,
25 |
26 | dxffile=dict(
27 | name='motor.dxf'
28 | ),
29 | stator=dict(
30 | mcvkey_yoke='dummy',
31 | mcvkey_shaft="dummy"
32 | ),
33 | magnet=dict(
34 | mcvkey_yoke="dummy",
35 | mcvkey_shaft="dummy"
36 | ),
37 | ...
38 |
39 | .. Note::
40 | * The parameters *poles*, *outer_diam*, *bore_diam* and *airgap* as well as *num_slots* and *num_slots_gen* will be set automatically
41 | * for additional keys of dxffile see :ref:`stator_slots_dxf`.
42 |
43 | Example with two separate dxf files for stator and rotor::
44 |
45 | machine = dict(
46 | name="Motor",
47 | lfe=0.001,
48 |
49 | stator=dict(
50 | mcvkey_yoke='dummy',
51 | dxffile=dict(
52 | name='mystator.dxf',
53 | position='out'
54 | )
55 | ),
56 | magnet=dict(
57 | mcvkey_yoke="dummy",
58 | mcvkey_shaft="dummy",
59 | dxffile=dict(
60 | name='myrotor.dxf',
61 | position='in'
62 | )
63 | ),
64 | ...
65 |
--------------------------------------------------------------------------------
/docs/models/machine.rst:
--------------------------------------------------------------------------------
1 | .. _machine-model:
2 |
3 | Machine
4 | =======
5 |
6 | Three different types of machines are supported:
7 |
8 | * RFM: Radial Flux Machines,
9 | * LM: Linear Machines,
10 | * AFPM: Axial Flux Machine.
11 |
12 | Machines have a set of basic parameters, a stator, a magnet and a winding:
13 |
14 | ============== ====================================== ======
15 | Parameter Description Unit
16 | ============== ====================================== ======
17 | name Name of machine
18 | lfe Lenght of iron m
19 | afmtype (AFPM only, see :ref:`afpm`)
20 | poles Number of poles
21 | outer_diam Outer diameter (yoke side) m
22 | bore_diam Bore diameter (airgap side) m
23 | inner_diam Inner diameter (yoke or shaft) m
24 | shaft_diam Shaft diameter m
25 | airgap airgap width m
26 | external_rotor True, False False
27 | ffactor processing factor for iron losses
28 | coord_system 1 (x/y) or 2 (r/z) 0
29 | dxffile (see :ref:`model_creation_with_dxf`)
30 | ============== ====================================== ======
31 |
32 | .. Note::
33 |
34 | depending on the type (RFM, AFM, LM) not all combinations are useful.
35 | A LM for example does not have a diameter.
36 |
37 | .. toctree::
38 | :maxdepth: 2
39 |
40 | stator
41 | windings
42 | magnet
43 | rotor
44 | dxf
45 | afpm
46 |
--------------------------------------------------------------------------------
/docs/pyplots/forcedens.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | import femagtools.forcedens
4 | import matplotlib.pylab as pl
5 |
6 | fdens = femagtools.forcedens.read('example.PLT1')
7 |
8 | f, (ax1, ax2) = pl.subplots(2, sharex=True)
9 | ax1.set_title('{}, Rotor position {}'.format(
10 | fdens.title, fdens.positions[0]['position']))
11 | ax1.plot(fdens.positions[0]['X'], [1e-3*ft
12 | for ft in fdens.positions[0]['FT']],
13 | label='F tang')
14 | ax1.plot(fdens.positions[0]['X'], [1e-3*ft
15 | for ft in fdens.positions[0]['FN']],
16 | label='F norm')
17 | ax1.legend()
18 | ax2.plot(fdens.positions[0]['X'], fdens.positions[0]['B_T'],
19 | label='B tang')
20 | ax2.plot(fdens.positions[0]['X'], fdens.positions[0]['B_N'],
21 | label='B norm')
22 | ax1.set_ylabel('kN/m²')
23 | ax2.set_ylabel('T')
24 | pl.xlabel('Position / deg')
25 | ax2.legend()
26 | pl.show()
27 |
--------------------------------------------------------------------------------
/docs/requirements.txt:
--------------------------------------------------------------------------------
1 | sphinx
2 | sphinx-autodoc-typehints
3 | nbsphinx
4 | ipython
5 | jupytext
6 | jupyter
7 | matplotlib
8 | numpy
9 | lmfit
10 | mako
11 | netCDF4
12 | networkx
13 | meshio
14 | dxfgrabber
15 | vtk
16 |
--------------------------------------------------------------------------------
/docs/slot-parameters/FEMAG-FSL.jrn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/slot-parameters/FEMAG-FSL.jrn
--------------------------------------------------------------------------------
/docs/slot-parameters/FEMAG-FSL.log:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/slot-parameters/FEMAG-FSL.log
--------------------------------------------------------------------------------
/docs/slot-parameters/magntype1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/slot-parameters/magntype1.png
--------------------------------------------------------------------------------
/docs/slot-parameters/magntype2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/slot-parameters/magntype2.png
--------------------------------------------------------------------------------
/docs/slot-parameters/magntype3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/slot-parameters/magntype3.png
--------------------------------------------------------------------------------
/docs/slot-parameters/magntype4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/slot-parameters/magntype4.png
--------------------------------------------------------------------------------
/docs/slot-parameters/magntype5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/docs/slot-parameters/magntype5.png
--------------------------------------------------------------------------------
/docs/slot-parameters/magv.PROT:
--------------------------------------------------------------------------------
1 | New File open 8:23. 5
2 |
--------------------------------------------------------------------------------
/docs/slot-parameters/stat1.PROT:
--------------------------------------------------------------------------------
1 | New File open 8:10.50
2 |
--------------------------------------------------------------------------------
/docs/tspost.rst:
--------------------------------------------------------------------------------
1 | FEMAG TS Postcalculation
2 | ************************
3 |
4 | \femagCommand{import femagtools\_ts as ftts}
5 |
6 | FEMAG-TS erstellt für die vtu-Files ein Verzeichnis mit dem Modellname und angegängtem "\_results\_x".
7 | Beim Initialisieren des ts\_vtu-Moduls muss der Modellname und das Verzeichnis der vtu-Files angegeben werden.
8 | \vspace{3mm} \\
9 | \femagParameter{modelname = "model"} \\
10 | \femagParameter{directory = modelname+"\_results\_1/"}
11 | \smalllineskip
12 | \femagCommand{vtu\_data = ftts.ts\_vtu(modelname,directory)}
13 |
--------------------------------------------------------------------------------
/docs/userspec.fsl:
--------------------------------------------------------------------------------
1 | User Specified Magnet Geometries
2 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3 |
4 | Magnet geometries not coverd by the built in models can be specified by fsl code. Here is a example:
5 |
6 | -- figure:: img/spoke.fsl
7 |
8 | example of a user specified geometry
9 |
10 | FSL Magnet::
11 |
12 | ..
13 | magnet=dict(
14 | mcvkey_yoke="dummy",
15 | spoke=dict(
16 | magn_height=0.012,
17 | shaft_diam=0.01,
18 | slot_width=0.006,
19 | magn_width=0.022
20 | )
21 | ..
22 |
23 | The following values can be referenced:
24 |
25 | ============== ========================
26 | mcvkey_yoke
27 | mcvkey_shaft
28 | agndst Node distance in airgap
29 | ============== ========================
30 |
--------------------------------------------------------------------------------
/docs/windings.rst:
--------------------------------------------------------------------------------
1 | Windings
2 | ********
3 |
4 | The windings module provides utility functions and the class
5 | Windings to define and analyze windings.
6 |
7 | Example of a symmetric 3-phase, 2-layer Winding with 54 slots and 6 pole pairs::
8 |
9 | w = femagtools.windings.Winding(dict(Q=54, p=6, m=3, l=2))
10 |
11 | assert wdg.yd == 4
12 | assert wdg.zoneplan() == (
13 | [[1, 2, -6], [4, 5, -9], [-3, 7, 8]],
14 | [[1, -5, -6], [4, -8, -9], [-2, -3, 7]])
15 |
16 | femagtools.plot.zoneplan(w)
17 |
18 | .. figure:: img/zoneplan.png
19 |
20 | Zone plan::
21 |
22 | femagtools.plot.winding(w)
23 |
24 | .. figure:: img/winding.png
25 |
26 | MMF::
27 |
28 | mmf = w.mmf()
29 | femagtools.plot.mmf(mmf)
30 | femagtools.plot.mmf_fft(mmf)
31 |
32 | .. figure:: img/mmf.png
33 |
34 | .. figure:: img/mmf_fft.png
35 |
36 | Custom Windings
37 | ===============
38 |
39 | Example of a custom defined winding::
40 |
41 | w = femagtools.windings.Winding(dict(
42 | Q=12, p=5, m=3,
43 | 1: {'N': [10, 10, 10, 10],
44 | 'layer': [1, 2, 1, 2],
45 | 'slots': [1, 1, -2, 6]},
46 | 2: {'N': [10, 10, 10, 10],
47 | 'layer': [2, 1, 2, 1],
48 | 'slots': [-4, 5, 5, -6]},
49 | 3: {'N': [10, 10, 10, 10],
50 | 'layer': [2, 1, 2, 1],
51 | 'slots': [2, -3, -3, 4]}})
52 | ))
53 |
--------------------------------------------------------------------------------
/examples/README:
--------------------------------------------------------------------------------
1 | Examples:
2 |
3 | mcv:
4 | write_mcv.py:
5 | create MC/MCV files from BH curve data
6 | plot_mcv.py:
7 | read MC file and show BH and Mue plot
8 |
9 | model-creation:
10 | various combinations of stator and magnet models
11 |
12 | bch-erg:
13 | read_ldq_bch-plot-torque.py: read BCH file from a Ld-Lq-identification
14 | and create surface plot of the torque
15 | read_pm_sim-bch-plot-torque.py: read BCH file from a PM/Rel Simulation
16 | and plot the torque vs rotor position
17 | erg-torque-mtpa.py: read ERG file and create surface plot with MTPA curve
18 |
19 | analytical-model:
20 | fieldweakening.py: calculate the frequency and current using an analytical model
21 | pmchar.py: calculate speed-torque characteristics and show plot
22 |
23 | calculation:
24 | ld_lq_fast.py: execute a ld-lq identification and calculate
25 | the frequency and current at given voltage and torque
26 | f1 222.5 Hz, I1 76.3 A, Beta -38.7 °
27 |
28 | psd_psq_fast.py: same with Psid-Psiq-Identification
29 | f1 230.0 Hz, I1 76.2 A, Beta -38.5 °
30 |
31 | cogg_calc_mcv.py: build model with magnetic curve data,
32 | execute a cogging calculation and print the fft
33 | spectrum of the torque
34 |
35 | pm_sym_fast.py:
36 | execute a PM/Rel machine simulation and print the torque and losses
37 | torq_calc.py:
38 | execute a Torq/Force calculation and print the torque and losses
39 | pm_sym_loss.py:
40 | execute a PM/Rel machine loss simulation and print losses
41 |
42 | parameter-variation:
43 | parvar.py: execute a parameter variation
44 |
45 | optimization:
46 | pmopt.py: execute a multi objective optimization
47 |
48 |
--------------------------------------------------------------------------------
/examples/amela/pm_sym_fast_amela.py:
--------------------------------------------------------------------------------
1 | import femagtools
2 | import femagtools.poc
3 | import femagtools.amela
4 | import pathlib
5 | import logging
6 | import math
7 |
8 | machine = dict(
9 | name="PM130L4",
10 | lfe=30e-3,
11 | poles=10,
12 | outer_diam=0.1,
13 | bore_diam=0.055,
14 | inner_diam=0.035,
15 | airgap=0.001,
16 | stator=dict(
17 | num_slots=12,
18 | statorfsl=dict(
19 | sw=0.005,
20 | tw=0.007,
21 | slot_h1=0.0017,
22 | slot_h2=0.002)
23 | ),
24 | magnet=dict(
25 | magnetfsl=dict(
26 | hm=3e-3,
27 | bm=11.205e-3
28 | )
29 | ),
30 |
31 | winding=dict(
32 | num_phases=3,
33 | num_wires=10,
34 | coil_span=1,
35 | num_layers=2)
36 | )
37 |
38 | logging.basicConfig(level=logging.INFO,
39 | format='%(asctime)s %(message)s')
40 |
41 | workdir = pathlib.Path().home() / 'femag'
42 | workdir.mkdir(parents=True, exist_ok=True)
43 |
44 | femag = femagtools.Femag(workdir)
45 |
46 | simulation = dict(
47 | angl_i_up=0.0,
48 | calculationMode="pm_sym_fast",
49 | wind_temp=60.0,
50 | magn_temp=20.0,
51 | current=30.0/math.sqrt(2),
52 | speed=8000/60,
53 | num_move_steps=-73,
54 | period_frac=1,
55 | plots=['field_lines', ['Babs', 0.5, 3.2, 'Babs.svg']])
56 |
57 | r = femag(machine,
58 | simulation)
59 |
60 | # amela directory can be specified separately
61 | amela_dir = '../../amela_interface'
62 | amela = femagtools.amela.Amela(workdir, dict(name=machine['name']), amela_dir)
63 | # magnet_loss is a python dict that contains the loss data
64 | magnet_loss = amela()
65 |
--------------------------------------------------------------------------------
/examples/bch-erg/erg-torque-mtpa.py:
--------------------------------------------------------------------------------
1 |
2 | import femagtools.erg
3 | import femagtools.machine
4 | import femagtools.plot
5 |
6 | import matplotlib.pylab as pl
7 |
8 | res = femagtools.erg.read('ldlq.erg')
9 |
10 | lfe = 350
11 |
12 | pm = femagtools.machine.create(res, r1=0, ls=0, lfe=lfe)
13 |
14 | femagtools.plot.mtpa(pm, res['i1'][-1])
15 | pl.show()
16 |
--------------------------------------------------------------------------------
/examples/bch-erg/ldlq.erg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/examples/bch-erg/ldlq.erg
--------------------------------------------------------------------------------
/examples/bch-erg/phasor_plot.py:
--------------------------------------------------------------------------------
1 | import femagtools
2 | import femagtools.plot
3 | import matplotlib.pylab as pl
4 |
5 | r = femagtools.read_bchfile('TEST_002.BCH')
6 |
7 | femagtools.plot.phasor(r)
8 | pl.show()
9 |
10 | #w1 = r.dqPar['npoles']*r.dqPar['speed']*math.pi
11 | #femagtools.plot.phasor(r.dqPar['up'], r.dqPar['i1'][-1],
12 | # r.dqPar['beta'][-1], 0,
13 | # w1*r.dqPar['ld'][-1],
14 | # w1*r.dqPar['lq'][-1])
15 |
--------------------------------------------------------------------------------
/examples/bch-erg/read_ldq-bch-plot-torque.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import femagtools
3 | import matplotlib.pylab as pl
4 | import femagtools.plot
5 | import femagtools.machine
6 |
7 | bch = femagtools.read_bchfile('TEST_001.BCH')
8 |
9 | beta = bch.ldq['beta']
10 | i1 = bch.ldq['i1']
11 | torque = bch.ldq['torque']
12 |
13 | pm = femagtools.machine.create(bch, r1=0, ls=0)
14 | femagtools.plot.mtpa(pm, i1[-1])
15 | pl.show()
16 |
17 |
--------------------------------------------------------------------------------
/examples/bch-erg/read_pm_sim-bch-plot-torque.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | import femagtools
4 | import matplotlib.pylab as pl
5 | import numpy as np
6 | import scipy.interpolate as ip
7 |
8 | bch = femagtools.read_bchfile('TEST_002.BCH')
9 |
10 | pos = bch.torque[-1]['angle']
11 | torque = bch.torque[-1]['torque']
12 |
13 | fig = pl.figure()
14 | ax = fig.add_subplot(111)
15 | ax.set_title(bch.project)
16 | ax.set_xlabel(u'Position [°]')
17 | ax.set_ylabel(u'Torque [Nm]')
18 | ax.plot(pos, torque, 'go', label='Calculated')
19 |
20 | k = 20
21 | posip = np.linspace(0, pos[-1], k*len(torque))
22 |
23 | f = ip.interp1d(pos, torque, kind='cubic')
24 |
25 | ax.plot(posip, f(posip), label='Interpolated')
26 | ax.plot(pos, [np.average(torque)] * len(pos), label='Average')
27 | ax.legend()
28 |
29 | pl.grid()
30 | pl.show()
31 |
--------------------------------------------------------------------------------
/examples/calculation/fieldcalc.mako:
--------------------------------------------------------------------------------
1 |
2 | -- demo template for custom calculations
3 | ---
4 | maxit=300
5 | du_u0=1e-3
6 |
7 | m.num_par_wdgs = ${model.get('num_par_wdgs', 1)}
8 | phi = ${model.get('phi')}
9 | I1 = ${model.get('current')}*math.sqrt(2.0)/m.num_par_wdgs
10 | k = 0
11 | for ii=1,3 do
12 | cur = I1*math.cos(phi/180.0*math.pi+k*math.pi/3.0)
13 | def_curr_wdg(1,cur)
14 | k = k+2
15 | end
16 |
17 | calc_field_single(maxit, reset, du_u0)
18 |
19 | post_models("induct(x)","b") -- Calculate field distribution
20 |
21 | data=io.open("bag.dat","w") -- Output in data file
22 | N = table.getn(b) -- Number of elements in array
23 | i = 1
24 | repeat
25 | data:write(string.format("%g %g %g\n",b[i],b[i+1],b[i+2]))
26 | i = i+3
27 | until i>=N
28 | io.close(data)
29 |
--------------------------------------------------------------------------------
/examples/docker-zmq/README:
--------------------------------------------------------------------------------
1 | This directory includes a cogging calculation example
2 | with FEMAG running as a service. This can be done
3 | either by starting a docker container:
4 |
5 | docker run -p 5555:5555 -p 5556:5556 --name femag -d \
6 | hub.semafor.ch/profemag/femag:9
7 |
8 | or as an operating system process with a port number argument
9 |
10 | xfemag64 -b 5555
11 |
12 |
--------------------------------------------------------------------------------
/examples/magnetcurves/BM38H.MC:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/examples/magnetcurves/BM38H.MC
--------------------------------------------------------------------------------
/examples/magnetcurves/BM38H.MCV:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/examples/magnetcurves/BM38H.MCV
--------------------------------------------------------------------------------
/examples/magnetcurves/M270-35A.MC:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/examples/magnetcurves/M270-35A.MC
--------------------------------------------------------------------------------
/examples/magnetcurves/M270-35A.MCV:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/examples/magnetcurves/M270-35A.MCV
--------------------------------------------------------------------------------
/examples/magnetcurves/M330-35A.MCV:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/examples/magnetcurves/M330-35A.MCV
--------------------------------------------------------------------------------
/examples/magnetcurves/M330-50A.MC:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/examples/magnetcurves/M330-50A.MC
--------------------------------------------------------------------------------
/examples/magnetcurves/M330-50A.MCV:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/examples/magnetcurves/M330-50A.MCV
--------------------------------------------------------------------------------
/examples/magnetcurves/M400_50A.MC:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/examples/magnetcurves/M400_50A.MC
--------------------------------------------------------------------------------
/examples/magnetcurves/M400_50A.MCV:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/examples/magnetcurves/M400_50A.MCV
--------------------------------------------------------------------------------
/examples/magnetcurves/M800-65A.MC:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/examples/magnetcurves/M800-65A.MC
--------------------------------------------------------------------------------
/examples/magnetcurves/M800-65A.MCV:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/examples/magnetcurves/M800-65A.MCV
--------------------------------------------------------------------------------
/examples/magnetcurves/Stahl37.MC:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/examples/magnetcurves/Stahl37.MC
--------------------------------------------------------------------------------
/examples/magnetcurves/Stahl37.MCV:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/examples/magnetcurves/Stahl37.MCV
--------------------------------------------------------------------------------
/examples/magnetcurves/V800-50A_aniso.MC:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/examples/magnetcurves/V800-50A_aniso.MC
--------------------------------------------------------------------------------
/examples/magnetcurves/V800-50A_aniso.MCV:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/examples/magnetcurves/V800-50A_aniso.MCV
--------------------------------------------------------------------------------
/examples/mcv/plot_mcv.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # read mc file with filename given as command line argument and
3 | # sho BH and Mue plot
4 | #
5 | # Usage:
6 | # plot.mcv.py
7 | #
8 | import matplotlib.pylab as pl
9 | import femagtools.mcv
10 | import femagtools.plot
11 | import sys
12 |
13 | mcv = femagtools.mcv.read(sys.argv[1])
14 |
15 | if mcv['mc1_type'] in (femagtools.mcv.MAGCRV, femagtools.mcv.ORIENT_CRV):
16 | ncols = 2
17 | else: # Permanent Magnet
18 | ncols = 1
19 |
20 | fig, ax = pl.subplots(nrows=1, ncols=ncols)
21 | if ncols > 1:
22 | pl.subplot(1, ncols, 1)
23 | femagtools.plot.mcv_hbj(mcv)
24 | pl.subplot(1, ncols, 2)
25 | femagtools.plot.mcv_muer(mcv)
26 | else:
27 | pl.subplot(1, ncols, 1)
28 | femagtools.plot.mcv_hbj(mcv, log=False)
29 |
30 | fig.tight_layout()
31 | fig.subplots_adjust(top=0.94)
32 | pl.show()
33 |
--------------------------------------------------------------------------------
/examples/modal-analysis/modal_analysis_me.py:
--------------------------------------------------------------------------------
1 | import femagtools
2 | import femagtools.plot
3 | import matplotlib.pyplot as plt
4 | import pathlib
5 | import logging
6 |
7 | machine = dict(
8 | name="PM130L4",
9 | lfe=30e-3,
10 | poles=10,
11 | outer_diam=0.1,
12 | bore_diam=0.055,
13 | inner_diam=0.035,
14 | airgap=0.001,
15 | stator=dict(
16 | num_slots=12,
17 | num_slots_gen=12,
18 | statorfsl=dict(
19 | sw=0.005,
20 | tw=0.007,
21 | slot_h1=0.0017,
22 | slot_h2=0.002)
23 | ),
24 | magnet=dict(
25 | magnetfsl=dict(
26 | hm=3e-3,
27 | bm=11.205e-3
28 | )
29 | ),
30 |
31 | winding=dict(
32 | num_phases=3,
33 | num_wires=10,
34 | coil_span=1,
35 | num_layers=2)
36 | )
37 |
38 | logging.basicConfig(level=logging.INFO,
39 | format='%(asctime)s %(message)s')
40 |
41 | workdir = pathlib.Path().home() / 'femag'
42 | workdir.mkdir(parents=True, exist_ok=True)
43 |
44 | # remove old results (if any)
45 | for i in workdir.glob('*_Mode_*'):
46 | i.unlink()
47 |
48 | femag = femagtools.Femag(workdir)
49 |
50 | # mechanical material can be passed in a list:
51 | # [mass_density, Young's Modulus, Possion's number]
52 | # kg/m3, Gpa, #
53 | simulation = dict(
54 | num_modes=15,
55 | calculationMode="modal_analysis",
56 | stator_material=[7700, 210, 0.3],
57 | slot_material=[5000, 1.5, 0.3],
58 | export_figure=True
59 | )
60 | # return eigenfrequency, eigenvectors
61 | r = femag(machine,
62 | simulation)
63 |
64 | if simulation['export_figure']:
65 | femagtools.plot.eigenmode(r)
66 | plt.show()
67 |
--------------------------------------------------------------------------------
/examples/model-creation/createall.py:
--------------------------------------------------------------------------------
1 | import femagtools
2 | import importlib
3 | import os
4 | import logging
5 | logging.basicConfig(level=logging.INFO,
6 | format='%(asctime)s %(message)s')
7 |
8 | models = ['statorBG-magnetSector',
9 | 'stator1-magnetIron3',
10 | 'stator1-magnetIron4',
11 | 'stator1-magnetIron5',
12 | 'stator1-magnetIronV',
13 | 'stator2-magnetSector',
14 | 'stator4-magnetSector',
15 | 'statorRotor3-magnetIron' ]
16 |
17 | logger = logging.getLogger("fslcreator")
18 | workdir = os.path.join(os.path.expanduser('~'), 'femag')
19 | try:
20 | os.mkdir(workdir)
21 | except FileExistsError:
22 | pass
23 | logger.info("Femagtools Version %s Working Dir %s",
24 | femagtools.__version__, workdir)
25 | for m in models:
26 | mod = importlib.import_module(m)
27 | logger.info("--> %s <--", m)
28 | with open(os.path.join(workdir, m+'.fsl'), 'w') as f:
29 | f.write('\n'.join(getattr(mod, 'create_fsl')()))
30 |
--------------------------------------------------------------------------------
/examples/model-creation/dualairgap/dualairg.py:
--------------------------------------------------------------------------------
1 | import femagtools
2 |
3 | machine = dict(
4 | name="DASSW",
5 | description="Dual Airgap, Single Stator Winding",
6 | lfe=0.023,
7 | poles=4,
8 | outer_diam=0.072,
9 | bore_diam=[0.025, 0.0558],
10 | inner_diam=0.015,
11 | airgap=[0.001,0.001],
12 | external_rotor=True,
13 |
14 | stator=dict(
15 | num_slots=4,
16 | stator=dict(
17 | beta_s=0.3,
18 | nodepitch1=1.0,
19 | nodepitch2=0.5)
20 | ),
21 | magnet=dict(
22 | remancenc=0.415,
23 | relperm=1.09,
24 | magnet=dict(
25 | hm=5e-3,
26 | alpha_m=0.98)
27 | ),
28 | windings=dict(
29 | num_phases=1,
30 | num_layers=2,
31 | num_wires=500,
32 | coil_span=1)
33 | )
34 |
35 | with open(machine['name'] +'.fsl', 'w') as fp:
36 | fp.write('\n'.join(femagtools.create_fsl(machine)))
37 |
--------------------------------------------------------------------------------
/examples/model-creation/dxf/dxf-ipm.py:
--------------------------------------------------------------------------------
1 | import femagtools
2 |
3 | def create_fsl():
4 | machine = dict(
5 | name="IPM4",
6 | desc="DXF Demo",
7 | lfe=0.08356,
8 | ffactor=1.1,
9 |
10 | dxffile=dict(
11 | name='ipm4.dxf'
12 | ),
13 |
14 | stator=dict(
15 | mcvkey_yoke='M270-35A',
16 | mcvkey_teeth='M270-35A'
17 | ),
18 | magnet=dict(
19 | mcvkey_yoke="M270-35A"
20 | ),
21 |
22 | windings=dict(
23 | num_phases=3,
24 | num_layers=2,
25 | num_wires=10,
26 | coil_span=8
27 | )
28 | )
29 | return femagtools.create_fsl(machine)
30 |
31 | if __name__ == '__main__':
32 | import os
33 | import logging
34 | logging.basicConfig(level=logging.INFO,
35 | format='%(asctime)s %(message)s')
36 | modelname = os.path.split(__file__)[-1].split('.')[0]
37 | logger = logging.getLogger(modelname)
38 | workdir = os.path.join(os.path.expanduser('~'), 'femag')
39 | try:
40 | os.mkdir(workdir)
41 | except FileExistsError:
42 | pass
43 | with open(os.path.join(workdir, modelname+'.fsl'), 'w') as f:
44 | f.write('\n'.join(create_fsl()))
45 |
46 | logger.info("FSL %s created",
47 | os.path.join(workdir, modelname+'.fsl'))
48 |
--------------------------------------------------------------------------------
/examples/model-creation/fsl-fml/stator1-spoke.py:
--------------------------------------------------------------------------------
1 | import femagtools
2 |
3 |
4 | def create_fsl():
5 | machine = dict(
6 | name="example2",
7 | lfe=0.1,
8 | poles=4,
9 | outer_diam=0.143,
10 | bore_diam=0.07,
11 | inner_diam=0.015,
12 | airgap=0.001,
13 |
14 | stator=dict(
15 | num_slots=12,
16 | mcvkey_yoke="dummy",
17 | rlength=1.0,
18 | stator1=dict(
19 | slot_rf1=0.057,
20 | tip_rh1=0.037,
21 | tip_rh2=0.037,
22 | tooth_width=0.011,
23 | slot_width=0.003)
24 | ),
25 |
26 | magnet=dict(
27 | mcvkey_yoke="dummy",
28 | spokefml=dict(
29 | magn_height=0.008,
30 | shaft_diam=0.01,
31 | slot_width=0.004,
32 | magn_width=0.024
33 | )
34 | ),
35 |
36 | winding=dict(
37 | num_phases=3,
38 | num_wires=100,
39 | coil_span=3.0,
40 | num_layers=1)
41 | )
42 |
43 | return femagtools.create_fsl(machine)
44 |
45 |
46 | if __name__ == '__main__':
47 | import os
48 | import logging
49 | logging.basicConfig(level=logging.INFO,
50 | format='%(asctime)s %(message)s')
51 | modelname = os.path.split(__file__)[-1].split('.')[0]
52 | logger = logging.getLogger(modelname)
53 | workdir = os.path.join(os.path.expanduser('~'), 'femag')
54 | try:
55 | os.mkdir(workdir)
56 | except FileExistsError:
57 | pass
58 |
59 | with open(os.path.join(workdir, modelname+'.fsl'), 'w') as f:
60 | f.write('\n'.join(create_fsl()))
61 |
62 | logger.info("FSL %s created",
63 | os.path.join(workdir, modelname+'.fsl'))
64 |
--------------------------------------------------------------------------------
/examples/model-creation/fsl-fml/statorfsl-ringmagnet.py:
--------------------------------------------------------------------------------
1 | import femagtools
2 |
3 |
4 | def create_fsl():
5 | machine = dict(
6 | name="statorfsl",
7 | desc="Stator FSL Demo",
8 | poles=10,
9 | outer_diam=0.1,
10 | bore_diam=0.055,
11 | inner_diam=0.033,
12 | airgap=0.001,
13 | lfe=0.15,
14 | stator=dict(
15 | num_slots=12,
16 | mcvkey_yoke='M270-35A',
17 | statorfsl=dict(
18 | yoke_height=0.008,
19 | slot_h1=0.0015,
20 | slot_h2=0.002,
21 | slot_width=0.003,
22 | tooth_width=0.007)
23 | ),
24 | magnet=dict(
25 | mcvkey_yoke="M270-35A",
26 | ring=dict(
27 | magn_height=0.005)
28 | ),
29 | winding=dict(
30 | num_phases=3,
31 | num_layers=2,
32 | num_wires=100,
33 | coil_span=1,
34 | cufilfact=0.4,
35 | culength=1.4)
36 | )
37 | return femagtools.create_fsl(machine, templatedir='templ')
38 |
39 |
40 | if __name__ == '__main__':
41 | import os
42 | import logging
43 | logging.basicConfig(level=logging.INFO,
44 | format='%(asctime)s %(message)s')
45 | modelname = os.path.split(__file__)[-1].split('.')[0]
46 | logger = logging.getLogger(modelname)
47 | workdir = os.path.join(os.path.expanduser('~'), 'femag')
48 | try:
49 | os.mkdir(workdir)
50 | except FileExistsError:
51 | pass
52 |
53 | with open(os.path.join(workdir, modelname+'.fsl'), 'w') as f:
54 | f.write('\n'.join(create_fsl()))
55 |
56 | logger.info("FSL %s created",
57 | os.path.join(workdir, modelname+'.fsl'))
58 |
--------------------------------------------------------------------------------
/examples/model-creation/stator1-magnetIron4.py:
--------------------------------------------------------------------------------
1 | import femagtools
2 |
3 | def create_fsl():
4 | machine = dict(
5 | name="PM 130 L4",
6 | lfe=0.1,
7 | poles=4,
8 | outer_diam=0.13,
9 | bore_diam=0.07,
10 | inner_diam=0.015,
11 | airgap=0.001,
12 |
13 | stator=dict(
14 | num_slots=12,
15 | stator1=dict(
16 | slot_rf1=0.057,
17 | tip_rh1=0.037,
18 | tip_rh2=0.037,
19 | tooth_width=0.009,
20 | slot_width=0.003)
21 | ),
22 |
23 | magnet=dict(
24 | magnetIron4=dict(
25 | magn_height=4e-3,
26 | magn_width=36e-3,
27 | gap_ma_iron=1e-3,
28 | air_space_h=3e-3,
29 | iron_bfe=2.5e-3,
30 | magn_di_ra=8e-3,
31 | corner_r=2e-3,
32 | air_sp_ori=0.0,
33 | condshaft_r=7e-3,
34 | magn_ori=1,
35 | magn_num=2,
36 | iron_shape=0)
37 | ),
38 |
39 | winding=dict(
40 | num_phases=3,
41 | num_wires=100,
42 | coil_span=3.0,
43 | num_layers=1)
44 | )
45 | return femagtools.create_fsl(machine)
46 |
47 |
48 | if __name__ == '__main__':
49 | import os
50 | import logging
51 | logging.basicConfig(level=logging.INFO,
52 | format='%(asctime)s %(message)s')
53 | modelname = os.path.split(__file__)[-1].split('.')[0]
54 | logger = logging.getLogger(modelname)
55 | workdir = os.path.join(os.path.expanduser('~'), 'femag')
56 |
57 | with open(os.path.join(workdir, modelname+'.fsl'), 'w') as f:
58 | f.write('\n'.join(create_fsl()))
59 |
60 | logger.info("FSL %s created",
61 | os.path.join(workdir, modelname+'.fsl'))
62 |
--------------------------------------------------------------------------------
/examples/model-creation/stator1-magnetIron5.py:
--------------------------------------------------------------------------------
1 | import femagtools
2 |
3 | def create_fsl():
4 | machine = dict(
5 | name="PM 130 L4",
6 | lfe=0.1,
7 | poles=4,
8 | outer_diam=0.13,
9 | bore_diam=0.07,
10 | inner_diam=0.015,
11 | airgap=0.001,
12 |
13 | stator=dict(
14 | num_slots=12,
15 | stator1=dict(
16 | slot_rf1=0.057,
17 | tip_rh1=0.037,
18 | tip_rh2=0.037,
19 | tooth_width=0.009,
20 | slot_width=0.003)
21 | ),
22 |
23 | magnet=dict(
24 | magnetIron5=dict(
25 | magn_height=4e-3,
26 | magn_width=36e-3,
27 | gap_ma_iron=1e-3,
28 | air_space_h=3e-3,
29 | air_space_b=3e-3,
30 | iron_bfe=2.5e-3,
31 | magn_di_ra=8e-3,
32 | corner_r=2e-3,
33 | air_sp_ori=0.0,
34 | magn_num=2,
35 | iron_shape=0)
36 | ),
37 |
38 | winding=dict(
39 | num_phases=3,
40 | num_wires=100,
41 | coil_span=3.0,
42 | num_layers=1)
43 | )
44 | return femagtools.create_fsl(machine)
45 |
46 |
47 | if __name__ == '__main__':
48 | import os
49 | import logging
50 | logging.basicConfig(level=logging.INFO,
51 | format='%(asctime)s %(message)s')
52 | modelname = os.path.split(__file__)[-1].split('.')[0]
53 | logger = logging.getLogger(modelname)
54 | workdir = os.path.join(os.path.expanduser('~'), 'femag')
55 |
56 | with open(os.path.join(workdir, modelname+'.fsl'), 'w') as f:
57 | f.write('\n'.join(create_fsl()))
58 |
59 | logger.info("FSL %s created",
60 | os.path.join(workdir, modelname+'.fsl'))
61 |
--------------------------------------------------------------------------------
/examples/model-creation/stator1-magnetIronV.py:
--------------------------------------------------------------------------------
1 | import femagtools
2 |
3 |
4 | def create_fsl():
5 | machine = dict(
6 | name="PM 130 L4",
7 | lfe=0.1,
8 | poles=4,
9 | outer_diam=0.13,
10 | bore_diam=0.07,
11 | inner_diam=0.015,
12 | airgap=0.001,
13 |
14 | stator=dict(
15 | num_slots=12,
16 | stator1=dict(
17 | slot_rf1=0.057,
18 | tip_rh1=0.037,
19 | tip_rh2=0.037,
20 | tooth_width=0.009,
21 | slot_width=0.003)
22 | ),
23 |
24 | magnet=dict(
25 | magnetIronV=dict(
26 | magn_height=4e-3,
27 | magn_width=18e-3,
28 | magn_angle=130,
29 | iron_hs=1e-3,
30 | iron_height=2e-3,
31 | gap_ma_iron=1e-3,
32 | air_triangle=1,
33 | condshaft_r=12e-3,
34 | magn_rem=1.2,
35 | magn_num=2,
36 | iron_shape=0)
37 | ),
38 |
39 | winding=dict(
40 | num_phases=3,
41 | num_wires=100,
42 | coil_span=3.0,
43 | num_layers=1)
44 | )
45 |
46 | return femagtools.create_fsl(machine)
47 |
48 |
49 | if __name__ == '__main__':
50 | import os
51 | import logging
52 | logging.basicConfig(level=logging.INFO,
53 | format='%(asctime)s %(message)s')
54 | modelname = os.path.split(__file__)[-1].split('.')[0]
55 | logger = logging.getLogger(modelname)
56 | workdir = os.path.join(os.path.expanduser('~'), 'femag')
57 |
58 | with open(os.path.join(workdir, modelname+'.fsl'), 'w') as f:
59 | f.write('\n'.join(create_fsl()))
60 |
61 | logger.info("FSL %s created",
62 | os.path.join(workdir, modelname+'.fsl'))
63 |
--------------------------------------------------------------------------------
/examples/model-creation/stator2-magnetSector.py:
--------------------------------------------------------------------------------
1 | import femagtools
2 |
3 |
4 | def create_fsl():
5 | machine = dict(
6 | name="PM 130 L4",
7 | lfe=0.1,
8 | poles=4,
9 | outer_diam=0.13,
10 | bore_diam=0.07,
11 | inner_diam=0.015,
12 | airgap=0.001,
13 |
14 | stator=dict(
15 | num_slots=12,
16 | num_slots_gen=12,
17 | stator2=dict(
18 | slot_t1=0.001,
19 | slot_t2=0.0005,
20 | slot_t3=0.0005,
21 | slot_depth=0.020,
22 | slot_width=0.009,
23 | corner_width=0.01)
24 | ),
25 |
26 | magnet=dict(
27 | magnetSector=dict(
28 | magn_num=1,
29 | magn_width_pct=0.8,
30 | magn_height=0.004,
31 | magn_shape=0.0,
32 | bridge_height=0.0,
33 | magn_type=1,
34 | condshaft_r=0.02,
35 | magn_ori=8,
36 | magn_rfe=0.0,
37 | bridge_width=0.0,
38 | magn_len=1.0)
39 | ),
40 |
41 | winding=dict(
42 | num_phases=3,
43 | num_wires=100,
44 | coil_span=3.0,
45 | num_layers=1)
46 | )
47 |
48 | return femagtools.create_fsl(machine)
49 |
50 |
51 | if __name__ == '__main__':
52 | import os
53 | import logging
54 | logging.basicConfig(level=logging.INFO,
55 | format='%(asctime)s %(message)s')
56 | modelname = os.path.split(__file__)[-1].split('.')[0]
57 | logger = logging.getLogger(modelname)
58 | workdir = os.path.join(os.path.expanduser('~'), 'femag')
59 |
60 | with open(os.path.join(workdir, modelname+'.fsl'), 'w') as f:
61 | f.write('\n'.join(create_fsl()))
62 |
63 | logger.info("FSL %s created",
64 | os.path.join(workdir, modelname+'.fsl'))
65 |
--------------------------------------------------------------------------------
/examples/model-creation/statorBG-magnetSector.py:
--------------------------------------------------------------------------------
1 | import femagtools
2 |
3 | def create_fsl():
4 | machine = dict(
5 | name="PM 130 L4",
6 | lfe=0.1,
7 | poles=4,
8 | outer_diam=0.04,
9 | bore_diam=0.022,
10 | inner_diam=0.005,
11 | airgap=0.001,
12 |
13 | stator=dict(
14 | num_slots=12,
15 | statorBG=dict(
16 | yoke_diam_ins=0.0344,
17 | slot_h1=0.0005,
18 | slot_h3=0.004,
19 | slot_width=0.00395,
20 | slot_r1=0.0008,
21 | slot_r2=0.0007,
22 | tooth_width=0.0032,
23 | middle_line=1,
24 | tip_rad=-0.03,
25 | slottooth=0)
26 | ),
27 |
28 | magnet=dict(
29 | magnetSector=dict(
30 | magn_num=1,
31 | magn_width_pct=0.8,
32 | magn_height=0.002,
33 | magn_shape=0.0,
34 | bridge_height=0.0,
35 | magn_type=1,
36 | condshaft_r=0.005,
37 | magn_ori=2,
38 | magn_rfe=0.0,
39 | bridge_width=0.0,
40 | magn_len=1.0)
41 | ),
42 |
43 | winding=dict(
44 | num_phases=3,
45 | num_wires=10,
46 | coil_span=1,
47 | num_layers=2)
48 | )
49 |
50 | return femagtools.create_fsl(machine)
51 |
52 |
53 | if __name__ == '__main__':
54 | import os
55 | import logging
56 | logging.basicConfig(level=logging.INFO,
57 | format='%(asctime)s %(message)s')
58 | modelname = os.path.split(__file__)[-1].split('.')[0]
59 | logger = logging.getLogger(modelname)
60 | workdir = os.path.join(os.path.expanduser('~'), 'femag')
61 |
62 | with open(os.path.join(workdir, modelname+'.fsl'), 'w') as f:
63 | f.write('\n'.join(create_fsl()))
64 |
65 | logger.info("FSL %s created",
66 | os.path.join(workdir, modelname+'.fsl'))
67 |
--------------------------------------------------------------------------------
/examples/model-creation/statorRotor3-magnetIron.py:
--------------------------------------------------------------------------------
1 | import femagtools
2 |
3 |
4 | def create_fsl():
5 | machine = dict(
6 | name="PM 130 L4",
7 | lfe=0.1,
8 | poles=4,
9 | outer_diam=0.13,
10 | bore_diam=0.07,
11 | inner_diam=0.015,
12 | airgap=0.001,
13 |
14 | stator=dict(
15 | num_slots=12,
16 | statorRotor3=dict(
17 | slot_height=0.02,
18 | slot_h1=0.002,
19 | slot_h2=0.004,
20 | slot_r1=0.0,
21 | slot_r2=0.0,
22 | wedge_width1=0,
23 | wedge_width2=0,
24 | middle_line=0,
25 | tooth_width=0.009,
26 | slot_top_sh=0.0,
27 | slot_width=0.003)
28 | ),
29 |
30 | magnet=dict(
31 | magnetIron=dict(
32 | magn_width=39e-3,
33 | magn_height=4e-3,
34 | gap_ma_iron=0.0,
35 | air_triangle=1,
36 | iron_height=0.8e-3,
37 | magn_rem=1.2,
38 | condshaft_r=5e-3,
39 | bridge_height=0,
40 | magn_ori=1,
41 | bridge_width=0.0,
42 | iron_shape=33.5e-3)
43 | ),
44 |
45 | winding=dict(
46 | num_phases=3,
47 | num_wires=100,
48 | coil_span=3.0,
49 | num_layers=1)
50 | )
51 |
52 | return femagtools.create_fsl(machine)
53 |
54 |
55 | if __name__ == '__main__':
56 | import os
57 | import logging
58 | logging.basicConfig(level=logging.INFO,
59 | format='%(asctime)s %(message)s')
60 | modelname = os.path.split(__file__)[-1].split('.')[0]
61 | logger = logging.getLogger(modelname)
62 | workdir = os.path.join(os.path.expanduser('~'), 'femag')
63 |
64 | with open(os.path.join(workdir, modelname+'.fsl'), 'w') as f:
65 | f.write('\n'.join(create_fsl()))
66 |
67 | logger.info("FSL %s created",
68 | os.path.join(workdir, modelname+'.fsl'))
69 |
--------------------------------------------------------------------------------
/examples/parameter-ident-characteristics/README:
--------------------------------------------------------------------------------
1 |
2 | Parameter Identification, Characteristics and Efficiency Map
3 | ============================================================
4 |
5 | For machine types: vmag (PMSM), eesm (WFSM), im (Induction Machine)
6 |
7 | To run the examples change to the machine type directory and
8 | follow these steps:
9 |
10 | 1. Create EEC parameters from machine (dqpars.json):
11 |
12 | $ python parident.py
13 |
14 | 2. Create speed characteristics plot (speedchar.pdf)
15 |
16 | $ python char.py
17 |
18 | 3. Create efficiency map (effmap.pdf)
19 |
20 | $ python effmap.py
21 |
--------------------------------------------------------------------------------
/examples/parameter-ident-characteristics/afpm/char.py:
--------------------------------------------------------------------------------
1 | """
2 | Speed characteristics of Axialflux PM
3 | Ronald Tanner
4 | """
5 | import logging
6 | import json
7 | import numpy as np
8 | import matplotlib.pyplot as plt
9 | import femagtools.plot
10 | import femagtools.machine
11 | from femagtools.machine.utils import betai1
12 |
13 |
14 | if __name__ == '__main__':
15 | logging.basicConfig(level=logging.INFO,
16 | format='%(asctime)s %(message)s')
17 |
18 | with open('dqpar.json') as fp:
19 | dqpars = json.load(fp)
20 |
21 | temp = [90, 90]
22 | pm = femagtools.machine.create_from_eecpars(temp, dqpars)
23 |
24 | i1max = 80
25 | Udc = 800
26 | u1max = round(0.9*Udc/np.sqrt(2)/np.sqrt(3))
27 |
28 | rep = []
29 | w1, T = pm.w1_imax_umax(i1max, u1max)
30 | iq, id = pm.iqd_tmech(T, w1/2/np.pi/pm.p)
31 | uq, ud = pm.uqd(w1, iq, id)
32 | u1 = np.linalg.norm((ud, uq))/np.sqrt(2)
33 | beta, i1 = betai1(iq, id)
34 | rep.append((w1/2/np.pi*60/pm.p, T, i1, beta/np.pi*180, u1))
35 |
36 | nmax = 4000/60
37 | w1 = 2*np.pi*nmax*pm.p
38 | iq, id, tq = pm.iqd_imax_umax(i1max, w1, u1max, T)
39 | beta, i1 = betai1(iq, id)
40 | uq, ud = pm.uqd(w1, iq, id)
41 | u1 = np.linalg.norm((ud, uq))/np.sqrt(2)
42 | rep.append((w1/2/np.pi*60/pm.p, tq, i1, beta/np.pi*180, u1))
43 |
44 | print("""
45 | n/rpm T/Nm I1/A beta/° U1/V
46 | -------------------------------
47 | """)
48 | for r in rep:
49 | print(f" {r[0]:5.0f} {r[1]:5.1f} {r[2]:5.1f} {r[3]:5.1f} {r[4]:5.1f}")
50 | print()
51 |
52 | r = pm.characteristics(T, nmax, u1max)
53 | fig = femagtools.plot.characteristics(r)
54 | fig.savefig('speedchar.pdf')
55 |
--------------------------------------------------------------------------------
/examples/parameter-ident-characteristics/afpm/effmap.py:
--------------------------------------------------------------------------------
1 | """
2 | Create Efficiency Map of a Axialflux PM
3 | Ronald Tanner
4 | """
5 | import logging
6 | import json
7 | import numpy as np
8 | import matplotlib.pyplot as plt
9 | import femagtools.plot
10 | import femagtools.machine
11 | import femagtools.machine.effloss
12 |
13 | if __name__ == '__main__':
14 | logging.basicConfig(level=logging.INFO,
15 | format='%(asctime)s %(message)s')
16 |
17 | with open('dqpar.json') as fp:
18 | dqpars = json.load(fp)
19 |
20 | temp = [90, 90]
21 | m = femagtools.machine.create_from_eecpars(temp, dqpars)
22 |
23 | i1max = 80
24 | Udc = 800
25 | u1max = round(0.9*Udc/np.sqrt(2)/np.sqrt(3))
26 | w1, T = m.w1_imax_umax(i1max, u1max)
27 |
28 | nmax = 4000/60
29 | fig, ax = plt.subplots(figsize=(12,12))
30 | ax.set_title('')
31 | effmap = femagtools.machine.effloss.efficiency_losses_map(
32 | m, u1max, T, [], nmax)
33 | contf = femagtools.plot.efficiency_map(effmap, ax, title='')
34 | fig.tight_layout()
35 | fig.savefig('effmap.pdf')
36 |
--------------------------------------------------------------------------------
/examples/parameter-ident-characteristics/afpm/parident.py:
--------------------------------------------------------------------------------
1 | # Axial Flux Machine (AFM) demo
2 | #
3 | from machine import machine
4 |
5 | if __name__ == '__main__':
6 | import logging
7 | import pathlib
8 | import json
9 | from femagtools.machine.afpm import parident
10 | from femagtools.multiproc import Engine
11 |
12 | logging.basicConfig(level=logging.INFO,
13 | format='%(asctime)s %(message)s')
14 |
15 | workdir = pathlib.Path('dqpar')
16 | workdir.mkdir(exist_ok=True)
17 |
18 | engine = Engine()
19 | temp = [60, 90]
20 | r = parident(workdir, engine, temp, machine,
21 | magnetizingCurves='',
22 | magnetMat=[], condMat=[],
23 | speed=4000/60,
24 | beta_min=-90,
25 | num_beta_steps=4, num_cur_steps=3)
26 | with open('dqpar.json', 'w') as fp:
27 | json.dump(r, fp)
28 |
--------------------------------------------------------------------------------
/examples/parameter-ident-characteristics/eesm/char.py:
--------------------------------------------------------------------------------
1 | """
2 | speed characteristics of EESM
3 | Ronald Tanner
4 | """
5 | import logging
6 | import numpy as np
7 | import json
8 | import femagtools.plot
9 | import femagtools.machine
10 | from femagtools.machine.utils import betai1
11 | import matplotlib.pyplot as plt
12 |
13 | logging.basicConfig(level=logging.INFO,
14 | format='%(asctime)s %(message)s')
15 |
16 | with open('eecpars.json') as fp:
17 | eecpars = json.load(fp)
18 |
19 | temp = [90, 90]
20 | eesm = femagtools.machine.create_from_eecpars(temp, eecpars)
21 |
22 | i1max = 275
23 | udc = 400
24 | u1max = 0.9*udc/np.sqrt(3)/np.sqrt(2)
25 | w1, Tmax = eesm.w1_imax_umax(i1max, u1max)
26 |
27 | speed = w1/2/np.pi/eesm.p
28 | iq, id, iex = eesm.iqd_tmech(Tmax, speed)
29 | uq, ud = eesm.uqd(w1, iq, id, iex)
30 | u1 = np.linalg.norm((ud, uq))/np.sqrt(2)
31 |
32 | print("""
33 | n/rpm T/Nm I1/A Iex/A U1/V
34 | -----------------------------------
35 | """)
36 | for n, T in zip([2000/60, speed, 6000/60, 10000/60],
37 | [120, Tmax, 100, 60]):
38 | w1 = 2*np.pi*n*eesm.p
39 | iq, id, iex, tqx = eesm.iqd_tmech_umax(T, w1, u1max)
40 | beta, i1 = betai1(iq, id)
41 | uq, ud = eesm.uqd(w1, iq, id, iex)
42 | u1 = np.linalg.norm((ud, uq))/np.sqrt(2)
43 | print(f" {60*n:6.0f} {T:5.1f} {i1:5.1f} {iex:4.1f} {u1:5.1f}")
44 | print()
45 | nmax = 12000/60
46 | r = eesm.characteristics(Tmax, nmax, u1max)
47 | fig = femagtools.plot.characteristics(r)
48 | fig.savefig('speedchar.pdf')
49 |
--------------------------------------------------------------------------------
/examples/parameter-ident-characteristics/eesm/effmap.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import json
3 | import matplotlib.pyplot as plt
4 | import numpy as np
5 | import pathlib
6 | import femagtools.plot
7 | import femagtools.machine
8 | import femagtools.machine.effloss
9 |
10 |
11 | logging.basicConfig(level=logging.INFO,
12 | format='%(asctime)s %(message)s')
13 |
14 | with open('eecpars.json') as fp:
15 | dqpars = json.load(fp)
16 |
17 | temp = [90, 90]
18 | m = femagtools.machine.create_from_eecpars(temp, dqpars)
19 |
20 | i1max = 275
21 | udc = 400
22 | u1max = 0.9*udc/np.sqrt(3)/np.sqrt(2)
23 | w1, Tmax = m.w1_imax_umax(i1max, u1max)
24 | nmax = 12000/60
25 |
26 | effmap = femagtools.machine.effloss.efficiency_losses_map(
27 | m, u1max, Tmax, [], nmax, num_proc=4)
28 |
29 | fig, ax = plt.subplots(figsize=(12,12))
30 | ax.set_title('')
31 | contf = femagtools.plot.efficiency_map(effmap, ax, title='')
32 | fig.tight_layout()
33 |
34 | fig.savefig('effmap.pdf')
35 |
--------------------------------------------------------------------------------
/examples/parameter-ident-characteristics/eesm/lamination/M270-35A.json:
--------------------------------------------------------------------------------
1 | {"name": "M270-35A",
2 | "desc": "for demo purposes only",
3 | "ctype": 1,
4 | "fillfac": 1.0,
5 | "fo": 50.0,
6 | "Bo": 1.5,
7 | "ch": 0.0,
8 | "ch_freq": 1.0,
9 | "cw": 3.0,
10 | "cw_freq": 1.45,
11 | "b_coeff": 1.85,
12 | "rho": 7.65,
13 | "fe_sat_mag": 2.15,
14 | "curve": [{
15 | "hi": [0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0,
16 | 70.0, 80.0, 90.0, 100.0, 200.0, 300.0, 400.0,
17 | 500.0, 600.0, 700.0, 800.0, 900.0, 1000.0, 2000.0,
18 | 3000.0, 4000.0, 5000.0, 6000.0, 7000.0, 8000.0,
19 | 9000.0, 10000.0, 20000.0, 30000.0, 40000.0, 50000.0,
20 | 60000.0, 70000.0, 80000.0, 90000.0, 100000.0, 200000.0,
21 | 500000.0],
22 | "bi": [0.0, 0.10174000263214111, 0.2011370062828064,
23 | 0.29615598917007446, 0.38528698682785034, 0.4676159918308258,
24 | 0.5427759885787964, 0.6108270287513733, 0.6721190214157104,
25 | 0.7271659970283508, 0.7765570282936096, 1.0706720352172852,
26 | 1.19780695438385, 1.2671619653701782, 1.3110430240631104,
27 | 1.3416420221328735, 1.3644800186157227, 1.382403016090393,
28 | 1.3970229625701904, 1.4093159437179565, 1.4805519580841064,
29 | 1.5231300592422485, 1.558081030845642, 1.589516043663025,
30 | 1.6187200546264648, 1.646183967590332, 1.672116994857788,
31 | 1.6966110467910767, 1.7197109460830688, 1.8815209865570068,
32 | 1.9547009468078613, 1.9886070489883423, 2.0083839893341064,
33 | 2.023422956466675, 2.0368940830230713, 2.049838066101074,
34 | 2.062593936920166, 2.0752789974212646, 2.2013800144195557,
35 | 2.5786280632019043],
36 | "angle": 0.0}]
37 | }
38 |
--------------------------------------------------------------------------------
/examples/parameter-ident-characteristics/eesm/lamination/M330-35A.json:
--------------------------------------------------------------------------------
1 | {"name": "M330-35A",
2 | "desc": "for demo purposes only",
3 | "ctype": 1,
4 | "fillfac": 1.0,
5 | "fo": 50.0,
6 | "Bo": 1.5,
7 | "ch": 0.0,
8 | "ch_freq": 0.0,
9 | "cw": 3.25,
10 | "cw_freq": 1.44,
11 | "b_coeff": 1.82,
12 | "rho": 7.65,
13 | "fe_sat_mag": 1.85325241,
14 | "curve": [{
15 | "hi": [0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0,
16 | 80.0, 90.0, 100.0, 200.0, 300.0, 400.0, 500.0,
17 | 600.0, 700.0, 800.0, 900.0, 1000.0, 2000.0,
18 | 3000.0, 4000.0, 5000.0, 6000.0, 7000.0, 8000.0,
19 | 9000.0, 10000.0, 20000.0, 30000.0, 40000.0,
20 | 50000.0, 60000.0, 70000.0, 80000.0, 90000.0,
21 | 100000.0, 200000.0, 500000.0],
22 | "bi": [0.0, 0.07722435891628265, 0.15325646102428436,
23 | 0.2270091325044632, 0.29758957028388977, 0.3643421232700348,
24 | 0.4268576204776764, 0.4849509298801422, 0.5386165380477905,
25 | 0.5879855155944824, 0.6332783699035645, 0.9237410426139832,
26 | 1.0597389936447144, 1.1359325647354126, 1.1846184730529785,
27 | 1.2186754941940308, 1.2440956830978394, 1.264011025428772,
28 | 1.280210256576538, 1.293785810470581, 1.3710200786590576,
29 | 1.4157471656799316, 1.4518680572509766, 1.484082818031311,
30 | 1.5138740539550781, 1.5418201684951782, 1.5681712627410889,
31 | 1.5930418968200684, 1.6164904832839966, 1.7810873985290527,
32 | 1.8559958934783936, 1.8907582759857178, 1.9109141826629639,
33 | 1.9261165857315063, 1.9396638870239258, 1.9526455402374268,
34 | 1.9654245376586914, 1.9781244993209839, 2.1042869091033936,
35 | 2.4815709590911865],
36 | "angle": 0.0}]}
37 |
--------------------------------------------------------------------------------
/examples/parameter-ident-characteristics/eesm/lamination/M400-50A.json:
--------------------------------------------------------------------------------
1 | {"name": "M400-50A",
2 | "desc": "for demo purposes only",
3 | "ctype": 1,
4 | "fillfac": 1.0,
5 | "fo": 50.0,
6 | "Bo": 1.5,
7 | "ch": 4.0,
8 | "ch_freq": 1.0,
9 | "cw": 0.8,
10 | "cw_freq": 1.0,
11 | "b_coeff": 1.0,
12 | "rho": 7.65,
13 | "fe_sat_mag": 2.15,
14 | "curve": [{
15 | "hi": [0.0, 28.0, 50.0, 62.0, 70.0, 76.0, 85.0, 94.0,
16 | 105.0, 119.0, 138.0, 152.0, 165.0, 187.0, 209.0,
17 | 255.0, 300.0, 400.0, 540.0, 900.0, 1330.0, 3300.0,
18 | 6600.0, 11600.0, 18800.0, 29000.0, 46000.0, 98000.0,
19 | 175000.0, 254000.0],
20 | "bi": [0.0, 0.1, 0.2,
21 | 0.3, 0.4, 0.5,
22 | 0.6, 0.7, 0.8,
23 | 0.9, 1.0, 1.05,
24 | 1.1, 1.15, 1.2,
25 | 1.25, 1.3, 1.35, 1.4,
26 | 1.45, 1.5, 1.6, 1.7,
27 | 1.8, 1.9, 2.0, 2.1,
28 | 2.2, 2.3, 2.4],
29 | "angle": 0.0}]}
30 |
--------------------------------------------------------------------------------
/examples/parameter-ident-characteristics/eesm/lamination/M530-50A.json:
--------------------------------------------------------------------------------
1 | {"name": "M530_50A",
2 | "desc": "for demo purposes only",
3 | "ctype": 1,
4 | "fillfac": 1.0,
5 | "fo": 50.0,
6 | "Bo": 1.5,
7 | "ch": 0.0,
8 | "ch_freq": 1,
9 | "cw": 3.0,
10 | "cw_freq": 1.45,
11 | "rho": 7.54,
12 | "fe_sat_mag": 2.0,
13 | "curve": [{
14 | "hi": [0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0,
15 | 80.0, 90.0, 100.0, 200.0, 300.0, 400.0, 500.0,
16 | 600.0, 700.0, 800.0, 900.0, 1000.0, 2000.0, 3000.0,
17 | 4000.0, 5000.0, 6000.0, 7000.0, 8000.0, 9000.0,
18 | 10000.0, 20000.0, 30000.0, 40000.0, 50000.0, 60000.0,
19 | 70000.0, 80000.0, 90000.0, 100000.0, 200000.0, 500000.0],
20 | "bi": [0.0, 0.060812, 0.121207,
21 | 0.180751, 0.239071, 0.295837, 0.350773, 0.403664,
22 | 0.454353, 0.502741, 0.548778, 0.890678, 1.082872,
23 | 1.198796, 1.274945, 1.328566, 1.368405,
24 | 1.399268, 1.423987, 1.444324, 1.54869795,
25 | 1.597807, 1.632702, 1.661675, 1.687457,
26 | 1.711187, 1.733412, 1.754415, 1.774355, 1.926546,
27 | 2.012048, 2.058275, 2.085491, 2.104347, 2.11966,
28 | 2.133483, 2.146672, 2.1595831, 2.2862, 2.6637],
29 | "angle": 0.0}]}
30 |
--------------------------------------------------------------------------------
/examples/parameter-ident-characteristics/eesm/lamination/M800-65A.json:
--------------------------------------------------------------------------------
1 | {"name": "M800-65A",
2 | "desc": "for demo purposes only",
3 | "ctype": 1,
4 | "fillfac": 1.0,
5 | "fo": 50.0,
6 | "Bo": 1.5,
7 | "ch": 0.0,
8 | "ch_freq": 1,
9 | "cw": 3,
10 | "cw_freq": 1.45,
11 | "b_coeff": 1.0,
12 | "rho": 7.65,
13 | "curve": [
14 | {"hi": [0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0,
15 | 80.0, 90.0, 100.0, 200.0, 300.0, 400.0, 500.0,
16 | 600.0, 700.0, 800.0, 900.0, 1000.0, 2000.0,
17 | 3000.0, 4000.0, 5000.0, 6000.0, 7000.0, 8000.0,
18 | 9000.0, 10000.0, 20000.0, 30000.0, 40000.0, 50000.0,
19 | 60000.0, 70000.0, 80000.0, 90000.0, 100000.0, 200000.0,
20 | 500000.0],
21 | "bi": [0.0, 0.056587, 0.112851, 0.168478, 0.223178, 0.2766881, 0.328783,
22 | 0.379275, 0.428017, 0.474904, 0.519865, 0.866555, 1.072363,
23 | 1.2, 1.285121, 1.345424, 1.39036, 1.4252, 1.453078, 1.475977,
24 | 1.591754, 1.644, 1.68, 1.71, 1.735142, 1.758716, 1.78075, 1.80158,
25 | 1.82141, 1.9778, 2.0735, 2.129, 2.162473, 2.184886, 2.2021,
26 | 2.2169, 2.2306, 2.243757, 2.37071, 2.7482841],
27 | "angle": 0.0}]
28 | }
29 |
--------------------------------------------------------------------------------
/examples/parameter-ident-characteristics/eesm/parident.py:
--------------------------------------------------------------------------------
1 | """
2 | Parameter Identification of a EESM
3 | Ronald Tanner
4 | """
5 | import logging
6 | import json
7 | import pathlib
8 | from machine import machine, laminations, condMat
9 | import femagtools.machine.sm
10 | import femagtools.mcv
11 | from femagtools.multiproc import Engine
12 |
13 | if __name__ == '__main__':
14 | logging.basicConfig(level=logging.INFO,
15 | format='%(asctime)s %(message)s')
16 |
17 | workdir = pathlib.Path('work')
18 | workdir.mkdir(exist_ok=True)
19 |
20 | engine = Engine()
21 | r = femagtools.machine.sm.parident(workdir, engine, machine,
22 | magnetizingCurves=laminations,
23 | condMat=condMat)
24 | r['zeta1'] = 0.3 # skin effect factor of winding resistance
25 | with open('eecpars.json', 'w') as fp:
26 | json.dump(r, fp)
27 |
--------------------------------------------------------------------------------
/examples/parameter-ident-characteristics/im/char.py:
--------------------------------------------------------------------------------
1 | """
2 | speed characteristics of IM
3 | Ronald Tanner
4 | """
5 | import logging
6 | import json
7 | import numpy as np
8 | import matplotlib.pyplot as plt
9 | import femagtools.plot
10 | import femagtools.machine
11 |
12 | logging.basicConfig(level=logging.INFO,
13 | format='%(asctime)s %(message)s')
14 |
15 |
16 | with open('impar.json') as fp:
17 | impars = json.load(fp)
18 |
19 | temp = [90, 80]
20 | im = femagtools.machine.create_from_eecpars(temp, impars)
21 |
22 | T = 57
23 | u1max = 230
24 | nmax = 100
25 |
26 | print("""
27 | n/rpm T/Nm I1/A U1/V cosphi f/Hz
28 | -----------------------------------------
29 | """)
30 |
31 | wm = im.wmfweak(u1max, im.psiref, T)
32 | for tq, n in zip([T, 32.9, 20],
33 | [wm/2/np.pi, 1450/60, 2900/60]):
34 | r = im.operating_point(T, n, u1max)
35 | print(f" {n*60:6.0f} {tq:5.1f} {r['i1']:5.1f} {r['u1']:4.1f} {r['cosphi']:6.3f} {r['f1']:5.1f}")
36 | print()
37 |
38 | r = im.characteristics(T, nmax, u1max)
39 | fig = femagtools.plot.characteristics(r)
40 | fig.savefig('speedchar.pdf')
41 |
--------------------------------------------------------------------------------
/examples/parameter-ident-characteristics/im/effmap.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import json
3 | import matplotlib.pyplot as plt
4 | import femagtools.plot
5 | import femagtools.machine
6 | import femagtools.machine.effloss
7 |
8 |
9 | logging.basicConfig(level=logging.INFO,
10 | format='%(asctime)s %(message)s')
11 |
12 |
13 | with open('impar.json') as fp:
14 | impars = json.load(fp)
15 |
16 | temp = [90, 80]
17 | T = 57
18 | u1max = 230
19 | nmax = 100
20 |
21 | r = femagtools.machine.effloss.efficiency_losses_map(
22 | impars, u1max, T, temp, nmax, npoints=(50, 40))
23 |
24 | fig, axs = plt.subplots(figsize=(12,10))
25 | femagtools.plot.efficiency_map(r, ax=axs, title='')
26 | fig.tight_layout()
27 | fig.savefig('effmap.pdf')
28 |
29 | # plt.show()
30 |
31 | fig, axs = plt.subplots()
32 | femagtools.plot.losses_map(r, ax=axs)
33 | fig.savefig('lossmap.pdf')
34 | # plt.show()
35 |
--------------------------------------------------------------------------------
/examples/parameter-ident-characteristics/im/parident.py:
--------------------------------------------------------------------------------
1 | """
2 | Parameter Identification of a IM
3 | Ronald Tanner
4 | """
5 | import logging
6 | import femagtools.machine
7 | import femagtools.mcv
8 | import pathlib
9 | import json
10 | from machine import machine, magnetizingCurves, condMat
11 | from femagtools.multiproc import Engine
12 |
13 | if __name__ == '__main__':
14 | logging.basicConfig(level=logging.INFO,
15 | format='%(asctime)s %(message)s')
16 |
17 | workdir = pathlib.Path('work')
18 | workdir.mkdir(exist_ok=True)
19 |
20 | engine = Engine()
21 | f1 = 50
22 | u1 = 400
23 | wdgcon = 'star'
24 | results = femagtools.machine.im.parident(
25 | workdir, engine, f1, u1, wdgcon,
26 | machine=machine,
27 | magnetizingCurves=magnetizingCurves,
28 | condMat=condMat)
29 | with open('impar.json', 'w') as fp:
30 | json.dump(results, fp)
31 |
--------------------------------------------------------------------------------
/examples/parameter-ident-characteristics/vmag/char.py:
--------------------------------------------------------------------------------
1 | """
2 | Speed characteristics of VMAG PM
3 | Ronald Tanner
4 | """
5 | import logging
6 | import json
7 | import numpy as np
8 | import matplotlib.pyplot as plt
9 | import femagtools.plot
10 | import femagtools.machine
11 | from femagtools.machine.utils import betai1
12 |
13 |
14 | if __name__ == '__main__':
15 | logging.basicConfig(level=logging.INFO,
16 | format='%(asctime)s %(message)s')
17 |
18 | with open('dqpar.json') as fp:
19 | dqpars = json.load(fp)
20 |
21 | temp = [90, 90]
22 | pm = femagtools.machine.create_from_eecpars(temp, dqpars)
23 |
24 | i1max = 250
25 | Udc = 420
26 | u1max = round(0.9*Udc/np.sqrt(2)/np.sqrt(3))
27 |
28 | rep = []
29 | w1, T = pm.w1_imax_umax(i1max, u1max)
30 | iq, id = pm.iqd_tmech(T, w1/2/np.pi/pm.p)
31 | uq, ud = pm.uqd(w1, iq, id)
32 | u1 = np.linalg.norm((ud, uq))/np.sqrt(2)
33 | beta, i1 = betai1(iq, id)
34 | rep.append((w1/2/np.pi*60/pm.p, T, i1, beta/np.pi*180, u1))
35 |
36 | nmax = 6000/60
37 | w1 = 2*np.pi*nmax*pm.p
38 | iq, id, tq = pm.iqd_imax_umax(i1max, w1, u1max, T)
39 | beta, i1 = betai1(iq, id)
40 | uq, ud = pm.uqd(w1, iq, id)
41 | u1 = np.linalg.norm((ud, uq))/np.sqrt(2)
42 | rep.append((w1/2/np.pi*60/pm.p, tq, i1, beta/np.pi*180, u1))
43 |
44 | print("""
45 | n/rpm T/Nm I1/A beta/° U1/V
46 | -------------------------------
47 | """)
48 | for r in rep:
49 | print(f" {r[0]:5.0f} {r[1]:5.1f} {r[2]:5.1f} {r[3]:5.1f} {r[4]:5.1f}")
50 | print()
51 |
52 | r = pm.characteristics(T, nmax, u1max)
53 | fig = femagtools.plot.characteristics(r)
54 | fig.savefig('speedchar.pdf')
55 |
--------------------------------------------------------------------------------
/examples/parameter-ident-characteristics/vmag/effmap.py:
--------------------------------------------------------------------------------
1 | """
2 | Create Efficiency Map of a VMAG PM
3 | Ronald Tanner
4 | """
5 | import logging
6 | import json
7 | import numpy as np
8 | import matplotlib.pyplot as plt
9 | import femagtools.plot
10 | import femagtools.machine
11 | import femagtools.machine.effloss
12 |
13 | if __name__ == '__main__':
14 | logging.basicConfig(level=logging.INFO,
15 | format='%(asctime)s %(message)s')
16 |
17 | with open('dqpar.json') as fp:
18 | dqpars = json.load(fp)
19 |
20 | temp = [90, 90]
21 | m = femagtools.machine.create_from_eecpars(temp, dqpars)
22 |
23 | i1max = 250
24 | Udc = 420
25 | u1max = round(0.9*Udc/np.sqrt(2)/np.sqrt(3))
26 | w1, T = m.w1_imax_umax(i1max, u1max)
27 |
28 | nmax = 6000/60
29 | fig, ax = plt.subplots(figsize=(12,12))
30 | ax.set_title('')
31 | effmap = femagtools.machine.effloss.efficiency_losses_map(
32 | m, u1max, T, [], nmax)
33 | contf = femagtools.plot.efficiency_map(effmap, ax, title='')
34 | fig.tight_layout()
35 | fig.savefig('effmap.pdf')
36 |
--------------------------------------------------------------------------------
/examples/parameter-ident-characteristics/vmag/parident.py:
--------------------------------------------------------------------------------
1 | """
2 | DQ Parameter Identification of a VMAG PM
3 | Ronald Tanner
4 | """
5 | import logging
6 | import pathlib
7 | import json
8 | import femagtools.machine
9 | import femagtools.mcv
10 | from machine import machine, laminations, magnetMat, condMat
11 | from femagtools.multiproc import Engine
12 |
13 | if __name__ == '__main__':
14 | logging.basicConfig(level=logging.INFO,
15 | format='%(asctime)s %(message)s')
16 |
17 | workdir = pathlib.Path('work')
18 | workdir.mkdir(exist_ok=True)
19 |
20 | engine = Engine()
21 | dqpars = femagtools.machine.pm.parident(
22 | workdir, engine, temp=[60, 90],
23 | i1_max=300,
24 | machine=machine,
25 | magnetizingCurves=laminations,
26 | magnetMat=magnetMat, condMat=condMat)
27 | dqpars['zeta1'] = 0.3 # skin effect factor of winding resistance
28 | with open('dqpar.json', 'w') as fp:
29 | json.dump(dqpars, fp)
30 |
--------------------------------------------------------------------------------
/examples/ts/machine.py:
--------------------------------------------------------------------------------
1 | machine = {
2 | 'name': "PM 130 L4",
3 | 'lfe': 0.05,
4 | 'poles': 4,
5 | 'outer_diam': 0.11,
6 | 'bore_diam': 0.057,
7 | 'inner_diam': 0.015,
8 | 'airgap': 0.0015,
9 | 'stator': {
10 | 'num_slots': 6,
11 | 'mcvkey_yoke': 'M400_50A',
12 | 'rlength': 1,
13 | 'simplestator': {
14 | 'slot_height': 16e-3,
15 | 'slot_width': 16e-3,
16 | },
17 | },
18 | 'magnet': {
19 | 'mcvkey_yoke': 'Stahl37',
20 | 'rlength': 1,
21 | 'simplemagnet': {
22 | 'magnet_height': 5e-3,
23 | 'magnet_width': 30e-3
24 | }
25 | },
26 | 'winding': {
27 | 'num_phases': 3,
28 | 'num_wires': 10,
29 | 'coil_span': 3,
30 | 'num_layers': 1
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/examples/ts/pmts.py:
--------------------------------------------------------------------------------
1 | # FEMAG DC PM/Rel-Simulation
2 | #
3 | import logging
4 | import femagtools
5 | import pathlib
6 | from machine import machine
7 | import matplotlib.pyplot as plt
8 |
9 | simulation = dict(
10 | calculationMode="calc_field_ts",
11 | src_ampl=10.0,
12 | src_type='current',
13 | freq=100.0,
14 | speed=50.0,
15 | sim_time=[0.01, 0.02],
16 | store_time=0.01/20,
17 | dtmin=0.01/20,
18 | dtmax=0.01/20,
19 | resmin=1e-5,
20 | resmax=1e-4,
21 | vtu_movie=True)
22 |
23 | logging.basicConfig(level=logging.INFO,
24 | format='%(asctime)s %(message)s')
25 | modelname = machine['name'].replace(' ', '_')
26 | workdir = pathlib.Path.home() / 'femag'
27 |
28 | femag = femagtools.Femag(workdir, magnetizingCurves='../magnetcurves',
29 | cmd='tsfemag64',
30 | templatedirs=['templates'])
31 |
32 | r = femag(machine, simulation)
33 |
34 | fig, axs = plt.subplots(2, 2, sharex=True)
35 | axs[0, 0].plot(r['time'], r['I1'])
36 | axs[0, 0].plot(r['time'], r['I2'])
37 | axs[0, 0].plot(r['time'], r['I3'])
38 | axs[0, 0].set_title('Current / A')
39 | axs[0, 0].grid()
40 | axs[0, 1].plot(r['time'], r['U1'])
41 | axs[0, 1].plot(r['time'], r['U2'])
42 | axs[0, 1].plot(r['time'], r['U3'])
43 | axs[0, 1].set_title('Voltage / V')
44 | axs[0, 1].grid()
45 | axs[1, 0].plot(r['time'], r['angle'])
46 | axs[1, 0].set_title('Angle / °')
47 | axs[1, 0].grid()
48 | axs[1, 0].set_xlabel('Time / s')
49 | axs[1, 1].plot(r['time'], r['torque'])
50 | axs[1, 1].set_title('Torque / Nm')
51 | axs[1, 1].grid()
52 | axs[1, 1].set_xlabel('Time / s')
53 | fig.tight_layout()
54 | plt.show()
55 |
--------------------------------------------------------------------------------
/notebooks/M400-50A.MC:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/notebooks/M400-50A.MC
--------------------------------------------------------------------------------
/notebooks/M400-50A.MCV:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/notebooks/M400-50A.MCV
--------------------------------------------------------------------------------
/notebooks/femag/ldlq.erg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/notebooks/femag/ldlq.erg
--------------------------------------------------------------------------------
/notebooks/femagtools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/notebooks/femagtools.png
--------------------------------------------------------------------------------
/notebooks/laminations/M270-35A.MC:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/notebooks/laminations/M270-35A.MC
--------------------------------------------------------------------------------
/notebooks/laminations/M270-35A.MCV:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/notebooks/laminations/M270-35A.MCV
--------------------------------------------------------------------------------
/notebooks/laminations/TKS-M400-65A.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/notebooks/laminations/TKS-M400-65A.txt
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["setuptools>=61.0"]
3 | build-backend = "setuptools.build_meta"
4 |
5 | [project]
6 | name = "femagtools"
7 | authors = [
8 | {name = "Ronald Tanner", email = "tar@semafor.ch"},
9 | {name = "Dapu Zhang", email = "dzhang@gtisoft.com"},
10 | {name = "Beat Holm", email = "hob@semafor.ch"},
11 | {name = "Günther Amsler", email = "amg@semafor.ch"},
12 | {name = "Nicolas Mauchle", email = "mau@semafor.ch"}
13 | ]
14 | description = "Python API for FEMAG"
15 | readme = "README.md"
16 | requires-python = ">=3.7"
17 | license = {file = "LICENSE"}
18 | classifiers = [
19 | "Programming Language :: Python :: 3",
20 | "Intended Audience :: Science/Research",
21 | "License :: OSI Approved :: BSD License",
22 | "Topic :: Scientific/Engineering"
23 | ]
24 | dependencies = [
25 | 'numpy',
26 | 'scipy',
27 | 'mako',
28 | 'six',
29 | 'lmfit',
30 | 'netCDF4>=1.6.5', # >=1.6.5 to mitigate CVE-2023-38545
31 | ]
32 | dynamic = ["version"]
33 |
34 | [project.optional-dependencies]
35 | rdp = ['rdp'] # reduce nodes in dxf/svg fsl conversion
36 | dxfsl = ['dxfgrabber', 'networkx']
37 | svgfsl = ['dxfgrabber', 'networkx', 'lxml']
38 | mplot = ['matplotlib']
39 | meshio = ['meshio']
40 | vtk = ['vtk']
41 | zmq = ['pyzmq']
42 | test = ['pytest']
43 | all = ['femagtools[dxfsl,svgfsl,mplot,meshio,vtk,zmq,test]'] # add new dependency groups here as well
44 |
45 | [project.scripts]
46 | femagtools-plot = "femagtools.plot.bch:main"
47 | femagtools-convert = "femagtools.convert:main"
48 | femagtools-bchxml = "femagtools.bchxml:main"
49 | femagtools-dxfsl = "femagtools.dxfsl.conv:main"
50 | femagtools-svgfsl = "femagtools.svgfsl.converter:main"
51 |
52 | [tool.setuptools.dynamic]
53 | version = {attr = "femagtools.__version__"}
54 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | numpy
2 | scipy
3 | mako
4 | networkx
5 | vtk
6 | meshio
7 | matplotlib
8 | lxml
9 | netCDF4
10 | lmfit
11 | dxfgrabber
12 | rdp
13 |
--------------------------------------------------------------------------------
/src/femagtools/__init__.py:
--------------------------------------------------------------------------------
1 | """Python API for FEMAG
2 |
3 | """
4 | __title__ = 'femagtools'
5 | __version__ = '1.8.15'
6 | __author__ = 'Ronald Tanner'
7 | __license__ = 'BSD'
8 | __copyright__ = 'Copyright 2023-2025 Gamma Technology'
9 |
10 | from .asm import read
11 | from .bch import Reader
12 | from .model import MachineModel
13 | from .fsl import Builder
14 | from .magnet import Magnet
15 | from .femag import Femag, ZmqFemag
16 | from .conductor import Conductor
17 |
18 |
19 | def read_bchfile(filename):
20 | """Read BCH/BATCH results from file *filename*."""
21 | import io
22 | bchresults = Reader()
23 | with io.open(filename, encoding='latin1', errors='ignore') as f:
24 | bchresults.read(f.readlines())
25 | return bchresults
26 |
27 |
28 | def create_fsl(machine,
29 | operatingconditions={},
30 | magnetmat=[],
31 | condMat=[],
32 | templatedirs=[]):
33 | """create FSL command list from model and operating parameters
34 |
35 | Args:
36 | machine: dict with parameters (model)
37 | operatingConditions: dict with parameters (simulation)
38 | magnetmat: list fo dict with parameters (magnet material)
39 | templatedir: additional template directory
40 | """
41 | model = MachineModel(machine)
42 |
43 | builder = Builder(templatedirs)
44 | magnets = []
45 | if magnetmat:
46 | magnets = Magnet(magnetmat)
47 | if condMat:
48 | if not isinstance(condMat, Conductor):
49 | condMat = Conductor(condMat)
50 |
51 | if operatingconditions:
52 | return builder.create(model, operatingconditions, magnets)
53 | return builder.create_model(model,
54 | condMat=condMat,
55 | magnets=magnets) + ['save_model("cont")']
56 |
--------------------------------------------------------------------------------
/src/femagtools/conductor.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | femagtools.conductor
4 | ~~~~~~~~~~~~~~~~~~~~
5 |
6 | Creating and managing coonductor material
7 |
8 |
9 | """
10 |
11 |
12 | class Conductor:
13 | def __init__(self, clist=[]):
14 | """initialize this object from a list of conductor objects"""
15 | self.conductors = {}
16 | for c in clist:
17 | if 'id' in c:
18 | self.conductors[str(c['id'])] = c
19 | elif 'name' in c:
20 | self.conductors[c['name']] = c
21 |
22 | def find(self, id):
23 | """find conductor by id or name"""
24 | try:
25 | return self.conductors[id]
26 | except ValueError:
27 | pass # not found
28 | except KeyError:
29 | pass
30 | return self.find_by_name(id)
31 |
32 | def find_by_name(self, name):
33 | """find conductor by name"""
34 | for k in self.conductors.keys():
35 | if self.conductors[k]['name'] == name:
36 | return self.conductors[k]
37 | # not found
38 | return None
39 |
40 | def __str__(self):
41 | return str([self.conductors[c]
42 | for c in self.conductors])
43 |
--------------------------------------------------------------------------------
/src/femagtools/dxfsl/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | femagtools.dxfsl
3 | ~~~~~~~~~~~~~~~~
4 |
5 | convert dxf to fsl
6 |
7 |
8 | """
9 |
--------------------------------------------------------------------------------
/src/femagtools/dxfsl/corner.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | femagtools.dxfsl.corner
4 | ~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 | Authors: Ronald Tanner, beat Holm
7 | """
8 | from __future__ import print_function
9 | import numpy as np
10 | import logging
11 | from .functions import distance
12 |
13 | logger = logging.getLogger('femagtools.corner')
14 |
15 |
16 | class Corner(object):
17 | def __init__(self, center, p):
18 | self.__p = p
19 | self.__dist = distance(center, p)
20 | self.__keep = False
21 | self.is_new_point = False
22 |
23 | def point(self):
24 | return self.__p
25 |
26 | def is_equal(self, p, rtol=1e-04, atol=1e-04):
27 | return (np.isclose(self.__p[0], p[0], rtol=rtol, atol=atol) and
28 | np.isclose(self.__p[1], p[1], rtol=rtol, atol=atol))
29 |
30 | def is_same_corner(self, c):
31 | return self.is_equal(c.__p)
32 |
33 | def set_keep_node(self):
34 | self.__keep = True
35 |
36 | def keep_node(self):
37 | return self.__keep
38 |
39 | def node(self):
40 | return self.__p
41 |
42 | def __eq__(self, c):
43 | return (np.isclose(self.__p[0], c.__p[0], rtol=1e-04, atol=1e-04) and
44 | np.isclose(self.__p[1], c.__p[1], rtol=1e-04, atol=1e-04))
45 |
46 | def __lt__(self, c):
47 | if self.__dist < c.__dist:
48 | return 1
49 | else:
50 | return 0
51 |
52 | def __str__(self):
53 | return "Corner: p={}, keep={}".format(self.__p, self.__keep)
54 |
--------------------------------------------------------------------------------
/src/femagtools/dxfsl/dumprenderer.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | dxfsl
4 | ~~~~~
5 |
6 | renders geometry
7 |
8 |
9 | """
10 | import numpy as np
11 | import logging
12 |
13 | logger = logging.getLogger(__name__)
14 |
15 |
16 | #############################
17 | # DumpRenderer #
18 | #############################
19 |
20 | class DumpRenderer(object):
21 | def __init__(self, name):
22 | self.model = name
23 |
24 | def circle(self, center, radius):
25 | self.content.append(u'Crcle({}, {}, {})'.format(center[0],
26 | center[1],
27 | radius))
28 |
29 | def arc(self, startangle, endangle, center, radius):
30 | p1 = (center[0] + radius*np.cos(startangle),
31 | center[1] + radius*np.sin(startangle))
32 | p2 = (center[0] + radius*np.cos(endangle),
33 | center[1] + radius*np.sin(endangle))
34 | self.content.append(
35 | u"Arc({}, {}, {}, {}, {}, {})".format(
36 | p1[0], p1[1], p2[0], p2[1],
37 | center[0], center[1]))
38 |
39 | def line(self, p1, p2):
40 | self.content.append(
41 | u"Line({}, {}, {}, {})".format(
42 | p1[0], p1[1], p2[0], p2[1]))
43 |
44 | def render(self, geom):
45 | '''create file with elements'''
46 | incl_bnd = True
47 | self.content = []
48 | handled = set()
49 |
50 | # collect all areas
51 | for i, area in enumerate(geom.areas(incl_bnd)):
52 | self.content.append('-- {}'.format(i))
53 | for e in area:
54 | if e not in handled:
55 | e.render(self)
56 | handled.add(e)
57 | self.content.append('--')
58 | geom.remove_areas(incl_bnd)
59 | # and all remaining edges and circles
60 | for circle in geom.circles():
61 | circle.render(self)
62 |
63 | for e1, e2, attr in geom.g.edges(data=True):
64 | attr['object'].render(self)
65 |
66 | return self.content
67 |
--------------------------------------------------------------------------------
/src/femagtools/erg.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | femagtools.erg
4 | ~~~~~~~~~~~~~~
5 |
6 | Reading ERG files
7 |
8 |
9 |
10 | """
11 | import re
12 | import numpy as np
13 | import io
14 |
15 |
16 | head_pattern = re.compile(r'([A-Za-z_0-9]+)')
17 | unit_pattern = re.compile(r'\[([A-Za-z/0-9 ]+)\]')
18 | num_pattern = re.compile(r'([+-]?\d+(?:\.\d+)?(?:[eE][+-]\d+)?)\s*')
19 |
20 |
21 | def read(filename):
22 | """read ERG file
23 | returns dict with array values
24 | """
25 | head = []
26 | units = []
27 | m = []
28 | with io.open(filename,
29 | errors='ignore') as f:
30 | for l in f:
31 | if head and units:
32 | n = num_pattern.findall(l)
33 | if n:
34 | m.append([float(x) for x in n])
35 | elif head:
36 | u = unit_pattern.findall(l)
37 | if u:
38 | units = u
39 | elif l.find('|') > 0:
40 | h = head_pattern.findall(l)
41 | if h:
42 | head = h
43 |
44 | m = np.array(m).T
45 | ncols = len(set(m[1]))
46 | i1 = np.reshape(m[0], (-1, ncols)).T[0]
47 | nrows = len(i1)
48 |
49 | res = {k: (np.reshape(x, (nrows, ncols)).T[::-1]).tolist()
50 | for k, x in zip(head[2:], m[2:])}
51 | res['i1'] = i1.tolist()
52 | res['beta'] = m[1][:ncols][::-1].tolist()
53 | return res
54 |
--------------------------------------------------------------------------------
/src/femagtools/grid.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | femagtools.grid
4 | ~~~~~~~~~~~~~~~
5 |
6 | Parameter range calculation using Grid sampling
7 |
8 |
9 |
10 | """
11 | import logging
12 | import femagtools.parstudy
13 | import numpy as np
14 |
15 | logger = logging.getLogger(__name__)
16 |
17 |
18 | def create_parameter_range(domain):
19 | """returns the transposed array of the combined domain values"""
20 | L = [len(d) for d in domain]
21 | LS = np.prod(L)
22 | s = []
23 | e = 1
24 | for d in domain:
25 | LS = LS//len(d)
26 | s.append(np.repeat(d*LS, e))
27 | e = e*L[0]
28 | L = L[1:]
29 | return np.array(s).T
30 |
31 |
32 | class Grid(femagtools.parstudy.ParameterStudy):
33 | """Grid Parameter variation calculation"""
34 |
35 | def __init__(self, workdir,
36 | magnetizingCurves=None, magnets=None, condMat=[],
37 | result_func=None): # tasktype='Task'):
38 | super().__init__(workdir,
39 | magnetizingCurves, magnets, condMat,
40 | result_func)
41 |
42 | def _get_names_and_range(self, dvars, num_samples):
43 | if isinstance(dvars, dict):
44 | dvarnames = dvars['columns']
45 | par_range = dvars['list']
46 | domain = [r for r in zip(*par_range)]
47 | else:
48 | dvarnames = [d['name'] for d in dvars]
49 | domain = [list(np.linspace(d['bounds'][0],
50 | d['bounds'][1],
51 | d['steps'])) if 'bounds' in d else d['values']
52 | for d in dvars]
53 |
54 | par_range = create_parameter_range(domain)
55 | return dvarnames, domain, par_range
56 |
--------------------------------------------------------------------------------
/src/femagtools/jhb.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | #
4 | import sys
5 | import os
6 | import femagtools.mcv as mcv
7 | import logging
8 |
9 | logger = logging.getLogger(__name__)
10 |
11 |
12 | class Reader(object):
13 | def __init__(self, filename):
14 | self.mc1_type = mcv.MAGCRV
15 |
16 | with open(filename) as f:
17 | self.name = os.path.splitext(
18 | os.path.basename(f.readline().strip()))[0]
19 | r = f.readline().split()
20 | self.angle = [float(a) for a in r[1:]]
21 | self.curve = [dict(hi=[], bi=[])
22 | for i in range(int(r[0])-1)]
23 | for l in f:
24 | r = l.split()
25 | if len(r) > 1:
26 | bh = [float(x.replace(',', '.')) for x in r]
27 | if bh[1] > 0:
28 | b = bh[0]
29 | for i, h in enumerate(bh[1:]):
30 | self.curve[i]['hi'].append(h)
31 | self.curve[i]['bi'].append(b)
32 | if len(self.curve) > 1:
33 | self.mc1_type = mcv.ORIENT_CRV
34 | logger.info("JHB %s curves %d sizes %s", self.name, len(self.curve),
35 | [len(c['bi']) for c in self.curve])
36 |
37 | def __getitem__(self, index):
38 | return self.__getattribute__(index)
39 |
40 | def getValues(self):
41 | """return values as mcv dict"""
42 | return {
43 | 'name': self.name,
44 | 'ctype': self.mc1_type,
45 | 'curve': self.curve}
46 |
47 |
48 | def read(filename):
49 | """read JHB File and return mc dict"""
50 | jhb = Reader(filename)
51 | return jhb.getValues()
52 |
53 |
54 | if __name__ == "__main__":
55 | if len(sys.argv) == 2:
56 | filename = sys.argv[1]
57 | else:
58 | filename = sys.stdin.readline().strip()
59 |
60 | jhb = Reader(filename)
61 | print(jhb.getValues())
62 |
--------------------------------------------------------------------------------
/src/femagtools/leakinduc.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | '''Calculate leakage inductances'''
3 | import numpy as np
4 | import logging
5 |
6 | logger = logging.getLogger(__name__)
7 |
8 |
9 | def end_wdg_leak_ind_round_wires(l_ew, p, q, m, y, taup, w1, layers, num_par_wdgs, slot_height):
10 | '''returns end winding leakage inductance per phase per end winding side (DE or NDE)'''
11 | mue0 = 4*np.pi*1e-7
12 | if layers == 2:
13 | lambda_ew = 0.34*q*(1 - 2*y*taup/(np.pi*l_ew*m*q))
14 | if layers == 1:
15 | lambda_ew = q*(0.67 - 0.43*(taup + slot_height*np.pi/(2*p))/l_ew)
16 | L_ew = mue0*2/(p*q)*(w1/num_par_wdgs)**2*l_ew*lambda_ew
17 | return L_ew
18 |
19 |
20 | def end_wdg_leak_ind_hairpin_wires(): #TODO
21 | L_ew = 0
22 | return L_ew
23 |
24 |
25 | def harm_leak_ind(E_fft, order_fft, freq, Ia): # needs to be validated
26 | '''returns harmonic leakage inductance per phase'''
27 | L_harm = []
28 | for ii in range(1, len(order_fft)): # skip 1st order
29 | L_harm.append(E_fft[ii] / Ia / (2*np.pi*freq*order_fft[ii]))
30 |
31 | return sum(L_harm)
32 |
33 |
--------------------------------------------------------------------------------
/src/femagtools/magnet.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | femagtools.magnet
4 | ~~~~~~~~~~~~~~~~~
5 |
6 | Creating and managing magnet material
7 |
8 |
9 |
10 | """
11 |
12 |
13 | class Magnet:
14 | def __init__(self, mlist=[]):
15 | """initialize this object from a list of magnet objects"""
16 | self.magnets = {}
17 | for m in mlist:
18 | if 'id' in m:
19 | self.magnets[str(m['id'])] = m
20 | elif 'name' in m:
21 | self.magnets[m['name']] = m
22 |
23 | def find(self, id):
24 | """find magnet by id or name"""
25 | try:
26 | return self.magnets[id]
27 | except ValueError:
28 | pass # not found
29 | except KeyError:
30 | pass
31 | return self.find_by_name(id)
32 |
33 | def find_by_name(self, name):
34 | """find magnet by name"""
35 | try:
36 | for k in self.magnets.keys():
37 | if self.magnets[k]['name'] == name:
38 | return self.magnets[k]
39 | # not found
40 | except KeyError:
41 | pass
42 | return {}
43 |
44 | def __str__(self):
45 | return str([self.magnets[m]
46 | for m in self.magnets])
47 |
--------------------------------------------------------------------------------
/src/femagtools/me.py:
--------------------------------------------------------------------------------
1 | """
2 | Postprocessing FEMAG-ME results
3 | """
4 | __author__ = 'dapu zhang'
5 |
6 | import re
7 | import numpy as np
8 | import matplotlib.pyplot as plt
9 | import logging
10 |
11 | # set logging
12 | logger = logging.getLogger(__name__)
13 |
14 | def get_eigenvectors(filelist, psfiles):
15 | """return eigenfrequency and eigenvectors (raw data and psfiles)"""
16 | eigenvecs = {}
17 | eigenfreq = []
18 | ps_data = []
19 | temp = []
20 | temp_arr = []
21 | read_fig = False
22 |
23 | if len(psfiles) > 0: read_fig = True
24 | if len(filelist) == 0: return []
25 |
26 | for k, kk in zip(filelist, range(len(filelist))):
27 | # read ps file
28 | if read_fig: ps_data.append(plt.imread(psfiles[kk]))
29 | eigenvecs[str(kk)] = {}
30 | with open(k, 'r') as f:
31 | data = f.read().split('\n')
32 | eigenval = float(re.split(r'\s+', data[0].strip())[2])
33 | eigenfreq.append(eigenval/2/np.pi)
34 |
35 | for i in range(len(data[1:-1])):
36 | for j in data[2+i].strip().split(' '):
37 | if j != '':
38 | temp.append(float(j))
39 |
40 | temp_arr = np.array(temp).reshape(-1, 5)
41 | idx_collect = []
42 | # remove the index, at which the dof equals zero
43 | for c in range(temp_arr.shape[0]):
44 | if np.abs(temp_arr[c, 1]) < 1e-15 and \
45 | np.abs(temp_arr[c, 2]) < 1e-15:
46 | idx_collect.append(c)
47 | # prepare the data from the further calculation
48 | temp_arr = np.delete(temp_arr, np.array(idx_collect), axis=0)
49 | temp_arr = np.insert(temp_arr, 3, np.zeros((temp_arr.shape[0], )), axis=1)
50 | temp_arr = np.hstack((temp_arr, np.zeros((temp_arr.shape[0], 1))))
51 | eigenvecs[str(kk)].update({'eigenvecs': temp_arr[:, 1:4]})
52 | # return node position
53 | if kk == 0: eigenvecs.update({'node_pos': temp_arr[:, 4::]})
54 |
55 | return [ps_data, eigenfreq, eigenvecs]
56 |
--------------------------------------------------------------------------------
/src/femagtools/moo/__init__.py:
--------------------------------------------------------------------------------
1 |
2 | """
3 | Multi objective Optimizer
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~
5 |
6 |
7 |
8 |
9 |
10 | """
11 | from .population import Population, Individual
12 | from .problem import Problem
13 | from .algorithm import Nsga2
14 |
--------------------------------------------------------------------------------
/src/femagtools/moo/test/ProblemTest.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | import unittest
4 | import sys
5 | sys.path.insert(0, '../..')
6 | from moo.problem import Problem
7 |
8 |
9 | class ProblemTest(unittest.TestCase):
10 | def test_compare_fc(self):
11 | prob = Problem(0, 0, 2)
12 | f1 = (0, 0)
13 | f2 = (1, 1)
14 | c1 = []
15 | c2 = []
16 | self.assertTrue(prob.compare_fc(f1, c1, f2, c2))
17 | self.assertFalse(prob.compare_fc(f2, c2, f1, c1))
18 | self.assertFalse(prob.compare_fc(f2, c2, f2, c2))
19 |
20 | if __name__ == '__main__':
21 | unittest.main()
22 |
--------------------------------------------------------------------------------
/src/femagtools/plot/__init__.py:
--------------------------------------------------------------------------------
1 | """Creating plots
2 |
3 | """
4 | from .machine import machine
5 | from .fluxdens import airgap, airgap_fft
6 | from .bch import torque, torque_fft, force, force_fft, \
7 | fluxdens_surface, winding_current, winding_flux, \
8 | voltage, voltage_fft, \
9 | pmrelsim, multcal, fasttorque, cogging, transientsc, \
10 | transientsc_demag, i1beta_torque, i1beta_ld, i1beta_lq, i1beta_psid, \
11 | i1beta_psiq, i1beta_psim, i1beta_up, \
12 | idq_ld, idq_lq, idq_psid, idq_psim, idq_psiq, idq_torque
13 | from .char import mtpa, mtpv, characteristics, efficiency_map, losses_map
14 | from .forcedens import forcedens, forcedens_surface, forcedens_contour, forcedens_fft
15 | from .nc import spel, mesh, demag, demag_pos, \
16 | flux_density, flux_density_eccentricity, \
17 | airgap_flux_density_pos, loss_density
18 | from .mcv import mcv_hbj, mcv_muer, felosses
19 | from .phasor import i1beta_phasor, iqd_phasor, phasor
20 | from .wdg import mmf, mmf_fft, zoneplan, winding_factors, winding, currdist
21 | from .fieldlines import fieldlines
22 |
--------------------------------------------------------------------------------
/src/femagtools/plot/fieldlines.py:
--------------------------------------------------------------------------------
1 | import re
2 | import xml.etree.ElementTree as ET
3 | import matplotlib.pyplot as plt
4 | import numpy as np
5 | import matplotlib.lines as mpl
6 |
7 | rgbpat = re.compile(r'rgb\((\d+),(\d+),(\d+)\)')
8 |
9 | def fieldlines(svgfilename, ax=0):
10 | """plot fieldlines from svg file"""
11 | lines = []
12 | cols = []
13 | tree = ET.parse(svgfilename)
14 | root = tree.getroot()
15 | for line in root.findall('svg:line',
16 | {'svg': 'http://www.w3.org/2000/svg'}):
17 | lines.append(
18 | ((float(line.attrib['x1']), float(line.attrib['x2'])),
19 | (float(line.attrib['y1']), float(line.attrib['y2']))))
20 | cols.append(
21 | [int(x)/256
22 | for x in rgbpat.findall(line.attrib['stroke'])[0]])
23 | a = np.array(lines)
24 | xmax, xmin = np.max(a[:, 0]), np.min(a[:, 0])
25 | ymax, ymin = np.max(a[:, 1]), np.min(a[:, 1])
26 |
27 | if ax == 0:
28 | ax = plt.gca()
29 | ax.set_frame_on(False)
30 | ax.set_aspect(1)
31 | ax.set_xlim((xmin, xmax))
32 | ax.set_ylim((ymax, ymin)) # upside down
33 | ax.set_yticks([])
34 | ax.set_xticks([])
35 |
36 | for l, c in zip(lines, cols):
37 | ax.add_line(mpl.Line2D(l[0], l[1], color=c))
38 |
--------------------------------------------------------------------------------
/src/femagtools/plot/fluxdens.py:
--------------------------------------------------------------------------------
1 | """ Create airgap flux density plots
2 |
3 | """
4 | import numpy as np
5 | import matplotlib.pyplot as plt
6 |
7 |
8 | def airgap(airgap, ax=0):
9 | """creates plot of flux density in airgap"""
10 | if ax == 0:
11 | ax = plt.gca()
12 | ax.set_title('Airgap Flux Density / T')
13 | ax.plot(airgap['pos'], airgap['B'],
14 | label='Max {:4.2f} T'.format(max(np.abs(airgap['B']))))
15 | ax.plot(airgap['pos'], airgap['B_fft'],
16 | label='Base Ampl {:4.2f} T'.format(airgap['Bamp']))
17 | ax.set_xlabel('Position/°')
18 | ax.legend()
19 | ax.grid(True)
20 |
21 |
22 | def airgap_fft(airgap, bmin=1e-2, ax=0):
23 | """plot airgap harmonics"""
24 | unit = 'T'
25 | if ax == 0:
26 | ax = plt.gca()
27 | ax.set_title('Airgap Flux Density Harmonics / {}'.format(unit))
28 | ax.grid(True)
29 | order, fluxdens = np.array([(n, b) for n, b in zip(airgap['nue'],
30 | airgap['B_nue']) if b > bmin]).T
31 | try:
32 | markerline1, stemlines1, _ = ax.stem(order, fluxdens, '-.', basefmt=" ")
33 | ax.set_xticks(order)
34 | except ValueError: # empty sequence
35 | pass
36 |
--------------------------------------------------------------------------------
/src/femagtools/templates/FE-losses.mako:
--------------------------------------------------------------------------------
1 |
2 | -- FE-Losses
3 | m.basfreq = ${model.get('basfreq', 50.0)}
4 | m.basind = ${model.get('basind', 1.5)}
5 | m.ch = ${model.get('ch', 4.0)}
6 | m.cw = ${model.get('cw', 2.0)}
7 | m.hyscoef = ${model.get('hyscoef', 1.0)}
8 | m.edycoef = ${model.get('edycoef', 2.0)}
9 | m.indcoef = ${model.get('indcoef', 2.0)}
10 | m.ffactor = ${model.get('ffactor', 1.0)}
11 | m.spweight = ${model.get('spweight', 7.65)}
12 | m.fillfact = ${model.get('fillfact', 1.0)}
13 | m.emodul = ${model.get('emodul', 210e9)}
14 | m.poison = ${model.get('poison', 0.3)}
15 | m.dampfact = ${model.get('dampfact', 0.0)}
16 | m.thcond = ${model.get('thcond', 30.0)}
17 | m.thcap = ${model.get('thcap', 480.0)}
18 |
--------------------------------------------------------------------------------
/src/femagtools/templates/airgapinduc.mako:
--------------------------------------------------------------------------------
1 | post_models("induct(x)","bagx") -- Calculate field distribution
2 | data=io.open("bag.dat","w") -- Output in data file
3 | for i = 1, #bagx, 3 do
4 | data:write(string.format("%g %g %g\n",bagx[i],bagx[i+1],bagx[i+2]))
5 | end
6 | io.close(data)
7 |
--------------------------------------------------------------------------------
/src/femagtools/templates/bertotti.mako:
--------------------------------------------------------------------------------
1 |
2 | function pfe(Bx,By,kh,fnu,km,z,d)
3 |
4 | -- Bx flux density x component
5 | -- By flux density y component
6 | -- kh Hysterese Factor
7 | -- fnu frequency
8 | -- km material factor
9 | -- ph return for hysterese losses
10 | -- pw return for eddy current losses
11 | -- iret status
12 |
13 | -- Parameter
14 |
15 | basfrq=${model['base_frequency']} -- Base Frequency for ch and cw [Hz]
16 | basind=${model['base_induction']} -- Base Induction (Peak) [T]
17 | ch=${model['ch']} -- Fe Hysteresis Coefficient ch [W/kg]
18 | cw=${model['cw']} -- Fe Eddy Current Coefficient cw [W/kg]
19 | ce=${model['ce']} -- Fe Excess Coefficient cw [W/kg]
20 | hyscoef=${model['alpha']} -- Hysteresis Frequency Coefficient
21 | spweight= ${model['special_weight']} -- Specific Weight Iron [gr/m3]
22 | fillfact=${model['fillfac']} -- Fillfactor Iron <= 1
23 |
24 | -- Bertotti Iron Loss Model
25 | -- pvfe = ch*f*(b**alpha) + cw*f**2*(b**2) + ce*f**1.5*(b**1.5)
26 | hxx = Bx/fillfact -- Bx
27 | hyy = By/fillfact -- By
28 | b21 = math.sqrt(hxx*hxx+hyy*hyy)
29 | b = b21/basind
30 |
31 | hi = fnu/basfrq
32 | hcw = hi^2
33 | hce = hi^1.5
34 |
35 | ph = kh*spweight*km*ch*hi*(b^hyscoef) -- [W/m3]
36 | pw = spweight*km*cw*hcw*(b^2) -- [W/m3]
37 | pe = spweight*km*ce*hce*(b^1.5)
38 | iret=1
39 | return ph, pw, pe, iret
40 | end
--------------------------------------------------------------------------------
/src/femagtools/templates/calc_therm_field.mako:
--------------------------------------------------------------------------------
1 | -- Stator aussen
2 | -- Waermeuebergange einer längsangestroemten Platte
3 | -- 10m/s => 57.0W/m2.K
4 | -- 20m/s => 95.3W/m2.K
5 | -- 30m/s => 130.0W/m2.K
6 | dy1 = 269.24
7 | da1 = 161.92
8 | dy2 = 110.64
9 | heat_trans = 57.0
10 | area_factor = 10
11 | rau = (dy1+0.5)/2.
12 | xau,yau = pr2c(rau,math.pi/num_slots) -- Luft aussen gegen Umgebung
13 | def_heat_transfer(xau,yau,skyblue,heat_trans,area_factor)
14 |
15 | rau = (dy2-0.5)/2.
16 | area_factor = 1
17 | xau,yau = pr2c(rau,math.pi/num_slots) -- Luft innen gegen Umgebung
18 | def_heat_transfer(xau,yau,skyblue,heat_trans/5,area_factor)
19 |
20 | ---------------------------------------------
21 | -- set boundary conditions -------------------
22 | del_bcond()
23 |
24 | beta = 2*math.pi*slots_gen/num_slots
25 | h = 3.8
26 | r1 = dy1/2 + h
27 | r2 = dy2/2 - h
28 | x0, y0 = pr2c(r1, beta)
29 | x1, y1 = pr2c(r2, beta)
30 | x2, y2 = r2, 0
31 | x3, y3 = r1, 0
32 | def_bcond_tp(x0, y0, x1, y1, x2, y2, x3, y3, 4)
33 | def_bcond_to(x1, y1, x2, y2)
34 | def_bcond_to(x3, y3, x0, y0)
35 | --[[
36 | ag = 0.75
37 | da2 = da1 - 2*ag
38 | r1 = da2/2+ag/2 -- Inner airgap nodechain
39 | r2 = da2/2+ag -- Outer airgap nodechain
40 |
41 | x0, y0 = r1, 0 -- pr2c(r1, beta)
42 | x1, y1 = pr2c(r1, beta)
43 |
44 | def_nccond_to(x0,y0, x1,y1)
45 |
46 | x0, y0 = r2, 0
47 | x1, y1 = pr2c(r2, beta)
48 | def_nccond_to(r2,0, 0,r2)
49 | --]]
50 | ---------------------------------------------
51 | -- Verluste import losses
52 | ---------------------------------------------
53 | import_losses_from_femag_dc()
54 | color_gradation_th(0,0,tot,Losses,0,0,model.."_losses.svg")
55 |
56 | ---------------------------------------------
57 | -- Temperatur berechnen ---------------------
58 | ---------------------------------------------
59 | calc_therm_field()
60 | color_gradation_th(0,0,tot,Temp,0.0,0,model.."_temp.svg")
61 |
--------------------------------------------------------------------------------
/src/femagtools/templates/colorgrad.mako:
--------------------------------------------------------------------------------
1 | % if model.get('colorgrad_babs',None):
2 | bmin = ${model.get('bmin', 0.0)}
3 | bmax = ${model.get('bmax', 0.0)}
4 | color_gradation( 0,0, 'tot', 'Babs', bmin, bmax, '${model['colorgrad_babs']}')
5 | % endif
6 | % if model.get('colorgrad_demag',None):
7 | hmin = ${model.get('hmin', 0.0)}
8 | hmax = ${model.get('hmax', 0.0)}
9 | color_gradation( 0,0, 'tot', 'demag', hmin, hmax, '${model['colorgrad_demag']}')
10 | % endif
11 |
12 |
--------------------------------------------------------------------------------
/src/femagtools/templates/com_motor_sim.mako:
--------------------------------------------------------------------------------
1 |
2 | -- Commutator-Motor-Simulation
3 | m.curr_step = ${model.get('curr_step',1)} --Number of current steps
4 | m.current = ${model.get('current',1)} --Nominal winding current [peak] IN [A]
5 | m.brush_angl = ${model.get('brush_angl',0)}
6 | m.skew_angle = ${model.get('skew_angle',0)}
7 | m.num_skew_st = ${model.get('num_skew_st',0)} --Number of skew sections: 0=infinite
8 | m.brush_width = ${model.get('brush_width',1e-2)} -- Rel. brush width (Ref:taupe:piD/2
9 |
10 | m.num_arm_bar = ${model.get('num_arm_bar',0)} --ZA : number of armature bars
11 | m.num_fi_turn = ${model.get('num_fi_turn',0)} --ZF : number of field windings
12 | m.num_par_wdgs = ${model.get('num_par_wdgs',2)} --N.par.arm.circ: LapW:2a=2p WaveW:2a=2
13 | m.ex_condition = ${model.get('ex_condition',1)}
14 | m.speed = ${model.get('speed',25)*60}
15 | m.magn_temp = ${model.get('magn_temp',20)}
16 | m.calc_noload = ${model.get('calc_noload',1)}
17 | m.forcedens = ${model.get('forcedens',0)}
18 | m.calc_react = ${model.get('calc_react',0)}
19 | m.calc_fe_los = ${model.get('calc_fe_los',0)}
20 | m.delta_br_an = ${model.get('delta_br_an',0)}
21 | m.nu_move_steps = ${model.get('num_move_steps',49)}
22 | m.cmmfilename = model .. "_" .. m.num_poles .."p.cmm"
23 | m.range_phi = ${model.get('range_phi',0)}
24 | m.phi_start = 0
25 |
26 | run_models("com-motor_sim")
27 |
--------------------------------------------------------------------------------
/src/femagtools/templates/conduct-data.mako:
--------------------------------------------------------------------------------
1 |
2 | -- conductor properties
3 | m.conduct = ${model.get('elconduct', 10e6)} -- el. conductivity S/m
4 | m.conrelperm = ${model.get('relperm', 100)} -- rel permeability
5 | m.contemp = ${model.get('contemp', 20)} -- conductor temperature °C
6 | m.contecoef = ${model.get('tempcoef', 0)} -- conduct. temperature coeff 1/K
7 | m.spconweight = ${model.get('spmaweight', 7.6)} -- mass density g/cm³
8 | m.relconlength = ${model.get('relconlength', 100)} -- rel cond length %
9 |
10 | pre_models('conduct-data')
--------------------------------------------------------------------------------
/src/femagtools/templates/connect_models.mako:
--------------------------------------------------------------------------------
1 | % if model.stator['num_slots'] > model.stator['num_slots_gen']:
2 | connect_models()
3 | % else:
4 | x0, y0 = pr2c(da1/2-ag/6, math.pi/2)
5 | create_mesh_se(x0, y0)
6 | x0, y0 = pr2c(da2/2+ag/6, math.pi/2)
7 | create_mesh_se(x0, y0)
8 |
9 | x0, y0 = pr2c(m.fc_radius, math.pi/2)
10 | create_mesh_se(x0, y0)
11 |
12 | x0,y0 = pd2c(dy1/2,0)
13 | def_bcond_vpo(x0, 0,-x0,0,0)
14 | def_bcond_vpo(-x0,0,x0,0,0)
15 | x0,y0 = pd2c(dy2/2,0)
16 | def_bcond_vpo(x0, 0,-x0,0,0)
17 | def_bcond_vpo(-x0,0,x0,0,0)
18 | % endif
19 |
20 | -- thermal properties
21 | ag_cond = 0.063
22 | --[[
23 | if speed < 1.0 then
24 | -- Waermeleitfähigkeit von Luft
25 | ag_cond = 0.0262
26 | end
27 | --]]
28 | xai, yai = pr2c((da1+da2)/4, math.pi/m.npols_gen)
29 | def_mat_therm(xai,yai,cyan,1.19,ag_cond,1007,1)
30 |
--------------------------------------------------------------------------------
/src/femagtools/templates/cu_losses.mako:
--------------------------------------------------------------------------------
1 |
2 | -- CU-Losses-
3 | m.cufilfact = ${model.get('cufilfact', 0.45)}
4 | m.culength = ${model.get('culength', 1.4)*100} -- rel wire length %
5 | m.cuconduct = ${model.get('cuconduct', 56e6)} -- el. conductivity S/m
6 | m.numlayers = ${model.get('num_layers', 1)}
7 | m.conheight = ${model.get('conheight', 0.0)}
8 | m.contemp = ${model.get('wind_temp',20.0)} -- conductor temperature °C
9 | m.emodul = ${model.get('emodul', 210e9)}
10 | m.poison = ${model.get('poisson', 0.3)}
11 | m.dampfact = ${model.get('dampfact', 0.0)}
12 | m.thcond = ${model.get('thcond', 30.)}
13 | m.thcap = ${model.get('thcap', 480.0)}
14 | m.slot_indul = ${model.get('slot_indul',0.0)*1e3}
15 | m.dia_wire = ${model.get('dia_wire',0.0)*1e3} -- wire diameter mm
16 | m.num_wire = ${model.get('num_wire',0.0)}
17 | % if model.get('winding_inside', False):
18 | -- conductor properties
19 | m.conduct = m.cuconduct
20 | m.conrelperm = ${model.get('relperm', 100)} -- rel permeability
21 | m.contecoef = ${model.get('tempcoef', 0)} -- conduct. temperature coeff 1/K
22 | m.spconweight = ${model.get('spmaweight', 7.6)} -- mass density g/cm³
23 | m.relconlength = ${model.get('rlen', 1)*100} -- rel cond length %
24 | pre_models('conduct-data')
25 | pre_models("CU-Losses-2") -- inside
26 | % else:
27 | pre_models("CU-Losses-1")
28 | % endif
29 |
--------------------------------------------------------------------------------
/src/femagtools/templates/dakota/moga.mako:
--------------------------------------------------------------------------------
1 | # Dakota Input Template File
2 |
3 | environment
4 | tabular_data
5 | tabular_data_file = 'femag.dat'
6 |
7 | method
8 | moga
9 | % if set(('num_generations', 'percent_change')).intersection(study.keys()):
10 | convergence_type metric_tracker
11 | % if 'num_generations' in study:
12 | num_generations = ${study['num_generations']}
13 | % endif
14 | % if 'percent_change' in study:
15 | percent_change = ${study['percent_change']}
16 | % endif
17 | % endif
18 | #final_solutions = 3
19 | print_each_pop
20 | # fitness_type domination_count
21 | # niching_type distance 0.05 0.05
22 | # replacement_type below_limit = 6
23 | # replacement_type roulette_wheel
24 | # postprocessor_type orthogonal_distance 0.05 0.05
25 | # max_function_evaluations = ${study.get('max_function_evaluations', 1000)}
26 |
27 | variables
28 | % if [d['bounds'] for d in study['decision_vars']]:
29 | continuous_design = ${len(study['decision_vars'])}
30 | lower_bounds ${' '.join([str(d['bounds'][0]) for d in study['decision_vars']])}
31 | upper_bounds ${' '.join([str(d['bounds'][1]) for d in study['decision_vars']])}
32 | descriptors ${' '.join([f"\"{d['name']}\"" for d in study['decision_vars']])}
33 | % endif
34 |
35 | interface
36 | id_interface = 'FEMAG'
37 | analysis_driver = 'python -m femagtools.dakota_femag'
38 | fork batch
39 | parameters_file = 'params.in'
40 | results_file = 'results.out'
41 | file_save
42 |
43 | responses
44 | objective_functions = ${len(study['objective_vars'])}
45 | descriptors ${' '.join([f"\"{o['name']}\"" for o in study['objective_vars']])}
46 | # sense 'max' 'min' ..
47 | no_gradients
48 | no_hessians
49 |
--------------------------------------------------------------------------------
/src/femagtools/templates/displ_stator_rotor.mako:
--------------------------------------------------------------------------------
1 | -- calculate static or dynamic eccentricity
2 | -- NOTE: requires full model
3 | --
4 | static = 0
5 | dynamic = 1
6 | m.disp_info = ${model.get('type', 'static')} -- Displace: Stator: 0, Rotor: 1
7 |
8 | da1 = ${model.get('bore_diam',0)*1e3}
9 | ag = ${model.get('airgap',0)*1e3}
10 |
11 | if m.b_min == 0 then -- move inside: outer stator
12 | if m.disp_info == static then
13 | m.fc_radius = da1/2 - ag/6
14 | else
15 | m.fc_radius = da1/2 - 5*ag/6
16 | end
17 | else
18 | if m.disp_info == static then
19 | m.fc_radius = da1/2 + ag/6
20 | else
21 | m.fc_radius = da1/2 + 5*ag/6
22 | end
23 | end
24 | m.disp_radius = ${model.get('ecc', 0)*1e3} -- Displacement: r [mm]
25 | m.disp_phi = 0.0 -- Displacement: phi [Degr]
26 |
27 | pre_models("Displ_Stat/Rot")
28 | -- must correct fc_radius
29 | if m.b_min == 0 then -- move inside: outer stator
30 | m.fc_radius = da1/2 - ag/2
31 | else
32 | m.fc_radius = da1/2 + ag/2
33 | end
--------------------------------------------------------------------------------
/src/femagtools/templates/ec-rotorbar.mako:
--------------------------------------------------------------------------------
1 | -- eddy current simulation of a rotor bar
2 | --
3 | -- set rotor bar
4 | xb, yb = 0, da2/2 - m.slot_height/2 - m.slot_h1
5 | muer = 1
6 | rel = 100
7 | cur = {1, 0}
8 | sigma1, sigma2 = get_dev_data( "cond_conduct" )
9 | rotorbar = def_new_bar(xb,yb, "green", "U", cur[1],cur[2], "wi",
10 | sigma2, muer, rel, "polar", 0, 0)
11 | Abar = get_sreg_data("area",rotorbar)
12 |
13 | maxit = m.num_nonl_it
14 | permode = 'restore'
15 | du_u0 = m.error_perm/5
16 |
17 | psi={}
18 | L={}
19 |
20 | % if model.get('bar_len', 0):
21 | barlen = ${model.get('bar_len')*1e3}
22 | % else:
23 | p = m.num_poles/2
24 | Dr = da2-m.slot_height
25 | barlen = m.arm_length+math.pi*Dr/Q2/math.sin(math.pi*p/Q2)
26 | % endif
27 |
28 | state_of_problem('mag_dynamic')
29 | file_bar = io.open("bar.dat","w")
30 | dfreq = 8
31 | f0 = 2
32 | bag = {}
33 | pos = {}
34 | leakind = {}
35 | currdens={1, 2, 3, 4} -- factor for current variation (Current densities A/mm²)
36 | Nfreqs = 15 --
37 | for i= 1, Nfreqs do
38 | freq = f0 + (i-1)*dfreq
39 | for k = 1, #currdens do
40 | cur = Abar*currdens[k]
41 | def_curr_wdg(rotorbar, cur, 0)
42 |
43 | calc_field_single({maxit=maxit, maxcop=du_u0,
44 | permode=permode, freq=freq})
45 | if k==1 then
46 | u_re, u_im = get_wdg_data("volt", rotorbar)
47 | rbar = u_re*barlen/cur
48 | end
49 | i_re, i_im = get_wdg_data("cur", rotorbar)
50 | flx1_re, flx1_im = get_wdg_data("flux", rotorbar)
51 | flx2_re, flx2_im = get_wdg_data("flux", stator)
52 |
53 | print(string.format("%g: %g %g %g",
54 | freq, i_re, flx1_re*m.arm_length, flx2_re*m.arm_length))
55 |
56 | leakind[k] = (flx1_re-flx2_re)*m.arm_length/cur
57 | end
58 | file_bar:write(string.format("%g %g ",
59 | freq, rbar))
60 | for k=1, #currdens do
61 | file_bar:write(string.format("%g ", leakind[k]))
62 | end
63 | file_bar:write("\n")
64 | end
65 | file_bar:close()
66 |
--------------------------------------------------------------------------------
/src/femagtools/templates/fe-contr.mako:
--------------------------------------------------------------------------------
1 | m.hc_min = ${'%12.3f' % model.get('hc_min', 95.0)} -- Limit demagnetisa > 0:[%]Hc,<0:[kA/m]
2 | m.con_hdcopy = ${'%12.3f' % model.get('con_hdcopy', 0)} -- Hc-copy:Name:auto:0,intact:1, none:-1
3 | m.b_max = ${'%12.3f' % model.get('b_max', 2.4)} -- Max Induction [T] in colorgradation
4 | m.b_min = ${'%12.3f' % model.get('move_inside')} -- Move inside: 0 , Move outside: > 0
5 | m.calc_fe_loss = ${model.get('calc_fe_loss', 1)} -- Calc. FE-Loss:0:no, 1:yes, 2:m-output
6 | m.eval_force = ${'%12.3f' % model.get('eval_force', 0)} -- Eval. force density > 0, no <= 0
7 | m.allow_draw = ${'%12.3f' % model.get('allow_draw', 1)} -- Draw Graphics :> 0: yes, 0: no
8 | m.fline_dens = ${'%12.3f' % model.get('fline_dens', 4)} -- F-Lines: 1: small, 2: medium, 3:thick
9 | m.num_flines = ${'%12.3f' % model.get('num_flines', 20)} -- Number of Field-lines: < 100 > 2
10 | m.name_bch_log = ${'%12.3f' % model.get('name_bch_log', 0)} -- Name bch-file in Logfile:> 0:yes,0:no
11 | m.st_size_move = ${'%12.3f' % model.get('st_size_move', 0)} -- Step size move: r/ph:[degr], x/y:[mm]
12 | m.num_nonl_it = ${'%12.3f' % model.get('num_nonl_it', 300)} -- Number of nonlinear Iterations < 99
13 | m.perm_mode = ${'%12.3f' % model.get('perm_mode', 0)} -- Permeability mode:>0:restore,0:actual
14 | m.error_perm = ${'%12.3f' % model.get('error_perm', 0.005)} -- Rel. Permeability error < 0.1 [%]
15 | m.allow_demagn = ${'%12.3f' % model.get('allow_demagn', 0)} -- Allow Demagnetisation:= 1:yes,= 0:no
16 | m.maenergy = ${'%12.3f' % model.get('maenergy', 0)} -- Force from magn energy 1 :yes,= 0:no
17 | m.el_order_ag = ${'%12.3f' % model.get('el_order_ag', 1)} -- El. order in air gap: lin=1: quadr=2
18 | m.export_scrpt = ${'%12.3f' % model.get('export_scrpt', 0)} -- Export parameters in script: yes > 0
19 |
20 | pre_models("FE-contr-data")
21 |
--------------------------------------------------------------------------------
/src/femagtools/templates/fieldcalc.mako:
--------------------------------------------------------------------------------
1 |
2 | -- no load single calculation
3 |
4 | maxit=300
5 | du_u0=1e-3
6 |
7 | get_wdg_keys("wkeys")
8 |
9 | -- set cur to zero
10 | for i = 1, #wkeys do
11 | def_curr_wdg(wkeys[i],0, 0)
12 | end
13 | % if model.get('noload_ex_cur', 0):
14 | def_curr_wdg(wkeys[#wkeys], ${model['noload_ex_cur']}, 0)
15 | % endif
16 |
17 | calc_field_single(maxit, reset, du_u0)
18 |
19 | post_models("induct(x)","b_airgap") -- Calculate field distribution
20 |
21 | data=io.open("bag.dat","w") -- Output in data file
22 | N = table.getn(b_airgap) -- Number of elements in array
23 | i = 1
24 | repeat
25 | data:write(string.format("%g %g %g\n",b_airgap[i],b_airgap[i+1],b_airgap[i+2]))
26 | i = i+3
27 | until i>=N
28 | io.close(data)
29 |
30 | -- experimental (new femag-classic needed)
31 | export_calc_results('fieldcalc.vtu')
--------------------------------------------------------------------------------
/src/femagtools/templates/inductances.mako:
--------------------------------------------------------------------------------
1 | % if model.get('calc_inductances',0):
2 |
3 | L={}
4 | curr = 1/a
5 | ksym = m.num_poles/m.npols_gen
6 | curr = {
7 | {1/a, 0, 0},
8 | {0, 1/a, 0},
9 | {0, 0, 1/a} }
10 |
11 | data=io.open("inductances.dat","w+")
12 | for i=1,m.num_phases do
13 | for k=1,m.num_phases do
14 | def_curr_wdg(k,curr[i][k],0)
15 | end
16 | calc_field_single({
17 | maxit=1,permode='actual',freq=m.frequency})
18 |
19 | for k=1,m.num_phases do
20 | psi_Re,psi_Im=flux_winding_wk(k)
21 | data:write(string.format("%g ",
22 | math.sqrt(psi_Re^2+psi_Im^2)*m.arm_length/a*ksym))
23 | end
24 | data:write('\n')
25 | end
26 | io.close(data)
27 | % endif
28 |
--------------------------------------------------------------------------------
/src/femagtools/templates/ld_lq_fast.mako:
--------------------------------------------------------------------------------
1 | --
2 | -- Ld-Lq- Identification
3 | --
4 |
5 | m.move_action = 0.0 -- rotate
6 | % if isinstance(model, dict) and 'lfe' in model:
7 | m.arm_length = ${model.get('lfe')*1e3}
8 | % endif
9 | m.speed = ${model.get('speed')*60}
10 | m.skew_angle = ${model.get('skew_angle',0)}
11 | m.nu_skew_steps = ${model.get('num_skew_steps',0)}
12 | m.magn_temp = ${model.get('magn_temp', 'nil')}
13 | m.fc_mult_move_type = 1.0 -- Type of move path in air gap
14 | m.phi_start = ${model.get('phi_start', 0)}
15 | m.range_phi = ${model.get('range_phi', 0)}
16 | m.nu_move_steps = ${model.get('num_move_steps', 49)}
17 | m.num_par_wdgs = ${model.get('num_par_wdgs',1)}
18 |
19 | m.current = ${model['i1_max']}*math.sqrt(2.0)/m.num_par_wdgs
20 | m.num_cur_steps = ${model['num_cur_steps']}
21 | m.nu_beta_steps = ${model['num_beta_steps']}
22 | m.beta_max = ${model['beta_max']}
23 | m.beta_min = ${model['beta_min']}
24 | % if model.get('calc_fe_loss', 0):
25 | m.calc_fe_loss = ${model['calc_fe_loss']}
26 | % endif
27 | % if model.get('loss_funct',0):
28 | m.loss_funct = ${model.get('loss_funct')}
29 | % endif
30 |
31 | m.pm_eff_aktiv = 0.0
32 | m.calc_noload = ${model.get('calc_noload', 1)}
33 | m.period_frac = ${model.get('period_frac', 1)}
34 |
35 | m.pocfilename = '${model.get('pocfilename', 'sin.poc')}'
36 | % if model.get('load_ex_cur',0):
37 | m.load_ex_cur = ${model.get('load_ex_cur',0)}
38 | run_models("ld_lq_f_cur")
39 | %else:
40 | run_models("ld_lq_fast")
41 | %endif
--------------------------------------------------------------------------------
/src/femagtools/templates/leak_dist_wind.mako:
--------------------------------------------------------------------------------
1 | -- End-Winding Leakage
2 | m.nseg = m.tot_num_slot/m.num_slots -- Number of segments
3 | m.npolsim = m.npols_gen -- Number of poles simulated
4 | % if 'perimrad' not in model:
5 | m.perimrad = (da1+dy1)/4 -- Radius of perimeter [mm]
6 | % else:
7 | m.perimrad = ${model['perimrad']*1e3} -- Radius of perimeter [mm]
8 | % endif
9 | m.vbendrad = ${model['vbendrad']*1e3} -- Bending radius vertical [mm]
10 | m.endheight = ${model['endheight']*1e3} -- End winding height [mm]
11 | m.wiredia = ${model['wiredia']*1e3} -- Wire diameter [mm]
12 | pre_models("leak_dist_wind")
13 |
--------------------------------------------------------------------------------
/src/femagtools/templates/leak_evol_wind.mako:
--------------------------------------------------------------------------------
1 | -- End-Winding Leakage
2 | m.nseg = m.tot_num_slot/m.num_slots -- Number of segments
3 | m.npolsim = m.npols_gen -- Number of poles simulated
4 |
5 | m.evol1rad = ${model['evol1rad']*1e3} -- Top radius of first evolvent [mm]
6 | m.evol2rad = ${model['evol2rad']*1e3} -- Top radius of second evolvent [mm]
7 | m.botlevel = ${model['botlevel']*1e3} -- Level at bottom of evolvents [mm]
8 | m.toplevel = ${model['toplevel']*1e3} -- Level at top of evolvents [mm]
9 | m.endheight = ${model['endheight']*1e3} -- End winding height [mm]
10 | m.evolbend = ${model['evolbend']*1e3} -- Bending radius [mm]
11 | m.wiredia = ${model['wiredia']*1e3} -- Wire diameter [mm]
12 |
13 | pre_models("leak_evol_wind")
14 |
--------------------------------------------------------------------------------
/src/femagtools/templates/leak_tooth_wind.mako:
--------------------------------------------------------------------------------
1 | -- End-Winding Leakage
2 | m.nseg = m.tot_num_slot/m.num_slots -- Number of segments
3 | m.npolsim = m.npols_gen -- Number of poles simulated
4 |
5 | m.endheight = ${model['endheight']*1e3} -- End winding height [mm]
6 | m.bendrad = ${model['bendrad']*1e3} -- Bending radius [mm]
7 | m.wiredia = ${model['wiredia']*1e3} -- Wire diameter [mm]
8 |
9 | pre_models("leak_tooth_wind")
10 |
--------------------------------------------------------------------------------
/src/femagtools/templates/magnet-data.mako:
--------------------------------------------------------------------------------
1 | -- Magnet-data
2 | %if model.get('remanenc',0):
3 | m.remanenc = ${model.get('remanenc')}
4 | %endif
5 | %if model.get('relperm',0):
6 | m.relperm = ${model.get('relperm')}
7 | %endif
8 | %if model.get('spmaweigth',0):
9 | m.spmaweight = ${model.get('spmaweight')*1e-3}
10 | %endif
11 | %if model.get('temcoefbr',0):
12 | m.temcoefbr = ${model.get('temcoefbr')*100}
13 | %endif
14 | %if model.get('temcoefhc',0):
15 | m.temcoefhc = ${model.get('temcoefhc')*100}
16 | %endif
17 | %if model.get('magntemp',0):
18 | m.magntemp = ${model.get('magntemp')}
19 | %endif
20 | %if model.get('magncond',0):
21 | m.magncond = ${model.get('magncond')}
22 | %endif
23 | %if model.get('rlen',0):
24 | m.rlen = ${model.get('rlen')*100}
25 | %endif
26 | %if model.get('mcvkey',0):
27 | m.mcvkey_magnet = '${model.get('mcvkey')}'
28 | %if model.get('orient', 0):
29 | m.orient = ${model.get('orient', 'm.cartiso')}
30 | %endif
31 | %else:
32 | %if model.get('magnwidth',0):
33 | m.magsegwid = ${model.get('magnwidth')*1e3}
34 | %elif model.get('magnsegwidth',0):
35 | m.magsegwid = ${model.get('magnsegwidth')*1e3}
36 | %endif
37 | %if model.get('magnlength',0):
38 | m.magseglen = ${model.get('magnlength')*1e3}
39 | %endif
40 | %if model.get('magnseglength',0):
41 | m.magseglen = ${model.get('magnseglength')*1e3}
42 | %endif
43 | %endif
44 |
45 | pre_models("Magnet-data")
46 |
--------------------------------------------------------------------------------
/src/femagtools/templates/magnetFC2.mako:
--------------------------------------------------------------------------------
1 | m.yoke_rad = dy2/2
2 | m.rotor_rad = da2/2
3 |
4 | m.yoke_height = ${model['yoke_height']*1e3}
5 |
6 | m.iron_h1 = ${model['iron_h1']*1e3}
7 | m.iron_h2 = ${model['iron_h2']*1e3}
8 | m.iron_b = ${model['iron_b']*1e3}
9 | m.magn_width = ${model['magn_width']*1e3}
10 | m.magn_height = ${model['magn_height']*1e3}
11 | m.iron_bfe = ${model['iron_bfe']*1e3}
12 | m.iron_bfo = ${model['iron_bfo']*1e3}
13 | m.iron_shape = ${model['iron_shape']*1e3}
14 | m.iron_hp = ${model['iron_hp']*1e3}
15 | m.magn_num = ${model['magn_num']}
16 |
17 | m.nodedist = ${model.get('nodedist',0.0)}
18 | m.zeroangl = ${model.get('zeroangle',0)}
19 |
20 | m.mcvkey_yoke = mcvkey_yoke
21 |
22 | pre_models("Rotor_FC2")
23 |
--------------------------------------------------------------------------------
/src/femagtools/templates/magnetSectorLinear.mako:
--------------------------------------------------------------------------------
1 |
2 | -- M-Sector-Lin
3 |
4 | m.l_corner_x0 = 0.0
5 | m.l_corner_y0 = 0.0
6 | m.magn_height = ${model['magn_height']*1e3}
7 | % if model.get('magn_width_pct'):
8 | m.magn_width = ${model['magn_width_pct']*1e2}
9 | % else:
10 | m.magn_width = -${model['magn_width']*1e3}
11 | % endif
12 | m.pole_width = ${model['pole_width']*1e3}
13 | m.yoke_heigth = ${model['yoke_height']*1e3}
14 | m.magn_len = ${model['magn_len']*100}
15 | m.magn_rem = m.remanenc
16 | m.gap_ma_yoke = ${model['gap_ma_yoke']*1e3}
17 | m.magn_ori = ${model['magn_ori']}
18 | m.airgap_shape = ${model['airgap_shape']*1e3}
19 | m.magn_type = ${model['magn_type']}
20 |
21 | m.zeroangl = ${model.get('zeroangle',0)}
22 |
23 | m.mcvkey_yoke = mcvkey_yoke
24 |
25 | pre_models("M-Sector-Lin");
26 |
--------------------------------------------------------------------------------
/src/femagtools/templates/magnetShell.mako:
--------------------------------------------------------------------------------
1 |
2 |
3 | m.magn_r1 = da1/2 -- Inner Radius Magnet R1 [mm]
4 | m.magn_r2 = dy1/2 - ${model.get('yoke_height')*1e3} -- Outer Radius Magnet R2 [mm]
5 | m.magn_r4 = ${model.get('magn_r4')*1e3} -- Eccentr. Radius Magnet R4 [mm]
6 | m.eccentr = ${model.get('eccentr')*1e3} -- Eccentricity E1 [mm]
7 | m.magn_r3 = ${model.get('eccentr')*1e3} -- Radius Magnet-end R3 [mm]
8 | m.magn_len = ${model.get('magn_len')*1e2} -- Magnet Length [%]
9 | m.magn_b1 = ${model.get('magn_b1')*1e3} -- Width Magnet outside B1 [mm]
10 | m.magn_h1 = ${model.get('magn_h1')*1e3} -- Height Magnet H1 [mm]
11 | m.magn_h2 = ${model.get('magn_h2')*1e3} -- Height Magnet H2 [mm]
12 | m.magn_rp = ${model.get('magn_rp')*1e3} -- Radius Housing Rp [mm]
13 | m.magn_a4 = ${model.get('magn_a4')} -- Angle of R4 A4 [Grad]
14 | m.magn_rem = 0.0 -- (ignored) Remanence Br [T]
15 | m.yoke_height = ${model.get('yoke_height')*1e3} -- Stator Housing height D [mm]
16 | m.magn_ori = ${model.get('magn_ori')} -- Orientation: par:1; Pol:2; cos:3
17 | --m.airgap = -1.0 -- Mesh height (2/3 airgap) [mm]
18 |
19 | m.mcvkey_yoke = mcvkey_yoke
20 | m.tot_num_sl = m.num_poles
21 | m.num_sl_gen = m.npols_gen
22 |
23 | m.zeroangl = ${model.get('zeroangl', 0)}
24 |
25 | pre_models("MAGNET_SHELL")
26 |
--------------------------------------------------------------------------------
/src/femagtools/templates/modified_steinmetz.mako:
--------------------------------------------------------------------------------
1 |
2 | function pfe(Bx,By,kh,fnu,km,z,d)
3 |
4 | -- Bx flux density x component
5 | -- By flux density y component
6 | -- kh Hysterese Factor
7 | -- fnu frequency
8 | -- km material factor
9 | -- ph return for hysterese losses
10 | -- pw return for eddy current losses
11 | -- iret status
12 |
13 | -- Parameter
14 |
15 | basfrq=${model['base_frequency']} -- Base Frequency for ch and cw [Hz]
16 | basind=${model['base_induction']} -- Base Induction (Peak) [T]
17 | ch=${model['ch']} -- Fe Hysteresis Coefficient ch [W/kg]
18 | cw=${model['cw']} -- Fe Eddy Current Coefficient cw [W/kg]
19 | alpha=${model['alpha']} -- Hysteresis Frequency Coefficient Alpha
20 | beta=${model['beta']} -- Hysteresis Frequency Coefficient Beta
21 | spweight= ${model['special_weight']} -- Specific Weight Iron [gr/m3]
22 | fillfact=${model['fillfac']} -- Fillfactor Iron <= 1
23 |
24 | -- Modified Steinmetz Iron Loss Model
25 | -- pvfe = ch*hi*(b**(alpha + beta*b)) + cw*(hi**2)*(b**2)
26 | hxx = Bx/fillfact -- Bx
27 | hyy = By/fillfact -- By
28 | b21 = math.sqrt(hxx*hxx+hyy*hyy)
29 |
30 | b = b21/basind
31 | hi = fnu/basfrq
32 | coeff = alpha+beta*b
33 | ph = kh*spweight*km*ch*hi*(b^coeff) -- [W/m3]
34 | pw = spweight*km*cw*(b^2)*(hi^2) -- [W/m3]
35 | pe = 0.0
36 |
37 | iret=1
38 | return ph, pw, pe, iret
39 | end
--------------------------------------------------------------------------------
/src/femagtools/templates/mult_cal_fast.mako:
--------------------------------------------------------------------------------
1 | --
2 | -- Multi Calculation I/x
3 | --
4 | m.move_action = 0 -- rotate
5 | % if 'lfe' in model:
6 | m.arm_length = ${model.get('lfe')*1e3}
7 | % endif
8 | m.skew_angle = ${model.get('skew_angle',0)}
9 | m.nu_skew_steps = ${model.get('num_skew_steps',0)}
10 | m.nu_force_pat = 0.0
11 | m.num_par_wdgs = ${model.get('num_par_wdgs',1)}
12 | m.current = ${model.get('current')}*math.sqrt(2.0)/m.num_par_wdgs
13 | m.angl_i_up = ${model.get('angl_i_up')}
14 | m.cur_control = 0 -- 0: range, 1: poc, 6
15 | m.max_current = 100.0 -- %
16 | m.num_cur_steps = ${model['num_cur_steps']}
17 | m.phi_start = ${model.get('phi_start', 0)}
18 | m.range_phi = ${model.get('range_phi', 0)}
19 | m.nu_move_steps = ${model.get('num_move_steps', 49)}
20 | m.speed = ${model.get('speed')*60}
21 | m.fc_mult_move_type = 1.0 -- Type of move path in air gap
22 | m.fc_force_points = 0.0 -- number move points in air gap
23 | m.loss_funct = ${model.get('loss_funct', 0)} -- loss functon 0: own 1: ext
24 | m.loss_fact = ${model.get('loss_fact', 1)} -- loss multiplication factor
25 | % if model.get('calc_fe_loss', 0):
26 | m.calc_fe_loss = ${model['calc_fe_loss']}
27 | % endif
28 |
29 | % if model.get('vtu_movie', 0):
30 | m.movie_type = 'vtu'
31 | % else:
32 | m.movie_type = nil
33 | % endif
34 |
35 | m.pocfilename = '${model.get('pocfilename', 'sin.poc')}'
36 |
37 | run_models("mult_cal_fast")
38 |
--------------------------------------------------------------------------------
/src/femagtools/templates/new_model.mako:
--------------------------------------------------------------------------------
1 |
2 | exit_on_error=${model.get('exit_on_error', 'false')}
3 | exit_on_end=${model.get('exit_on_end', 'false')}
4 | verbosity=${model.get('verbosity', 1)}
5 |
6 | model = '${model.get('name')}'
7 | description = '${model.get('description','')}'
8 | % if model.get('scratch_mode', 0):
9 | new_model(model, '', 'scratch')
10 | % else:
11 | new_model_force(model, description)
12 | %endif
13 |
--------------------------------------------------------------------------------
/src/femagtools/templates/open.mako:
--------------------------------------------------------------------------------
1 | exit_on_error=${model.get('exit_on_error', 'false')}
2 | exit_on_end=${model.get('exit_on_end')}
3 | verbosity=${model.get('verbosity', 1)}
4 |
5 | model = '${model.get(['name'])}'
6 | load_model(model)
7 |
8 | m.num_poles = get_dev_data("num_poles")
9 | m.num_pol_pair = m.num_poles/2
10 | m.npols_gen = get_mod_data("num_poles")
11 | m.arm_length = get_dev_data("arm_length")
12 |
--------------------------------------------------------------------------------
/src/femagtools/templates/plots.mako:
--------------------------------------------------------------------------------
1 | % for p in model.get('plots', []):
2 | % if not isinstance(p, str):
3 | % if p[0] == 'field_lines':
4 | % if len(p) < 2:
5 | field_lines('field.svg', 20)
6 | % else:
7 | field_lines('field.svg', ${p[1]})
8 | % endif
9 | % else:
10 | % if len(p) < 3:
11 | color_gradation( 0,0, 'tot', '${p[0]}', 0, 0, '${p[0]}'..'.svg')
12 | % elif len(p) < 4:
13 | color_gradation( 0,0, 'tot', '${p[0]}', ${p[1]}, ${p[2]}, '${p[0]}'..'.svg')
14 | % else:
15 | color_gradation( 0,0, 'tot', '${p[0]}', ${p[1]}, ${p[2]}, '${p[3]}')
16 | % endif
17 | % endif
18 | % else:
19 | % if p == 'field_lines':
20 | field_lines('field.svg', 20)
21 | % else:
22 | color_gradation( 0,0, 'tot', '${p}', 0, 0, '${p}'..'.svg')
23 | % endif
24 | % endif
25 | % endfor
26 |
--------------------------------------------------------------------------------
/src/femagtools/templates/pm_sym_f_cur.mako:
--------------------------------------------------------------------------------
1 | --
2 | -- SM Simulation with excitation current
3 | --
4 | m.wdcon = ${model.get('wdgcon', 0)} -- Connection: 0=open, 1=star, 2=delta
5 | m.move_action = ${model.get('move_action', 0)}
6 | m.speed = ${model.get('speed')*60}
7 | m.skew_angle = ${model.get('skew_angle',0)}
8 | m.nu_skew_steps = ${model.get('num_skew_steps',0)}
9 | m.eval_force = ${model.get('eval_force', 0)}
10 | m.num_par_wdgs = ${model.get('num_par_wdgs',1)}
11 | m.current = ${model.get('current')}*math.sqrt(2.0)/m.num_par_wdgs
12 | m.angl_i_up = ${model.get('angl_i_up', 0)}
13 |
14 | m.optim_i_up = ${model.get('optim_i_up', 0)}
15 | m.nu_move_steps = ${model.get('num_move_steps', 49)}
16 | m.range_phi = ${model.get('range_phi', 0)}
17 | m.phi_start = ${model.get('phi_start', 0)}
18 | m.pm_eff_aktiv = 0 -- Generate additional output (>=1)
19 | m.fc_mult_move_type = 1 -- Type of move path in air gap (1=circ)
20 | m.calc_noload = ${model.get('calc_noload', 1)}
21 | m.period_frac = ${model.get('period_frac', 1)}
22 | m.pocfilename = '${model.get('pocfilename', 'sin.poc')}'
23 | % if model.get('vtu_movie', 0):
24 | m.movie_type = 'vtu'
25 | %endif
26 | % if model.get('calc_fe_loss'):
27 | m.calc_fe_loss = ${'%d' % model['calc_fe_loss']}
28 | % endif
29 | % if model.get('loss_funct',0):
30 | m.loss_funct = ${model.get('loss_funct')}
31 | % endif
32 | -- Excitation current
33 | m.nloa_ex_cur = ${model.get('noload_ex_cur', 0)} -- No Load Exciting current
34 | m.load_ex_cur = ${model.get('load_ex_cur', 0)} -- Load Exciting current
35 | m.wdgkeyex = 0 -- automatic winding selection
36 |
37 | run_models("pm_sym_f_cur")
38 |
--------------------------------------------------------------------------------
/src/femagtools/templates/pm_sym_loss.mako:
--------------------------------------------------------------------------------
1 | --
2 | -- PM/Rel Losses
3 | --
4 | m.move_action = 0.0 -- rotate
5 | % if 'lfe' in model:
6 | m.arm_length = ${model.get('lfe')*1e3}
7 | % endif
8 | m.speed = 1000.
9 | m.skew_angle = ${model.get('skew_angle',0)}
10 | m.nu_skew_steps = ${model.get('num_skew_steps',0)}
11 | m.magn_temp = ${model.get('magn_temp')}
12 | m.fc_mult_move_type = 1.0 -- Type of move path in air gap
13 | m.fc_force_points = 0.0 -- number move points in air gap
14 | m.phi_start = ${model.get('phi_start', 0)}
15 | m.range_phi = ${model.get('range_phi', 0)}
16 | m.nu_move_steps = ${model.get('num_move_steps', 49)}
17 | m.num_par_wdgs = ${model.get('num_par_wdgs',1)}
18 |
19 | m.winding_temp = ${model.get('wind_temp')}
20 | m.current = 1.0
21 | m.ntibfilename = model..'.ntib'
22 | m.period_frac = ${model.get('period_frac', 1)}
23 | % if model.get('calc_fe_loss', 0):
24 | m.calc_fe_loss = ${model['calc_fe_loss']}
25 | % endif
26 | % if model.get('loss_funct',0):
27 | m.loss_funct = ${model.get('loss_funct')}
28 | % endif
29 |
30 | m.pocfilename = '${model.get('pocfilename', 'sin.poc')}'
31 |
32 | run_models("pm_sym_loss")
33 |
--------------------------------------------------------------------------------
/src/femagtools/templates/psd_psq_fast.mako:
--------------------------------------------------------------------------------
1 | --
2 | -- Psid-Psiq- Identification
3 | --
4 | % if model.get('magn_temp',0):
5 | set_dev_data("magn_temp", ${model.get('magn_temp')})
6 | %endif
7 |
8 | m.move_action = 0.0 -- rotate
9 | m.speed = ${model.get('speed')*60}
10 | m.skew_angle = ${model.get('skew_angle',0)}
11 | m.nu_skew_steps = ${model.get('num_skew_steps',0)}
12 | m.fc_mult_move_type = 1.0 -- Type of move path in air gap
13 | m.phi_start = ${model.get('phi_start', 0)}
14 | m.range_phi = ${model.get('range_phi', 0)}
15 | m.nu_move_steps = ${model.get('num_move_steps', 49)}
16 | m.num_par_wdgs = ${model.get('num_par_wdgs',1)}
17 |
18 | m.maxid = ${model['maxid']}/m.num_par_wdgs
19 | m.minid = ${model['minid']}/m.num_par_wdgs
20 | m.maxiq = ${model['maxiq']}/m.num_par_wdgs
21 | m.miniq = ${model['miniq']}/m.num_par_wdgs
22 | m.delta_id = ${model['delta_id']}/m.num_par_wdgs
23 | m.delta_iq = ${model['delta_iq']}/m.num_par_wdgs
24 | % if model.get('load_ex_cur',0):
25 | m.load_ex_cur = ${model['load_ex_cur']}
26 | %endif
27 | % if model.get('calc_fe_loss', 0):
28 | m.calc_fe_loss = ${model['calc_fe_loss']}
29 | % endif
30 | % if model.get('loss_funct',0):
31 | m.loss_funct = ${model.get('loss_funct')}
32 | % endif
33 | m.pm_eff_aktiv = 0.0
34 | m.calc_noload = ${model.get('calc_noload', 1)}
35 | m.period_frac = ${model.get('period_frac', 1)}
36 | m.pocfilename = '${model.get('pocfilename', 'sin.poc')}'
37 | run_models("psd_psq_fast")
38 |
--------------------------------------------------------------------------------
/src/femagtools/templates/ring.mako:
--------------------------------------------------------------------------------
1 | --[[
2 | Ring rotor (either laminated or pure air)
3 | --]]
4 |
5 | x1, y1 = pd2c(da2/2, m.zeroangl)
6 | x2, y2 = pd2c(dy2/2, m.zeroangl)
7 | x3, y3 = pd2c(dy2/2, m.zeroangl + 360/m.num_poles)
8 | x4, y4 = pd2c(da2/2, m.zeroangl + 360/m.num_poles)
9 | ndt(2*agndst)
10 | nc_circle(x1, y1, x4, y4, 0)
11 | ndt(8*agndst)
12 | nc_line(x1, y1, x2, y2, 0)
13 | nc_circle(x2, y2, x3, y3, 0)
14 | nc_line(x3, y3, x4, y4,0)
15 | xm, ym = pd2c((dy2+da2)/4, 90/m.num_poles)
16 | create_mesh_se(xm, ym)
17 | if mcvkey_yoke ~= 'dummy' then
18 | def_mat_fm_nlin(xm, ym, 'blue', m.mcvkey_yoke, 100)
19 | else
20 | def_mat_air(xm, ym)
21 | end
22 | if(m.npols_gen>1) then
23 | rotate_copy_nodechains(x2, y2, x1, y1, x4, y4, x3, y3, m.npols_gen-1)
24 | end
25 |
--------------------------------------------------------------------------------
/src/femagtools/templates/rot_hsm.mako:
--------------------------------------------------------------------------------
1 | m.inside_diam = dy2
2 | m.rotor_diam = da2+2*ag
3 |
4 | m.gap_pol_shaft = ${model['gap_pol_shaft']*1e3}
5 | m.core_height = ${model['core_height']*1e3}
6 | m.pole_height = ${model['pole_height']*1e3}
7 | m.pole_rad = ${model['pole_rad']*1e3}
8 | m.core_width2 = ${model['core_width2']*1e3}
9 | m.core_width1 = ${model['core_width1']*1e3}
10 | m.pole_width_r = ${model['pole_width_r']*1e3}
11 | m.pole_width = ${model['pole_width']*1e3}
12 | m.slot_width = ${model['slot_width']*1e3}
13 | m.slot_height = ${model['slot_height']*1e3}
14 | m.damper_diam = ${model['damper_diam']*1e3}
15 | m.damper_div = ${model['damper_div']*1e3}
16 | m.mcvkey_yoke = mcvkey_yoke
17 |
18 | m.zeroangl = ${model.get('zeroangle', 0)}
19 | m.tot_num_sl = m.num_poles
20 | m.num_sl_gen = m.npols_gen
21 | m.airgap = ag
22 |
23 | pre_models("ROT_HSM")
24 |
25 | -- Yoke material
26 | if mcvkey_yoke ~= 'dummy' then
27 | x, y = pd2c( m.inside_diam/2+1, 360/m.num_poles/2)
28 | rellen = 100 -- relative length in %
29 | def_mat_fm_nlin(x, y, "blue", mcvkey_yoke, rellen)
30 | end
31 |
--------------------------------------------------------------------------------
/src/femagtools/templates/rotorKs2.mako:
--------------------------------------------------------------------------------
1 |
2 | Q1 = m.tot_num_sl
3 | Q2 = ${model['num_slots']}
4 | m.tot_num_sl = Q2
5 | % if model.get('num_slots_gen', 0):
6 | m.num_sl_gen = ${model['num_slots_gen']}
7 | % else:
8 | m.num_sl_gen = Q2 * m.npols_gen/m.num_poles
9 | % endif
10 |
11 | m.rotor_diam = da2
12 | m.inside_diam = dy2
13 | m.slot_angle = ${model.get('slot_angle')} -- Angle ALPHA [degr]
14 | m.slot_height = ${model.get('slot_height')*1e3} -- Total height H [mm]
15 | m.slot_topwidth = ${model.get('slot_topwidth')*1e3} -- Slot width top B [mm]
16 | m.slot_width = ${model.get('slot_width')*1e3} -- Slot width SW [mm]
17 | m.slot_h1 = ${model.get('slot_h1')*1e3} -- Distance H1 [mm]
18 | m.slot_h2 = ${model.get('slot_h2')*1e3} -- Distance H2 [mm]
19 | m.slot_r1 = ${model.get('slot_r1')*1e3} -- Radius R1 [mm]
20 | m.slot_r2 = ${model.get('slot_r2')*1e3} -- Radius R2 [mm]
21 | m.middle_line = ${model.get('middle_line')} -- Centerline: no: 0; vertic: 1; horiz:2
22 |
23 | m.zeroangl = ${model.get('zeroangl',0)}
24 | m.nodedist = ${model.get('nodedist',1)}
25 |
26 | m.mcvkey_yoke = mcvkey_yoke
27 | pre_models("ROTOR_KS2")
28 |
29 | dphi=1e-2
30 | if mcvkey_yoke ~= 'dummy' then
31 | m.rlength = ${model.get('rlength', 1)*100}
32 | x, y = pd2c(m.rotor_diam/2-m.slot_height/2,m.zeroangl+dphi)
33 | def_mat_fm_nlin(x, y, "blue", mcvkey_yoke, m.rlength)
34 |
35 | x, y = pd2c(m.inside_diam/2+(m.rotor_diam/2-m.inside_diam/2-m.slot_height)/2,m.zeroangl+dphi)
36 | def_mat_fm_nlin(x, y, "blue", mcvkey_yoke, m.rlength)
37 | end
38 | -- for winding gen
39 | if m.middle_line == 2 then
40 | taus = 2*math.pi/m.tot_num_slot
41 | r = da2/2 - m.slot_height/4
42 | m.xcoil_1, m.ycoil_1 = pr2c(r, taus/2)
43 | m.xcoil_2, m.ycoil_2 = pr2c(r-m.slot_height/2, taus/2)
44 | end
45 |
46 | -- set subregions 'Bar'
47 | r=da2/2 - m.slot_height/2
48 | phi=180/Q2+m.zeroangl
49 | x,y=pd2c(r,phi)
50 | delete_sreg(x, y)
51 | x,y=pd2c(r,phi-dphi)
52 | def_new_subreg( x,y, 'Bar', violet )
53 |
54 | for i=2, m.num_sl_gen do
55 | phi=(2*i-1)*180/Q2 + m.zeroangl
56 | x,y = pd2c(r,phi)
57 | add_to_subreg( x, y )
58 | end
59 |
--------------------------------------------------------------------------------
/src/femagtools/templates/rotor_winding.mako:
--------------------------------------------------------------------------------
1 | -- Winding (ROT_HSM or dxf)
2 | m.num_wires = ${model['num_wires']}
3 |
4 | phi = math.pi/m.num_poles
5 | if m.xcoil_r == nil then -- ROT_HSM
6 | a = m.rotor_diam/2 - ag - m.pole_height - m.core_height/2
7 | b = ((m.core_width1 + m.core_width2)/4 + m.pole_width/2)/2
8 | r = math.sqrt(a^2 + b^2)
9 | alpha = math.atan2(b, a)
10 | else
11 | r,beta = c2pr(m.xcoil_r, m.ycoil_r)
12 | alpha = phi - beta
13 | end
14 | dir = {'wi', 'wo'}
15 | xcoil, ycoil = pr2c(r, phi - alpha)
16 | def_new_wdg(xcoil, ycoil, yellow, "Exc", m.num_wires, 10.0, dir[1])
17 | xcoil, ycoil = pr2c(r, phi + alpha)
18 | add_to_wdg(xcoil, ycoil, wsamekey, dir[2], 'wser')
19 | for i = 2, m.npols_gen do
20 | n = (i+1) % 2 + 1
21 | phi = phi + 2*math.pi/m.num_poles
22 | xcoil, ycoil = pr2c(r, phi - alpha)
23 | add_to_wdg(xcoil, ycoil, wsamekey, dir[n], 'wser')
24 | xcoil, ycoil = pr2c(r, phi + alpha)
25 | n = i % 2 + 1
26 | add_to_wdg(xcoil, ycoil, wsamekey, dir[n], 'wser')
27 | end
28 |
--------------------------------------------------------------------------------
/src/femagtools/templates/shortcircuit.mako:
--------------------------------------------------------------------------------
1 | -- Short Circuit
2 | m.re_winding = ${model.get('r1',0)} -- Resistance stator winding Ra [Ohm]
3 | m.l_daxis = ${model.get('ld',0)} -- Inductance Ld [H/mm]
4 | m.l_qaxis = ${model.get('lq',0)} -- Inductance Lq [H/mm]
5 | m.l_endwindg = ${model.get('l_endwinding',0)} -- Stator ewdg inductance Le [H]
6 | m.l_external = ${model.get('l_external',0)} -- Stator external inductance Lex [H]
7 | m.magn_flux = ${model.get('psim',0)} -- Magn. flux (RMS) = Up/omega [Vs/mm]
8 | m.arm_length = ${model.get('lfe',0)*1e3} -- Effect. armature length lm [mm]
9 | m.current = ${model.get('current',0)} -- Current (operat. limit) (RMS) [A]
10 | m.angl_i_up = ${model.get('angl_i_up',0)} -- Angle current vs. voltage Vp [Deg]
11 | m.speed = ${model.get('speed',0)*60} -- Speed [1/min]
12 | m.num_pol_pair = ${model.get('num_pol_pair',0)} -- Number of Pole pairs p (>= 1)
13 | m.typ = ${model.get('sc_type',3)} -- Type of sc : 3ph = 3
14 | m.initial = ${model.get('initial',2)} -- Initial conditions: noload:1; load:2
15 | m.simultime = ${model.get('simultime',0.1)} -- Simulation time [s]
16 | m.fc_radius = ${model.get('fc_radius',0)*1e3} -- Radius air-gap center (torq.) [mm]
17 | m.num_par_wdgs = ${model.get('num_par_wdgs',0)} -- Number of parallel Windings(>= 1) a
18 | m.allow_demagn = ${model.get('allow_demagn',0)} -- Allow Demagnetisation:= 1:yes;= 0:no
19 | m.sim_demagn = ${model.get('sim_demagn',0)} -- Simulate Demagnetisation:1:yes; 0:no
20 |
21 | m.pocfilename = '${model.get('pocfilename','sin.poc')}'
22 |
23 | run_models("shortcircuit")
24 |
--------------------------------------------------------------------------------
/src/femagtools/templates/stator1.mako:
--------------------------------------------------------------------------------
1 | m.yoke_rad = dy1/2
2 | m.inside_rad = da1/2
3 |
4 | m.tip_rh2 = ${model['tip_rh2']*1e3}
5 | m.tip_rh1 = ${model['tip_rh1']*1e3}
6 | m.slot_rf1 = ${model['slot_rf1']*1e3}
7 | m.slot_rf2 = m.slot_rf1
8 | m.yoke_rad2 = m.yoke_rad
9 | m.slot_width = ${model['slot_width']*1e3}
10 | m.tooth_width = ${model['tooth_width']*1e3}
11 | m.zeroangl = ${model['zeroangle']}
12 | m.rlength = ${model['rlength']*100}
13 |
14 | m.mcvkey_yoke = mcvkey_yoke
15 | m.wdg_location = -1.0 -- stator (internal values)
16 |
17 | pre_models( "STATOR_1")
18 |
19 | if mcvkey_teeth ~= nil then
20 | x0, y0 = pr2c( (m.tip_rh1 + m.slot_rf1)/2, 2*math.pi/m.tot_num_slot + m.zeroangl/180*math.pi)
21 | def_mat_fm_nlin(x0, y0, "blue", mcvkey_teeth, m.rlength)
22 | end
23 |
--------------------------------------------------------------------------------
/src/femagtools/templates/stator2.mako:
--------------------------------------------------------------------------------
1 | m.yoke_rad = dy1/2
2 | m.inside_rad = da1/2
3 |
4 | m.slot_t1 = ${model['slot_t1']*1e3}
5 | m.slot_t2 = ${model['slot_t2']*1e3}
6 | m.slot_t3 = ${model['slot_t3']*1e3}
7 | m.slot_depth = ${model['slot_depth']*1e3}
8 | m.slot_width = ${model['slot_width']*1e3}
9 | m.corner_width = ${model['corner_width']*1e3}
10 | m.num_layer = ${model['num_layers']}
11 | m.zeroangl = ${model['zeroangle']}
12 | m.rlength = ${model['rlength']*100}
13 |
14 | m.mcvkey_yoke = mcvkey_yoke
15 | m.wdg_location = -1.0 -- stator (internal values)
16 |
17 | pre_models( "STATOR_2")
18 |
19 |
--------------------------------------------------------------------------------
/src/femagtools/templates/stator3Linear.mako:
--------------------------------------------------------------------------------
1 |
2 |
3 | m.cood_system = ${model.get('coord_system', 1)} -- 1: x/y or 2: r/z
4 |
5 | m.l_corner_x0 = 0.0
6 | m.l_corner_y0 = 0.0
7 | m.slot_height = ${model['slot_height']*1e3}
8 | m.slot_h1 = ${model['slot_h1']*1e3}
9 | m.slot_h2 = ${model['slot_h2']*1e3}
10 | m.tip_slot = ${model['tip_slot']*1e3}
11 | m.yoke_height = ${model['yoke_height']*1e3}
12 | m.slot_r1 = ${model['slot_r1']*1e3}
13 | m.slot_r2 = ${model['slot_r2']*1e3}
14 | m.width_bz = ${model['width_bz']*1e3}
15 | m.tooth_width = ${model['tooth_width']*1e3}
16 | m.slot_width = m.width_bz - m.tooth_width
17 |
18 | m.middle_line = ${model['middle_line']}
19 | m.zeroangl = 0.000 -- Reference angle to x-axis [grad]
20 |
21 | m.mcvkey_yoke = mcvkey_yoke
22 |
23 | pre_models("STATOR3_Linear");
24 |
--------------------------------------------------------------------------------
/src/femagtools/templates/stator4.mako:
--------------------------------------------------------------------------------
1 | m.yoke_diam = dy1
2 | m.inside_diam = da1
3 | if( m.el_order_ag == nil ) then
4 | m.el_order_ag = 1 -- El. order in air gap: lin=1: quadr=2
5 | end
6 | m.slot_height = ${model['slot_height']*1e3}
7 | m.slot_h1 = ${model['slot_h1']*1e3}
8 | m.slot_h2 = ${model['slot_h2']*1e3}
9 | m.slot_h3 = ${model['slot_h3']*1e3}
10 | m.slot_h4 = ${model['slot_h4']*1e3}
11 | m.slot_r1 = ${model['slot_r1']*1e3}
12 | m.slot_width = ${model['slot_width']*1e3}
13 | m.wedge_width1 = ${model['wedge_width1']*1e3}
14 | m.wedge_width2 = ${model['wedge_width2']*1e3}
15 | m.wedge_width3 = ${model['wedge_width3']*1e3}
16 |
17 | m.num_layer = ${model['num_layers']}
18 | m.zeroangl = ${model['zeroangle']}
19 |
20 | m.mcvkey_yoke = mcvkey_yoke
21 | m.wdg_location = -1.0 -- stator (internal values)
22 |
23 | pre_models( "STATOR_4")
24 |
25 | if mcvkey_teeth ~= nil then
26 | m.rlength = ${model.get('rlength', 1)*100}
27 | if da1 > da2 then
28 | r = (da1 + m.slot_height)/2
29 | else
30 | r = (da1 - m.slot_height)/2
31 | end
32 | x0, y0 = pr2c(r, 2*math.pi/m.tot_num_slot + m.zeroangl/180*math.pi)
33 | def_mat_fm_nlin(x0, y0, "blue", mcvkey_teeth, m.rlength)
34 | end
35 |
--------------------------------------------------------------------------------
/src/femagtools/templates/statorBG.mako:
--------------------------------------------------------------------------------
1 |
2 | m.yoke_diam = dy1
3 | m.inside_diam = da1
4 | m.yoke_diam_ins = ${model['yoke_diam_ins']*1e3}
5 | m.slot_h1 = ${model['slot_h1']*1e3}
6 | m.slot_h3 = ${model['slot_h3']*1e3}
7 | m.slot_width = ${model['slot_width']*1e3}
8 | m.slot_r1 = ${model['slot_r1']*1e3}
9 | m.slot_r2 = ${model['slot_r2']*1e3}
10 | m.tooth_width = ${model['tooth_width']*1e3}
11 | m.middle_line = ${model['middle_line']}
12 |
13 | m.tip_rad = ${model['tip_rad']*1e3}
14 | m.slottooth = ${model['slottooth']*1e3}
15 | m.wdg_location = -1.0 -- stator (internal values)
16 |
17 | m.zeroangl = ${model['zeroangle']}
18 |
19 | m.rlength = ${model['rlength']*100}
20 | m.mcvkey_yoke = mcvkey_yoke
21 |
22 | pre_models("STATOR_BG")
23 |
24 | if mcvkey_teeth ~= nil then
25 | r = (da1 + m.yoke_diam_ins)/4
26 | x0, y0 = pr2c(r, 2*math.pi/m.tot_num_slot + m.zeroangl/180*math.pi)
27 | def_mat_fm_nlin(x0, y0, "blue", mcvkey_teeth, m.rlength)
28 | end
29 |
--------------------------------------------------------------------------------
/src/femagtools/templates/stator_msh.mako:
--------------------------------------------------------------------------------
1 |
2 |
3 | read_msh("${model['name']}")
4 | x1, y1 = pd2c(dy1/2, 360/m.tot_num_slot/2)
5 | x2, y2 = pd2c(da1/2, 360/m.tot_num_slot/2)
6 | mirror_nodechains(x1, y1, x2, y2)
7 |
8 | x1, y1 = pd2c(da1/2, 0)
9 | x2, y2 = pd2c(dy1/2, 0)
10 | x3, y3 = pd2c(dy1/2, 360/m.tot_num_slot)
11 | x4, y4 = pd2c(da1/2, 360/m.tot_num_slot)
12 | rotate_copy_nodechains(x1, y1, x2, y2, x3, y3, x4, y4, m.num_sl_gen-1)
13 |
14 | -- airgap meshing
15 |
16 | x1, y1 = pd2c(da1/2, 0)
17 | x2, y2 = pd2c(da1/2 - ag/3, 0)
18 | x3, y3 = pd2c(da1/2 - ag/3, 360/m.tot_num_slot*m.num_sl_gen)
19 | x4, y4 = pd2c(da1/2, 360/m.tot_num_slot*m.num_sl_gen)
20 |
21 | nc_line(x1, y1, x2, y2, 2)
22 | nc_line(x3, y3, x4, y4, 2)
23 | nc_circle_m(x2, y2, x3, y3, 0, 0, num_agnodes+1)
24 | x1, y1 = pd2c(da1/2 - ag/6, 360/m.tot_num_slot*m.num_sl_gen/2)
25 | create_mesh_se(x1, y1)
26 |
27 | % for y in model['yoke']:
28 | x, y = ${model[y][0]*1e3}, ${model[y][1]*1e3}
29 | if( mcvkey_yoke ~= 'dummy' ) then
30 | def_mat_fm_nlin(x, y, "blue", mcvkey_yoke, 100) -- ${y}
31 | else
32 | def_mat_fm(x, y, "blue", 1000, 100) -- ${y}
33 | end
34 | % endfor
35 | % for t in model['teeth']:
36 | x, y = ${model[t][0]*1e3}, ${model[t][1]*1e3}
37 | if( mcvkey_yoke ~= 'dummy' ) then
38 | def_mat_fm_nlin(x, y, "blue", mcvkey_teeth, 100) -- ${t}
39 | else
40 | def_mat_fm_nlin(x, y, "blue", 1000, 100) -- ${t}
41 | end
42 | % endfor
43 | % for a in model['air']:
44 | x, y = ${model[a][0]*1e3}, ${model[a][1]*1e3}
45 | def_mat_air(x, y) -- ${a}
46 | % endfor
47 | % if 'wdg' in model:
48 | m.xcoil_1, m.ycoil_1 = ${model['wdg'][0]*1e3}, ${model['wdg'][1]*1e3}
49 | delete_sreg(m.xcoil_1, m.ycoil_1)
50 |
51 | r, phi = c2pd(m.xcoil_1, m.ycoil_1)
52 | for n = 1, m.num_sl_gen do
53 | s = tostring(n)
54 | x, y = pd2c( r, (n-1)*360/m.tot_num_slot + phi)
55 | def_new_sreg(x, y, s, 'white')
56 | x, y = pd2c(r, n*360/m.tot_num_slot - phi)
57 | add_to_sreg(x, y, s)
58 | end
59 | % else:
60 | m.xcoil_1, m.ycoil_1 = pd2c(da1/2 + (dy1-da1)/8, 360/m.tot_num_slot/2-0.1)
61 | create_mesh()
62 | % endif
63 |
--------------------------------------------------------------------------------
/src/femagtools/templates/therm_static.mako:
--------------------------------------------------------------------------------
1 | -- EXPERIMENTAL
2 | -- Caution: this will likely be modified
3 | --
4 | slots_gen = get_mod_data("num_slots")
5 | num_slots = get_dev_data("num_slots")
6 | state_of_problem("therm_static")
7 |
8 | beta = 360*slots_gen/num_slots
9 | m.zeroangl = 0
10 |
11 | heat_transfer_coefficient = ${model['heat_transfer_coefficient']}
12 | area_factor = 5
13 |
14 | % if 'inner_diam' in model and len(model['heat_transfer_coefficient'])>1:
15 | -- heat transfer inside
16 | dy2 = ${model['inner_diam']*1e3}
17 | x,y = pd2c(dy2/2-0.05, beta/2+m.zeroangl)
18 | % else:
19 | -- heat transfer outside
20 | dy1 = ${model['outer_diam']*1e3}
21 | x,y = pd2c(dy1/2+0.05, beta/2+m.zeroangl)
22 | def_heat_transfer(x,y,yellow,heat_transfer_coefficient, area_factor)
23 | %endif
24 | ---------------------------------------------
25 | -- import losses
26 | import_losses_from_femag_dc()
27 | -- overwrite magnet losses (IALH)
28 | %if not isinstance(model.get('magnet_loss_th', 0), list):
29 | printf('magnet losses from B2 Method')
30 | %else:
31 | printf('magnet losses from IAlH Method')
32 | %for i in model['magnet_loss_th']:
33 | elkeys = get_spel_data("elkeys", ${i[0]})
34 | x, y = get_elem_data("xycp", elkeys[1])
35 | def_losses ( x,y,'red', ${i[1]})
36 | %endfor
37 | %endif
38 |
39 | color_gradation_th(0,0,tot,Losses,0,0, "losses.svg")
40 |
41 | ---------------------------------------------
42 | calc_therm_field()
43 | color_gradation_th(0,0,tot,Temp,0.0,0, "temp.svg")
44 |
45 | state_of_problem("mag_static")
46 |
--------------------------------------------------------------------------------
/src/femagtools/utils.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 | def fft(pos, y, pmod=0):
4 | """calculate fft spectrum of y and return samples,
5 | values, amplitude and phase of base harmonic
6 |
7 | Arguments:
8 | pos: (list of floats) sample positions
9 | y: (list of floats) y values
10 | pmod: number of poles in model (ignored if 0)
11 | """
12 | model_angle = pos[-1] - pos[0]
13 | if 360/model_angle < 1:
14 | ntiles=1
15 | else:
16 | ntiles = int(round(360/model_angle))
17 |
18 | if pmod:
19 | negative_periodic = pmod % 2
20 | else:
21 | #negative_periodic = np.abs(y[0] - y[-1])/np.max(y) > 1
22 | # count zero crossings
23 | ypos = np.asarray(y)-np.mean(y) > 0
24 | nypos = ~ypos
25 | nzc = len(((ypos[:-1] & nypos[1:])
26 | | (nypos[:-1] & ypos[1:])).nonzero()[0])
27 | negative_periodic = nzc == 0 or nzc % 2 == 1
28 |
29 | if negative_periodic:
30 | yx = np.concatenate(
31 | [n*y[:-1]
32 | for n in [m % 2 or -1
33 | for m in range(1, ntiles+1)]])
34 | else:
35 | yx = np.tile(y[:-1], ntiles)
36 |
37 | N = len(yx)
38 | # compute DFT from induction (eliminate DC offset)
39 | a0 = np.mean(yx)
40 | Y = np.fft.fft(yx-a0)
41 |
42 | # find the peak (amplitude of base harmonic)
43 | i = np.argmax(np.abs(Y[:N//2]))
44 |
45 | a = 2*np.abs(Y[i])/N
46 | freq = np.fft.fftfreq(N, d=360/N)
47 | nmax = min(18*ntiles, N//2)
48 | T0 = 0
49 | if abs(freq[i]) > 0:
50 | T0 = np.abs(1/freq[i])
51 | npoles = 2*int(360/T0)
52 | nmax = min(9*npoles, N//2)
53 |
54 | alfa0 = np.angle(Y[i])
55 | alfa = np.angle(Y[:nmax])
56 |
57 |
58 | return {'a': a, 'a0': a0, 'T0': T0, 'alfa0': alfa0,
59 | 'alfa': alfa,
60 | 'nue': (2*np.abs(Y[:nmax])/N).tolist(),
61 | 'yi': yx.tolist()}
62 |
--------------------------------------------------------------------------------
/src/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/__init__.py
--------------------------------------------------------------------------------
/src/tests/data/AMELA:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | echo "succeed"
--------------------------------------------------------------------------------
/src/tests/data/AMELA.bat:
--------------------------------------------------------------------------------
1 | @echo succeed
--------------------------------------------------------------------------------
/src/tests/data/FERRIT_20gC.MCV:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/data/FERRIT_20gC.MCV
--------------------------------------------------------------------------------
/src/tests/data/M270-50A_1000Hz_L.jhb:
--------------------------------------------------------------------------------
1 | ./M270-50A_1000Hz_L.jhb
2 | 2 0.000
3 | 0.000 0.000
4 | 0.194 70.000
5 | 0.291 93.000
6 | 0.388 117.000
7 | 0.485 145.000
8 | 0.582 176.000
9 | 0.679 210.000
10 | 0.776 248.000
11 | 0.873 291.000
12 | 0.970 339.000
13 | 1.020 37124.230
14 | 1.070 75249.062
15 | 1.120 114310.867
16 | 1.170 153831.047
17 |
--------------------------------------------------------------------------------
/src/tests/data/TKM270-50A-LOSS.MCV:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/data/TKM270-50A-LOSS.MCV
--------------------------------------------------------------------------------
/src/tests/data/TKS-M400-65A.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/data/TKS-M400-65A.txt
--------------------------------------------------------------------------------
/src/tests/data/TKS_NO_20.MCV:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/data/TKS_NO_20.MCV
--------------------------------------------------------------------------------
/src/tests/data/V800-50A_aniso.MCV:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/data/V800-50A_aniso.MCV
--------------------------------------------------------------------------------
/src/tests/data/aniso.jhb:
--------------------------------------------------------------------------------
1 | aniso.jhb
2 | 3 0.000 90.000
3 | 0.100 33.960 16.980
4 | 0.200 47.000 23.500
5 | 0.300 56.300 28.150
6 | 0.400 64.600 32.300
7 | 0.500 72.790 36.395
8 | 0.600 80.390 40.185
9 | 0.700 89.820 44.910
10 | 0.800 100.610 50.305
11 | 0.900 114.390 57.195
12 | 1.000 134.070 67.035
13 | 1.050 147.920 73.960
14 | 1.100 166.190 83.085
15 | 1.150 191.010 95.505
16 | 1.200 228.320 114.160
17 | 1.250 288.840 144.420
18 | 1.301 397.660 198.830
19 | 1.351 617.220 308.610
20 | 1.401 1043.110 521.555
21 | 1.452 1738.700 896.350
22 | 1.504 2768.920 1384.460
23 | 1.555 4098.940 2046.470
24 | 1.607 5683.790 2841.895
25 | 1.712 9891.200 4945.600
26 | 1.793 14187.790 7093.895
27 | 1.854 20000.000 10000.000
28 | 1.913 30000.000 15000.000
29 | 1.977 50000.000 25000.000
30 | 2.028 75000.000 37500.000
31 | 2.069 100000.000 50000.000
32 | 2.211 200000.000 100000.000
33 | 2.341 300000.000 150000.000
34 | 2.470 400000.000 200000.000
35 | 2.597 500000.000 250000.000
36 | 2.724 600000.000 300000.000
37 | 2.850 700000.000 350000.000
38 | 2.976 800000.000 400000.000
39 | 3.102 900000.000 450000.000
40 | 3.228 1000000.000 500000.000
41 | 4.485 2000000.000 1000000.000
42 |
--------------------------------------------------------------------------------
/src/tests/data/cogging.BATCH:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/data/cogging.BATCH
--------------------------------------------------------------------------------
/src/tests/data/convert/Designer.jplot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/data/convert/Designer.jplot
--------------------------------------------------------------------------------
/src/tests/data/convert/quads.ISA7:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/data/convert/quads.ISA7
--------------------------------------------------------------------------------
/src/tests/data/convert/quads.nas:
--------------------------------------------------------------------------------
1 | $
2 | $ this is a comment
3 | $
4 | BEGIN BULK
5 | GRID 1 0. 0. 0.
6 | GRID 2 1. 0. 0.
7 | $ also a comment
8 | GRID 3 1. .5 0.
9 | GRID 4 1. 1. 0.
10 | GRID 5 0. 1. 0.
11 | GRID 6 0. .5 0.
12 | CQUAD4 1 1 1 2 3 6
13 | CQUAD4 2 1 6 3 4 5
14 | ENDDATA
15 | $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
16 | $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
17 |
--------------------------------------------------------------------------------
/src/tests/data/convert/superelements.nas:
--------------------------------------------------------------------------------
1 | $
2 | $ this is a comment
3 | $
4 | BEGIN BULK
5 | GRID 1 0. 0. 0.
6 | GRID 2 1. 0. 0.
7 | $ also a comment
8 | GRID 3 1. .5 0.
9 | GRID 4 1. 1. 0.
10 | GRID 5 0. 1. 0.
11 | GRID 6 0. .5 0.
12 | CTRIA3 1 2 3 4 6
13 | CTRIA3 1 1 4 5 6
14 | CQUAD4 2 2 1 2 3 6
15 | ENDDATA
16 | $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
17 | $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
18 |
--------------------------------------------------------------------------------
/src/tests/data/convert/triangles.ISA7:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/data/convert/triangles.ISA7
--------------------------------------------------------------------------------
/src/tests/data/convert/triangles.nas:
--------------------------------------------------------------------------------
1 | $
2 | $ this is a comment
3 | $
4 | BEGIN BULK
5 | GRID 1 0. 0. 0.
6 | GRID 2 1. 0. 0.
7 | $ also a comment
8 | GRID 3 1. 1. 0.
9 | GRID 4 0. 1. 0.
10 | CTRIA3 1 1 1 2 3
11 | CTRIA3 2 1 1 3 4
12 | ENDDATA
13 | $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
14 | $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
15 |
--------------------------------------------------------------------------------
/src/tests/data/dq.BATCH:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/data/dq.BATCH
--------------------------------------------------------------------------------
/src/tests/data/ldlq.erg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/data/ldlq.erg
--------------------------------------------------------------------------------
/src/tests/data/m270_35.vbf:
--------------------------------------------------------------------------------
1 | M235_35
2 | 50 1.5
3 | 7 19
4 | 50 100 200 400 500 1000 2000
5 | 0.10103 0.01859 0.04461 0.10782 0.2838 0.39409 1.16244 3.57408
6 | 0.20105 0.07684 0.17722 0.43127 1.13022 1.56273 4.45273 13.07317
7 | 0.30106 0.16358 0.37426 0.91707 2.4104 3.32623 9.37392 27.14519
8 | 0.40008 0.26768 0.62212 1.53547 4.04873 5.59287 15.76365 46.63288
9 | 0.50109 0.39037 0.91211 2.2716 6.00803 8.36762 23.62688 70.58197
10 | 0.60109 0.52917 1.24424 3.11803 8.32548 11.54513 33.63035 100.6593
11 | 0.70111 0.68284 1.61478 4.07599 10.9825 15.27785 45.09369 0
12 | 0.80013 0.85386 2.02498 5.14797 14.00635 19.56824 58.67124 0
13 | 0.90115 1.04347 2.48104 6.34264 17.45898 24.86492 74.72488 0
14 | 1.00118 1.25539 2.98914 7.70708 21.67625 30.61766 93.57929 0
15 | 1.10022 1.49457 3.56541 9.20166 26.22441 37.20815 115.6707 0
16 | 1.2013 1.77713 4.23834 10.96019 31.44426 44.76528 141.527 0
17 | 1.30049 2.12289 5.06866 13.09795 37.6766 53.71784 0 0
18 | 1.40116 2.50335 6.18773 16.00159 0 0 0 0
19 | 1.50311 2.89992 7.22253 18.82715 0 0 0 0
20 | 1.61841 3.35349 8.12348 0 0 0 0 0
21 | 1.71087 3.65588 0 0 0 0 0 0
22 | 1.81709 3.97809 0 0 0 0 0 0
23 | 1.92619 4.28171 0 0 0 0 0 0
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/tests/data/magnsec.AUX7:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/data/magnsec.AUX7
--------------------------------------------------------------------------------
/src/tests/data/magnsec.ISA7:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/data/magnsec.ISA7
--------------------------------------------------------------------------------
/src/tests/data/minimal.AUX7:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/data/minimal.AUX7
--------------------------------------------------------------------------------
/src/tests/data/minimal.ISA7:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/data/minimal.ISA7
--------------------------------------------------------------------------------
/src/tests/data/minimal.nc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/data/minimal.nc
--------------------------------------------------------------------------------
/src/tests/data/parident/bar.dat:
--------------------------------------------------------------------------------
1 | 2 0.00011541 3.57991e-07 3.57872e-07 3.5619e-07 3.49832e-07
2 | 10 0.00011581 3.5777e-07 3.57651e-07 3.55972e-07 3.49623e-07
3 | 18 0.000116736 3.57258e-07 3.5714e-07 3.55466e-07 3.49142e-07
4 | 26 0.000118173 3.56464e-07 3.56347e-07 3.54683e-07 3.48396e-07
5 | 34 0.000120097 3.55403e-07 3.55289e-07 3.53636e-07 3.47398e-07
6 | 42 0.000122477 3.54095e-07 3.53982e-07 3.52345e-07 3.46165e-07
7 | 50 0.000125276 3.5256e-07 3.5245e-07 3.50831e-07 3.44719e-07
8 | 58 0.000128454 3.50824e-07 3.50718e-07 3.49117e-07 3.43081e-07
9 | 66 0.000131968 3.48914e-07 3.48811e-07 3.47231e-07 3.41276e-07
10 | 74 0.000135773 3.46856e-07 3.46756e-07 3.45198e-07 3.39329e-07
11 | 82 0.000139824 3.44677e-07 3.44582e-07 3.43045e-07 3.37264e-07
12 | 90 0.000144079 3.42403e-07 3.42313e-07 3.408e-07 3.35108e-07
13 | 98 0.000148497 3.4006e-07 3.39973e-07 3.38483e-07 3.32882e-07
14 | 106 0.00015304 3.37671e-07 3.37586e-07 3.36121e-07 3.30609e-07
15 | 114 0.000157674 3.35254e-07 3.35173e-07 3.33731e-07 3.28306e-07
16 |
--------------------------------------------------------------------------------
/src/tests/data/pm_data.nc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/data/pm_data.nc
--------------------------------------------------------------------------------
/src/tests/data/test.poc:
--------------------------------------------------------------------------------
1 | 3
2 | 1
3 | 2
4 | 3
5 | 0
6 | 120
7 | 240
8 | 360.00000
9 | sin
10 | 30.000000
11 | 3
12 |
13 |
--------------------------------------------------------------------------------
/src/tests/data/test_disp_stat.ISA7:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/data/test_disp_stat.ISA7
--------------------------------------------------------------------------------
/src/tests/data/test_disp_stat.nc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/data/test_disp_stat.nc
--------------------------------------------------------------------------------
/src/tests/data/zzz_pm_model_ts.nc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/data/zzz_pm_model_ts.nc
--------------------------------------------------------------------------------
/src/tests/engines/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/engines/__init__.py
--------------------------------------------------------------------------------
/src/tests/engines/config.ini:
--------------------------------------------------------------------------------
1 | [amazon]
2 | iam_instance_profile = ecsInstanceRole
3 | key_name = test-key-pair-eucentral-1
4 | security_group_ids = sg-123456,
5 | server_location = eu-central-1
6 | instance_type = t2.small
7 |
8 |
--------------------------------------------------------------------------------
/src/tests/engines/data/cloud_init.txt:
--------------------------------------------------------------------------------
1 | Test Cloud init
2 | {{ENV}}
3 |
--------------------------------------------------------------------------------
/src/tests/engines/test_config.py:
--------------------------------------------------------------------------------
1 | import femagtools.config
2 | import os.path
3 | import platform
4 |
5 |
6 | def test_femag():
7 | if platform.system() == "Windows":
8 | expected = "wfemagw64"
9 | else:
10 | expected = "xfemag64"
11 |
12 | try:
13 | msg = femagtools.config.get_executable()
14 | except Exception as e:
15 | msg = str(e)
16 | assert msg.find(expected) > -1
17 |
18 |
19 | def test_engine_config():
20 | default_config = {
21 | 'ENGINE': 'amazon',
22 | 'INSTANCE_TYPE': 't2.micro'}
23 | config = femagtools.config.Config(default_config)
24 | ini_file = os.path.join(os.path.dirname(__file__), 'config.ini')
25 | config.from_ini_file(ini_file)
26 | assert config['KEY_NAME'] == 'test-key-pair-eucentral-1'
27 |
--------------------------------------------------------------------------------
/src/tests/geom/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/geom/__init__.py
--------------------------------------------------------------------------------
/src/tests/geom/test_functions.py:
--------------------------------------------------------------------------------
1 | import femagtools.dxfsl.geom as g
2 | import numpy as np
3 | import logging
4 | import pytest
5 |
6 |
7 | def test_alpha_points():
8 | p1 = (3.0, 1.0)
9 | p2 = (4.0, 5.0)
10 | p3 = (1.0, 3.0)
11 |
12 | alfa1 = g.alpha_points(p1, p2, p3)
13 | alfa2 = g.alpha_points(p2, p3, p1)
14 | alfa3 = g.alpha_points(p3, p1, p2)
15 |
16 | alfa = alfa1 + alfa2 + alfa3
17 | assert(np.isclose(alfa, 2*np.pi))
18 |
19 |
20 | def test_points_are_close():
21 | rtol = 1e-05
22 | atol = 1e-08
23 | p1 = (3.14, 2.7666)
24 | p2 = (3.141592, 2.77)
25 |
26 | A = g.points_are_close(p1, p2, rtol, atol)
27 | B = g.points_are_close(p1, p2, rtol, 0.001)
28 | assert(A == B)
29 |
30 | A = g.points_are_close(p1, p2, 1e-01, atol)
31 | B = g.points_are_close(p1, p2, 1e-02, atol)
32 | assert(A == B)
33 |
34 |
35 | def test_same_angle():
36 | assert(g.is_same_angle(3.14159266, np.pi))
37 | assert(g.is_same_angle(3.14159266, -np.pi))
38 |
39 |
40 | def test_misc():
41 | assert(g.gcd(4, 5) == 1)
42 | assert(g.gcd(24, 6) == 6)
43 | assert(g.gcd(47, 23) == 1)
44 | assert(g.gcd(18, 3) == 3)
45 | assert(g.gcd(39, 13) == 13)
46 |
47 |
48 | if __name__ == "__main__":
49 |
50 | logging.basicConfig(level=logging.INFO,
51 | format='%(asctime)s %(message)s')
52 |
53 | test_alpha_points()
54 | test_points_are_close()
55 | test_same_angle()
56 | test_misc()
57 |
--------------------------------------------------------------------------------
/src/tests/mcvwriter:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #
3 | # dummy mcvwriter
4 | #
5 | cat > dummy.mc
6 |
7 |
--------------------------------------------------------------------------------
/src/tests/moo/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SEMAFORInformatik/femagtools/7023116e47c0718b9966c897481648830dfb5121/src/tests/moo/__init__.py
--------------------------------------------------------------------------------
/src/tests/moo/test_problem.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | import unittest
4 | from femagtools import moo
5 |
6 |
7 | class ProblemTest(unittest.TestCase):
8 | def test_compare_fc(self):
9 | prob = moo.Problem(0, 0, 2)
10 | f1 = (0, 0)
11 | f2 = (1, 1)
12 | c1 = []
13 | c2 = []
14 | self.assertTrue(prob.compare_fc(f1, c1, f2, c2))
15 | self.assertFalse(prob.compare_fc(f2, c2, f1, c1))
16 | self.assertFalse(prob.compare_fc(f2, c2, f2, c2))
17 |
18 | if __name__ == '__main__':
19 | unittest.main()
20 |
--------------------------------------------------------------------------------
/src/tests/test_airgap_induction.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | import femagtools.airgap as ag
4 | import numpy as np
5 | import os
6 |
7 |
8 | def test_airgap_induction():
9 | testPath = os.path.join(os.path.split(__file__)[0], 'data')
10 | if len(testPath) == 0:
11 | testPath = os.path.join(os.path.abspath('.'), 'data')
12 | r = ag.read(os.path.join(testPath, 'bag.dat'))
13 | np.testing.assert_almost_equal(r['Bamp'], 1.26914, 3)
14 | assert r['npoles'] == 8
15 | harms = [nue for nue, amp in zip(r['nue'],
16 | r['B_nue']) if amp > 1e-2]
17 |
18 | assert harms == [4, 12, 20, 28, 36, 44, 52, 60, 68]
19 |
20 | def test_airgap_induction2():
21 | testPath = os.path.join(os.path.split(__file__)[0], 'data')
22 | if len(testPath) == 0:
23 | testPath = os.path.join(os.path.abspath('.'), 'data')
24 | r = ag.read(os.path.join(testPath, 'bag2.dat'))
25 | np.testing.assert_almost_equal(r['Bamp'], 0.9272, 3)
26 | assert r['npoles'] == 32
27 | harms = [nue for nue, amp in zip(r['nue'],
28 | r['B_nue']) if amp > 1e-2]
29 |
30 | assert harms == [16, 48, 80, 112, 144, 176, 208, 272]
31 |
--------------------------------------------------------------------------------
/src/tests/test_amela.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | import json
3 | from femagtools import amela
4 | from pathlib import Path
5 |
6 | def read_output():
7 | return (Path(__file__).parent/ "data/amela.out").read_text().split('\n')[0]
8 |
9 | def read_json():
10 | return json.loads(
11 | (Path(__file__).parent/"data/pm_data/pm_data_se38.json").read_text())
12 |
13 | def test_amela():
14 | al = amela.Amela(workdir='src/tests/data',
15 | magnet_data=dict(name='pm_data'))
16 | loss = al()
17 | r = read_json()
18 | assert r['name'] == 'pm_data_se38'
19 | assert len(r['phi']) == 73
20 | assert read_output() == 'succeed'
21 | assert round(loss['pm_data_se38']['total_loss'], 3) == 0.881
22 |
--------------------------------------------------------------------------------
/src/tests/test_asm.py:
--------------------------------------------------------------------------------
1 | import femagtools.asm
2 | import pathlib
3 | import pytest
4 |
5 | expected = {'version': '9.2.x-202-geff049a1',
6 | 'project': './LS4p.nc', 'filename': 'TEST_001', 'date': '2021-05-27T13:23',
7 | 'wdgconn': 'star',
8 | 'f1': [50.0, 50.0, 50.0], 'r1': 1.2, 'lfe': 160.0,
9 | 'rbarlen': 246.0, 'num_phases': 3, 'p': 2, 'p_gen': 1,
10 | 'num_par_wdgs': 1, 'mcfile': 'M330-50A',
11 | 'felosscoeff': 1.44, 'maxiters': 300,
12 | 'permchg': 0.0, 's': [0.0, 0.025, 0.05], 'T': [0.0, 48.8, 92.4],
13 | 'u1': [380.0, 380.0, 380.0],
14 | 'Tp2': [0.0, 45.5, 84.7], 'p2': [0.0, 179.0, 665.0], 'pfe1': [],
15 | 'i1': [8.52, 14.9, 25.3], 'p1': [0.0, 7230.0, 13600.0],
16 | 'cosphi': [0.0, 0.738, 0.818],
17 | 'pcu': [261.32544, 799.236, 2304.324],
18 | 'pltotal': [261.32544, 978.236, 2969.324],
19 | 'lh': 0.079515, 'ls1': 0.00245,
20 | 'ls2': 0.00925, 'r2': 0.406538, 'sk': 0.1135}
21 |
22 |
23 | def test_read_asm():
24 | datadir = pathlib.Path(__file__).resolve().parent.joinpath('data')
25 |
26 | content = (datadir / 'test.ASM').read_text()
27 | r = femagtools.asm.read(content.split('\n'))
28 | assert r.keys() == expected.keys()
29 | for k in r.keys():
30 | if isinstance(r[k], float) or isinstance(r[k], list):
31 | assert pytest.approx(r[k], rel=0.01) == expected[k]
32 | else:
33 | assert r[k] == expected[k]
34 |
--------------------------------------------------------------------------------
/src/tests/test_conductor.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | #
4 | import femagtools.conductor
5 |
6 | condMat = [dict(
7 | name="Cu",
8 | spmaweight=8.96,
9 | elconduct=56e6,
10 | tempcoef=3.9e-3)
11 | ]
12 |
13 |
14 | def test_findById():
15 | cond = femagtools.conductor.Conductor(condMat)
16 | result = cond.find('Cu')
17 | expected = condMat[0]
18 | assert result == expected
19 |
--------------------------------------------------------------------------------
/src/tests/test_dxfsl.py:
--------------------------------------------------------------------------------
1 | import pathlib
2 | from femagtools.dxfsl.converter import convert
3 |
4 | def test_convert():
5 | p = pathlib.Path(__file__).parent / 'data' / 'IPM-130-4.dxf'
6 | r = convert(str(p))
7 |
8 | assert r['num_poles'] == 4
9 | assert r['tot_num_slot'] == 12
10 | totnumsl = [l for l in r['fsl'] if l.startswith('m.tot_num_slot')]
11 | assert len(totnumsl) == 1
12 | assert totnumsl[0].split()[-1] == '12'
13 |
--------------------------------------------------------------------------------
/src/tests/test_effloss.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | import pytest
4 | import femagtools.machine.effloss
5 |
6 |
7 | @pytest.fixture
8 | def impars():
9 | return {'p': 2, 'm': 3, 'f1ref': 50, 'u1ref': 230.94, 'rotor_mass': 12.19, 'kfric_b': 1,
10 | 'r1': 0.2, 'r2': 0.54459629551,
11 | 'lsigma1': 0.0009996977709180593, 'lsigma2': 0.006836872295316844,
12 | 'psiref': 0.728735006166921, 'wref': 314.1592653589793,
13 | 'fec': 64.10000000000001, 'fee': 0, 'fexp': 7.0,
14 | 'im': [2.043764851047857, 4.087529702095714, 6.1312945531435705,
15 | 8.175059404191428, 10.218824255239285],
16 | 'psi': [0.27117452078113785, 0.5286659550273167, 0.7135568973434478,
17 | 0.8133415467307101, 0.8671946085010127]}
18 |
19 |
20 | def test_imeffloss(impars):
21 | nmax = 8000/60
22 | T = 32.9
23 | u1 = 230
24 | temp = (120, 120)
25 |
26 | r = femagtools.machine.effloss.efficiency_losses_map(
27 | impars, u1, T, temp, nmax, npoints=(5, 4))
28 | assert r['T'] == pytest.approx(
29 | [-32.9, -0.5, 0.4, 32.9,
30 | -16.7, -0.5, 0.4, 15.8,
31 | -10.8, -0.5, 0.4, 10.1,
32 | -8.0, -0.5, 0.4, 7.4,
33 | -6.4, -0.5, 0.4, 6.0], abs=1e-1)
34 |
--------------------------------------------------------------------------------
/src/tests/test_erg.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | import os
4 | import femagtools.erg
5 | import numpy as np
6 |
7 |
8 | def read_erg(filename):
9 | testPath = os.path.join(os.path.split(__file__)[0], 'data')
10 | if len(testPath) == 0:
11 | testPath = os.path.join(os.path.abspath('.'), 'data')
12 | r = femagtools.erg.read(os.path.join(testPath, filename))
13 | return r
14 |
15 |
16 | def test_read_erg():
17 | r = read_erg('ldlq.erg')
18 | assert len(r.keys()) == 14
19 | assert min(r['beta']) == -90.0
20 | assert max(r['beta']) == 0.0
21 | np.array(r['M_FE']).shape == (10, 10)
22 |
23 |
--------------------------------------------------------------------------------
/src/tests/test_forcedens.py:
--------------------------------------------------------------------------------
1 |
2 | from femagtools import forcedens
3 |
4 |
5 | def test_plt_read():
6 | filename = 'src/tests/data/PLT.0'
7 | fdens = forcedens.ForceDensity()
8 | fdens.read(filename)
9 |
10 | assert fdens.title == 'Load PM-Syn_motor airgap 1, No Skewing'
11 | assert len(fdens.positions) == 31
12 | assert sorted(fdens.positions[0].keys()) == ['B_N', 'B_T', 'FN', 'FT',
13 | 'Radius', 'X',
14 | 'column_units', 'position',
15 | 'unit']
16 |
--------------------------------------------------------------------------------
/src/tests/test_heat_source_network.py:
--------------------------------------------------------------------------------
1 | import femagtools.heat_source_network as hsn
2 | import pathlib
3 | import pytest
4 |
5 |
6 | @pytest.fixture
7 | def data_dir():
8 | return pathlib.Path(__file__).with_name('data')
9 |
10 |
11 | def test_heat_source_network(data_dir):
12 | model = hsn.read(str(data_dir / 'temp_model.hsn'))
13 | assert [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13] == model.nodes
14 | names = model.get_node_names()
15 | assert ['StZa', 'outs', 'StJo', 'Slot',
16 | 'Shaf', 'Iron', 'PMag', 'PMag',
17 | 'W1 ', 'W2 ', 'W3 '] == names
18 | T = model.solve()
19 | # [130.22552926, 56.75737966, 116.12788806, 150.18881253,
20 | # 175.77455152, 175.77455152, 175.77526274, 175.77455152,
21 | # 126.04691063, 122.49609205, 125.27401647])
22 |
--------------------------------------------------------------------------------
/src/tests/test_hxy.py:
--------------------------------------------------------------------------------
1 | import femagtools.hxy
2 | import pathlib
3 | import pytest
4 |
5 |
6 | @pytest.fixture
7 | def data_dir():
8 | return pathlib.Path(__file__).with_name('data') / 'hxy'
9 |
10 |
11 | def test_read(data_dir):
12 | num_magnets = 2
13 | magnets = femagtools.hxy.read(data_dir / 'PM270L8_011.hxy',
14 | num_magnets)
15 | assert len(magnets) == num_magnets
16 | assert set([len(m['e'][0]) for m in magnets]) == {169, 189}
17 | assert [m['pos'][0] for m in magnets] == [0.0, 0.0]
18 | assert sorted([m['havg'][0] for m in magnets]) == pytest.approx([156.3, 156.5], 0.1)
19 | assert sorted([m['hmax'][0] for m in magnets]) == pytest.approx([195.6, 304.4], 0.1)
20 |
--------------------------------------------------------------------------------
/src/tests/test_im.py:
--------------------------------------------------------------------------------
1 | import femagtools.machine.im
2 | import pathlib
3 | import pytest
4 | import numpy as np
5 |
6 |
7 | @pytest.fixture
8 | def im():
9 | impars = {
10 | "p": 2, "m": 3, "f1type": 50, "u1type": 230, "rotor_mass": 6, "kfric_b": 1,
11 | "r1": 0.2, "r2": 0.5389, "lsigma1": 2e-3,
12 | "lsigma2": 4.4e-3, "kh": 10, "zeta2": 1,
13 | "fec": 120, "fee": 0, "fexp": 7.0,
14 | "iml": 5.317456519935536, "ims": 3.425169199057511, "mexp": 8.75033417091787}
15 | return femagtools.machine.im.InductionMachine(impars)
16 |
17 |
18 | def test_im(im):
19 | u1 = 230
20 | f1 = 50
21 | s = 0.01
22 | torque = im.torqueu(2*np.pi*f1, u1, 2*np.pi*(1-s)*f1/im.p)
23 | assert pytest.approx(torque, rel=0.01) == 17.77
24 |
--------------------------------------------------------------------------------
/src/tests/test_jhb.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | import os
4 | import femagtools.jhb
5 |
6 |
7 | def test_read_jhb():
8 | testPath = os.path.split(__file__)[0]
9 | if not testPath:
10 | testPath = '.'
11 | filename = "data/M270-50A_1000Hz_L.jhb"
12 | jhb = femagtools.jhb.Reader('{0}/{1}'.format(testPath, filename))
13 | assert jhb['name'] == 'M270-50A_1000Hz_L'
14 | assert len(jhb['curve']) == 1
15 | assert len(jhb['curve'][0]['hi']) == 13
16 | assert jhb['curve'][0]['bi'][-1] == 1.17
17 |
18 |
19 | def test_read_jhb_aniso():
20 | testPath = os.path.split(__file__)[0]
21 | if not testPath:
22 | testPath = '.'
23 | filename = "data/aniso.jhb"
24 | jhb = femagtools.jhb.Reader('{0}/{1}'.format(testPath, filename))
25 | assert jhb['name'] == 'aniso'
26 | assert len(jhb['curve']) == 2
27 | assert len(jhb['curve'][0]['hi']) == 39
28 | assert jhb['curve'][0]['bi'][-1] == 4.485
29 |
30 |
--------------------------------------------------------------------------------
/src/tests/test_job.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | import femagtools.job
4 | import tempfile
5 | import os
6 |
7 |
8 | def test_condor():
9 | workdir = tempfile.mkdtemp()
10 | job = femagtools.job.CondorJob(workdir)
11 | task = job.add_task()
12 | task.add_file('femag.fsl', ['exit_on_end=True'])
13 | try:
14 | job.prepareDescription()
15 |
16 | with open(os.path.join(workdir, 'femag.submit')) as f:
17 | x = [l.strip().split('=') for l in f]
18 |
19 | len(x) == 12
20 | x[-1][0].split() == '1'
21 |
22 | d = {l[0].strip(): l[1].strip() for l in x if len(l) > 1}
23 | d['Universe'] == 'vanilla'
24 | except Exception as e:
25 | pass # no femag installed on ci server.
26 |
27 |
28 | def test_job():
29 | workdir = tempfile.mkdtemp()
30 | job = femagtools.job.Job(workdir)
31 | task = job.add_task()
32 | task.add_file('femag.fsl', ['exit_on_end=True'])
33 |
34 | with open(os.path.join(workdir, '0/femag.fsl')) as f:
35 | x = [l.strip().split('=') for l in f]
36 | d = {k: v for k, v in x}
37 | d['exit_on_end'] == 'True'
38 |
--------------------------------------------------------------------------------
/src/tests/test_magnet.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | #
4 | import femagtools.magnet
5 |
6 | magMat = [dict(
7 | name="M395",
8 | remanenc=1)
9 | ]
10 |
11 |
12 | def test_findById():
13 | mag = femagtools.magnet.Magnet(magMat)
14 | result = mag.find('M395')
15 | expected = magMat[0]
16 | assert result == expected
17 |
--------------------------------------------------------------------------------
/src/tests/test_me.py:
--------------------------------------------------------------------------------
1 | from femagtools import me
2 |
3 | def test_me():
4 | r = me.get_eigenvectors(['src/tests/data/Mode_001.txt'], [])
5 | assert r[2]['0']['eigenvecs'].shape[0] == 5796
6 | assert round(r[1][0], 2) == 52.07
7 |
--------------------------------------------------------------------------------
/src/tests/test_parident.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import femagtools.machine
3 | from femagtools.job import Task
4 | import pathlib
5 | import pytest
6 |
7 |
8 | @pytest.fixture
9 | def data_dir():
10 | return pathlib.Path(__file__).with_name('data')
11 |
12 |
13 | def test_ecsim_eval(data_dir):
14 | task = Task(id=1, directory=data_dir / 'parident')
15 | eval = femagtools.machine.im._eval_ecsim()
16 | r = eval(task)
17 | expected = {'r2': 0.00011541,
18 | 'ls2': 3.57991e-07,
19 | 'zeta2': 0.9891,
20 | 'pl2v': 0.913}
21 | assert expected['r2'] == r['r2']
22 | assert expected['ls2'] == r['ls2']
23 | assert expected['zeta2'] == round(r['zeta2'], 4)
24 | assert expected['pl2v'] == round(r['pl2v'], 3)
25 |
26 |
27 | def test_noloadrot_eval(data_dir):
28 | task = Task(id=1, directory=data_dir / 'parident')
29 | i1tab = [2.0384197650236815, 4.076839530047363,
30 | 6.115259295071045, 8.153679060094726, 10.192098825118407]
31 | u1ph = 400/np.sqrt(3)
32 | pmod = 0
33 | eval = femagtools.machine.im._eval_noloadrot(pmod)
34 | r = eval(task)
35 | i0 = [2.0384, 4.0768, 6.1153, 8.1537, 10.1921]
36 | psi1_0 = [0.2725, 0.5301, 0.7106, 0.8091, 0.8641]
37 | #Bamp = [0.3091, 0.6013, 0.8058, 0.9159, 0.9768]
38 | Bamp = [0.3001, 0.5836, 0.7809, 0.8866, 0.9453]
39 | assert i0 == [round(x, 4) for x in r['i1_0']]
40 | assert psi1_0 == [round(x, 4) for x in np.mean(r['psi1_0'], axis=1)]
41 | assert Bamp == [round(x, 4) for x in np.mean(r['Bamp'], axis=1)]
42 |
--------------------------------------------------------------------------------
/src/tests/test_sizing.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | import pytest
4 | import femagtools.machine.sizing
5 |
6 |
7 | def test_im():
8 | P = 1.5e3
9 | fs = 12e3
10 | lda = 0.9
11 | p = 4
12 | f1 = 100
13 | n = f1/p
14 | udc = 550
15 | r = femagtools.machine.sizing.im(P, n, p, udc=udc,
16 | sigmas=fs, Ba=0.77,
17 | cos_phi=0.8, eta=0.8,
18 | lda=0.9, rtype='statorRotor3')
19 | assert round(r['outer_diam'], 3) == 0.182
20 | assert r['stator']['num_slots'] == 36
21 |
22 |
23 | def test_spm():
24 | P = 1.5e3
25 | fs = 12e3
26 | lda = 0.9
27 | p = 4
28 | f1 = 100
29 | n = f1/p
30 | udc = 550
31 |
32 | r = femagtools.machine.sizing.spm(P, n, p, udc=udc,
33 | Hc=700, sigmas=fs, brem=1.1, Ba=0.77,
34 | cos_phi=0.7, eta=0.8, demag=6.8,
35 | lda=0.9)
36 | assert round(r['outer_diam'], 3) == 0.181
37 | assert r['stator']['num_slots'] == 24
38 |
39 |
40 | def test_eesm():
41 | P = 10e3
42 | speed = 4440/60
43 | p = 4
44 | udc = 600
45 | r = femagtools.machine.sizing.eesm(P, speed, p, udc=udc, Q1=36)
46 | assert r['rotor']['rot_hsm']
47 |
--------------------------------------------------------------------------------
/src/tests/test_tksreader.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | import os
4 | import femagtools.tks
5 |
6 |
7 | def test_read_tks():
8 | testPath = os.path.split(__file__)[0]
9 | if not testPath:
10 | testPath = '.'
11 | filename = "data/TKS-M400-65A.txt"
12 | tks = femagtools.tks.Reader('{0}/{1}'.format(testPath, filename))
13 | assert tks['name'] == 'TKS-M400-65A'
14 | assert len(tks['losses']['f']) == 4
15 | assert len(tks['losses']['B']) == 13
16 | assert len(tks['losses']['pfe']) == 4
17 | assert len(tks['losses']['pfe'][0]) == 13
18 | assert tks['losses']['f'] == [50.0, 100.0, 200.0, 400.0]
19 | assert round(tks['losses']['B'][-1], 1) == 1.8
20 | # 13.1279112, 17.92205587, 23.79869172, 30.84129721, 39.3434623, 48.97389844, 60.25629981, 72.88007909
21 | assert len([x for x in tks['losses']['pfe'][3] if x]) == 8
22 |
--------------------------------------------------------------------------------
/src/tests/test_ts.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from femagtools import ts
3 |
4 |
5 | @pytest.fixture
6 | def losses():
7 | dirname = 'src/tests/data/zzz_pm_model_ts_results_1'
8 | modelname = 'src/tests/data/zzz_pm_model_ts'
9 | return ts.Losses(modelname, dirname)
10 |
11 |
12 | def test_read(losses):
13 | e = losses.ohm_lossenergy(0.0, 0.0)
14 | assert len(e) == 6
15 | assert {'key': 1, 'name': 'stfe', 'losses': 0.0} == e[0]
16 | assert {'key': 2, 'name': 'rofe', 'losses': 0.0} == e[1]
17 | assert {'key': 3, 'name': 'wefe', 'losses': 0.0} == e[2]
18 | assert pytest.approx(
19 | {'key': 4, 'name': '', 'losses': 0.001913}, abs=1e-5) == e[3]
20 | assert pytest.approx(
21 | {'key': 5, 'name': '', 'losses': 0.001967}, abs=1e-5) == e[4]
22 | assert pytest.approx(
23 | {'key': 6, 'name': '', 'losses': 0.001886}, abs=1e-5) == e[5]
24 | p = losses.ohm_powerlosses()
25 | assert len(p) == 6
26 | assert {'key': 1, 'name': 'stfe', 'losses': 0.0} == p[0]
27 | assert {'key': 2, 'name': 'rofe', 'losses': 0.0} == p[1]
28 | assert {'key': 3, 'name': 'wefe', 'losses': 0.0} == p[2]
29 | assert pytest.approx(
30 | {'key': 4, 'name': '', 'losses': 0.09809}, abs=1e-5) == p[3]
31 | assert pytest.approx(
32 | {'key': 5, 'name': '', 'losses': 0.10102}, abs=1e-5) == p[4]
33 | assert pytest.approx(
34 | {'key': 6, 'name': '', 'losses': 0.09673}, abs=1e-5) == p[5]
35 | p = losses.ohm_powerlosses_fft()
36 | assert len(p) == 6
37 | assert {'key': 1, 'name': 'stfe', 'losses': 0.0} == p[0]
38 | assert {'key': 2, 'name': 'rofe', 'losses': 0.0} == p[1]
39 | assert {'key': 3, 'name': 'wefe', 'losses': 0.0} == p[2]
40 | assert pytest.approx(
41 | {'key': 4, 'name': '', 'losses': 0.101086}, abs=1e-5) == p[3]
42 | assert pytest.approx(
43 | {'key': 5, 'name': '', 'losses': 0.101086}, abs=1e-5) == p[4]
44 | assert pytest.approx(
45 | {'key': 6, 'name': '', 'losses': 0.101086}, abs=1e-5) == p[5]
46 |
--------------------------------------------------------------------------------
/src/tests/test_vbfreader.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | import unittest
4 | import os
5 | import femagtools.vbf
6 |
7 |
8 | class VbfReaderTest(unittest.TestCase):
9 | def test_read_vbf(self):
10 | testPath = os.path.split(__file__)[0]
11 | if not testPath:
12 | testPath = '.'
13 |
14 | filename = "data/m270_35.vbf"
15 | vbf = femagtools.vbf.Reader('{0}/{1}'.format(testPath, filename))
16 | r = vbf.getLossValues()
17 | self.assertEqual(r['name'], 'M235_35')
18 | self.assertEqual(len(r['f']), 7)
19 | self.assertEqual(len(r['B']), 19)
20 | self.assertEqual(len(r['pfe']), 19)
21 | self.assertEqual(len(r['pfe'][0]), 7)
22 | self.assertAlmostEqual(r['f'][-1], 2000.0, 1)
23 | self.assertAlmostEqual(r['B'][-1], 1.926, 3)
24 | self.assertAlmostEqual(r['pfe'][3][-1], 46.633, 3)
25 |
26 | if __name__ == '__main__':
27 | unittest.main()
28 |
--------------------------------------------------------------------------------
/src/tests/test_vtu.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | import pathlib
3 | from femagtools import vtu
4 |
5 |
6 | @pytest.fixture
7 | def ts_data_dir():
8 | return pathlib.Path(__file__).with_name('data') / 'zzz_pm_model_ts_results_1/'
9 |
10 | @pytest.fixture
11 | def demag_data_dir():
12 | return pathlib.Path(__file__).with_name('data') / 'demag-vtu/'
13 |
14 |
15 | def test_read(ts_data_dir):
16 | vtu_data = vtu.read(ts_data_dir / 'zzz_pm_model_ts_0000.vtu')
17 | assert vtu_data.field_data_names == [
18 | 'time [s]', 'angle [rad]',
19 | 'speed [rad/s]', 'torque [Nm]',
20 | 'winding 1 current [A]', 'winding 1 voltage [V]',
21 | 'winding 2 current [A]', 'winding 2 voltage [V]',
22 | 'winding 3 current [A]', 'winding 3 voltage [V]', 'branch names']
23 | assert vtu_data.point_data_names == ['vector potential']
24 | assert vtu_data.cell_data_names == [
25 | 'b', 'curd', 'demagnetization', 'current [A]', 'voltage [V]']
26 |
27 | b = vtu_data.get_data_vector('b', 1)
28 | assert b[0] == pytest.approx([-0.003114], abs=1e-5)
29 | assert b[1] == pytest.approx([-0.00313], abs=1e-5)
30 | assert b[2] == [0.0]
31 |
32 | def test_demag(demag_data_dir):
33 | vtu_data = vtu.read(demag_data_dir / 'PM_130_L10_0000.vtu')
34 | keys = [7412, 7413, 7414, 7415, 7416]
35 | class Element:
36 | def __init__(self, key):
37 | self.key = key
38 | elements = [Element(k) for k in keys]
39 | expected = [241.5, 250.2, 262.3, 276.5, 390.5]
40 | actual = vtu_data.demag(elements)
41 | assert len(actual) == 1
42 | assert actual[0] == pytest.approx(expected, abs=0.1)
43 |
--------------------------------------------------------------------------------
/tox.ini:
--------------------------------------------------------------------------------
1 | # Tox (http://tox.testrun.org/) is a tool for running tests
2 | # in multiple virtualenvs. This configuration file will run the
3 | # test suite on all supported python versions. To use it, "pip install tox"
4 | # and then run "tox" from this directory.
5 |
6 | [tox]
7 | envlist = py27,py34,py35,py36
8 |
9 | [testenv]
10 | commands = py.test tests {posargs}
11 | deps =
12 | pytest
13 | femagtools
14 | matplotlib
15 | py27: mock
16 |
17 | [travis]
18 | python =
19 | 2.7: py27
20 | 3.4: py34
21 | 3.5: py35
22 | 3.6: py36
--------------------------------------------------------------------------------