{"id":26965573,"url":"https://github.com/zubax/jafit","last_synced_at":"2026-04-02T01:53:47.070Z","repository":{"id":273844594,"uuid":"912846901","full_name":"Zubax/jafit","owner":"Zubax","description":"Jiles-Atherton system identification tool: Given a B(H) curve, finds the Jiles-Atherton model coefficients. Supports various JA model formulations. Has an interactive GUI.","archived":false,"fork":false,"pushed_at":"2025-03-29T22:33:56.000Z","size":28105,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-29T23:23:45.530Z","etag":null,"topics":["hysteresis-loop","jiles-atherton","magnet","magnetism","model-fitting","system-identification"],"latest_commit_sha":null,"homepage":"https://zubax.com","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Zubax.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-06T14:12:58.000Z","updated_at":"2025-03-29T22:33:59.000Z","dependencies_parsed_at":"2025-03-06T13:42:34.531Z","dependency_job_id":null,"html_url":"https://github.com/Zubax/jafit","commit_stats":null,"previous_names":["zubax/jafit"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Zubax%2Fjafit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Zubax%2Fjafit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Zubax%2Fjafit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Zubax%2Fjafit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Zubax","download_url":"https://codeload.github.com/Zubax/jafit/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246955823,"owners_count":20860365,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hysteresis-loop","jiles-atherton","magnet","magnetism","model-fitting","system-identification"],"created_at":"2025-04-03T07:30:04.698Z","updated_at":"2026-04-02T01:53:47.060Z","avatar_url":"https://github.com/Zubax.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# jafit\n\n[![Discuss - on Zubax Forum](https://img.shields.io/static/v1?label=Discuss\u0026message=on+Zubax+Forum\u0026color=ff0000)](https://forum.zubax.com)\n\nJiles-Atherton system identification tool: Given a hysteresis loop, finds the Jiles-Atherton model coefficients.\nSupports several JA model definitions.\n\n\u003cimg src=\"image.png\" width=\"800\" alt=\"\"\u003e\n\n## Usage\n\n### Install the tool\n\n```shell\ngit clone https://github.com/Zubax/jafit\ncd jafit\npip install \".[interactive]\"\n```\n\nYou may omit `[interactive]` if you are not planning on using the GUI.\n\nThe tool works on GNU/Linux and Windows. Probably also on macOS, but YMMV.\n\n### Solve the JA equation\n\nThe tool will plot the curves and export table files containing the data points.\n\n```shell\n# Coefficients from the default COMSOL Jiles-Atherton material model:\njafit model=venk  c_r=0.1 M_s=1.6e6 a=560 k_p=1200 alpha=0.0007\n\n# Coefficients from the Altair Flux example B(H) curve:\njafit model=venk  H_amp_max=1111  c_r=0.2107788 M_s=1306755.22 a=108.694943 k_p=177.625645 alpha=0.000294224757\n\n# From \"Modeling of permanent magnets: Interpretation of parameters obtained from the Jiles–Atherton hysteresis model\":\njafit model=orig  H_amp_min=4774648 H_amp_max=4774648  c_r=0.885 M_s=1080000 a=1107718.3824 k_p=702271.17275 alpha=3.168\n```\n\nIf the H amplitude is set manually and is insufficient to reach saturation,\nthe resulting hysteresis loop will be a minor loop.\n\n### Find JA coefficients for a given reference B(H) curve\n\nThe fitting problem may take multiple hours or days to solve,\ndepending on the curve shape and the performance of your computer.\nIntermediate results and logs will be stored in the current working directory,\nso it may be a good idea to create a dedicated directory for this purpose.\n\nBasic examples:\n\n```shell\n# Fit the example curve from Altair Flux:\njafit model=venk ref=\"data/B(H).Altair_Flux.Example.csv\" interpolate=300 H_amp_max=0\n\n# Find coefficients for isotropic AlNiCo 5:\njafit model=venk ref=\"data/B(H).Jesenik.AlNiCo.tab\" preg=100\n```\n\nOutput symbol legend per function evaluation:\n💚 -- best match so far; ❌ -- no solution (convergence failure); 🔵 -- solution exists but is not the best.\nUse `quiet=1` to reduce the verbosity.\n\nThe input reference curve file must contain two columns: H \\[A/m\\] and B \\[T\\], either tab- or comma-separated.\nThe first row may or may not be the header row.\nThe reference curve may be either the entire hysteresis loop, whether major or minor,\nor only a part of the descending branch.\n\nBy default, the tool will attempt to determine the suitable range of the H amplitude values using heuristics.\nIt is always a good idea to specify this manually instead by setting `H_amp_min` and/or `H_amp_max`,\nwhere `H_amp_min` specifies the minimum H magnitude that must be reached before switching the H sweep direction,\nand `H_amp_max` is the maximum H magnitude that the solver is allowed to use; the solver will flip the H sweep\ndirection somewhere between these two values as soon as the material reaches saturation ($\\chi^\\prime$ becomes small).\n\n`H_amp_max` is clamped to be at least as large as `H_amp_min`;  therefore, setting `H_amp_max=0`\nwill effectively force the tool to use a fixed H amplitude, irrespective of the saturation detection.\nIf the provided loop is a minor loop, the tool needs to be instructed to limit the H amplitude to what is seen\nin the reference dataset; to do that, simply pass `H_amp_max=0`.\n\nBy default, the tool will assume that the reference loop may not push the material into saturation,\nand thus it will attempt to determine $M_s$ as part of the optimization problem.\nBy default, the range for the $M_s$ search is determined automatically using heuristics.\nThe heuristics can be overridden using the optional `M_s_min` and/or `M_s_max` parameters.\nIf `M_s_max\u003c=M_s_min`, the tool will assume that $M_s$ is known exactly, $M_s$=`M_s_min`=`M_s_max`,\nand remove the corresponding dimension from the optimization problem.\nThis is often useful because manufacturers often provide the saturation magnetization (or polarization) directly.\nNote that for anisotropic materials, $M_s$ is usually invariant with respect to the direction of the applied field,\nas it is defined by the chemical composition of the material.\n\nOptionally, you can provide the initial guess for (some of) the coefficients: `c_r`, `M_s`, `a`, `k_p`, `alpha`.\nIt is required that `M_s_min \u003c= M_s \u003c= M_s_max`; if both min and max are provided, `M_s` is not needed.\nIt is usually not necessary to set `k_p` because it defaults to $H_c$, which is a reasonable guess.\n\nThe priority region error gain -- `preg` --\ncan be set to a value greater than one to make the optimizer assign proportionally higher importance\nto the part of the descending branch where $M\u003e0$, and the part of the ascending branch where $M\u003c0$.\nExample: `preg=100`.\nThis option only has effect if the full reference loop is provided.\n\nOption `interpolate=N`, where N is a positive integer, can be used to interpolate the reference curve\nwith N equidistant sample points distributed along its length. Note that this is not the same as sampling the curve\non a regular H-axis grid; the difference is that the used method ensures consistent Euclidean distances between\nthe sample points. This is useful with irregularly sampled curves, but may cause adverse effects if the reference\ncurves contain large gaps, as the interpolation error within the gaps may be large.\n\nIf interpolation is not used (it is not by default), then the optimizer will naturally assign higher importance\nto the regions of the curve with higher density of sample points. This may be leveraged to great advantage\nif the reference curve is pre-processed to leave out the regions that are less important for the fitting.\n\nThe optimization is done in multiple stages, with global search preceding local refinement.\nThe tool can be instructed to skip N first stages by setting `stage=N`. See the code for details.\n\nThe tool relies on a robust implicit solver to work around stiffness that arises with certain coefficient combinations\nduring the optimization process. While ultra-high stiffness may be considered unphysical as it may indicate an\nunrealistically high magnetic susceptibility, being able to solve such cases is useful as it improves the smoothness\nof the optimization landscape, which in turn helps the optimizer converge faster and reduces the chances of\ngetting stuck in local minima.\n\nFor a more advanced usage example, consider the following datasheet from the manufacturer:\n\n\u003cimg src=\"data/B(H),J(H).VegaTechnik.LNG60.png\" width=\"600\" alt=\"\"\u003e\n\nThe following data is immediately available:\n\n* The second quadrant of the $B(H)$ curve; the data is extracted here as `data/B(H).VegaTechnik.LNG60.tab`.\n\n* The second quadrant polarization $J(H)$ curve is also available but not needed --- the tool will convert\n  $B(H) \\Rightarrow J(H) \\Rightarrow M(H)$.\n\n* Saturation magnetization $M_s=1174563$ A/m, which is expressed as saturation polarization $J_s$ in the datasheet.\n  This value is usually invariant with respect to the direction of the applied field in anisotropic materials.\n\n* The excitation field intensity $H_m=713014$ A/m.\n\nSadly, the datasheet is not using the SI system, so manual conversion is needed.\nThe corresponding optimization command is as follows:\n\n```shell\njafit ref='data/B(H).VegaTechnik.LNG60.tab' model=venkataraman M_s_min=1174563 M_s_max=1174563 H_amp_min=713014 H_amp_max=713014\n```\n\n### Adjust the parameters interactively\n\nUse `interactive=1` to launch an interactive tool with web GUI.\nThis mode requires that the interactive GUI option is enabled when installing the package;\nrefer to the installation section for details.\n\n```\njafit interactive=1 model=venk ref='data/B(H).Campbell.AlNiCo_5.tab' c_r=0.00083284 M_s=1251180 a=20838 k_p=69771 alpha=0.08\n```\n\n\u003cimg src=\"interactive.png\" width=\"800\" alt=\"\"\u003e\n\n### Helpful tips\n\nFor fetching the (approximate) data points from a third-party plot,\nsuch as from a published paper or a material datasheet,\nconsider using [`trace_image.py`](https://gist.github.com/pavel-kirienko/0fcd509cd1d7c6dc2651981510badb99).\n\nFor the benefit of all mankind, please only use SI units. To convert data from a non-SI source:\n\n- $1 \\ \\text{oersted} \\approx 79.57747 \\frac{\\text{A}}{\\text{m}}$\n- $1 \\ \\frac{\\text{emu}}{\\text{cm}^3} = 10^3 \\frac{\\text{A}}{\\text{m}}$\n- $1 \\ \\text{gauss} = 10^{-4} \\ \\text{T}$\n\nFor more, refer to `papers/magnetic_units.pdf`.\n\n## Validation\n\n### Against COMSOL Multiphysics\n\nThere is a COMSOL model in the `validation` directory that contains a bored steel cylinder with a copper wire passing\nalong its axis.\n\nIf $B = \\mu_0 (H_i + M)$ and $H_i = H - H_d$, where $H_i$ is the internal field and\n$H_d = M N_d$ is the demagnetizing field with the demagnetizing factor $N_d$,\nthen $B = \\mu_0 (H - N_d M + M)$.\nSince $N_d = 0$ in the absence of free poles, the validation is performed using a loop-shaped magnet\nwith a magnetization wire passing through the center, which ensures $B = \\mu_0 (H + M)$.\n\nThe wire carries AC magnetizing current whose amplitude is chosen to be just high enough to push the\ncylinder material into saturation, while the frequency is chosen to be low to avoid eddy currents\nand small-time-scale coercivity effects.\nThe setup is used to obtain the J(H) curve and ascertain that it matches the predictions made by the tool.\n\n\u003cimg src=\"validation/COMSOL_B(t).gif\" width=\"600px\" alt=\"\"\u003e\n\nTo make the prediction, run the tool specifying the JA model coefficients copied from the material properties\nassigned to the cylinder in the COMSOL model,\nnote the shape of the curve and the predicted $H_c$, $B_r$, and $BH_\\text{max}$,\nand compare them against the COMSOL simulation results.\n\n#### Specimen A: default Jiles-Atherton material\n\nNote that we're using the same H-field amplitude as in the COMSOL model.\n\n```shell\njafit model=venk H_amp_max=65e3 c_r=0.1 M_s=1.6e6 a=560 k_p=1200 alpha=0.0007\n```\n\n\u003cimg src=\"validation/jafit-comsol-default-material.png\" alt=\"\" height=\"200px\"\u003e\u003cimg src=\"validation/hysteresis-comsol-default-material.png\" alt=\"\" height=\"200px\"\u003e\n\n#### Specimen B: LNGT72 approximation\n\n```shell\njafit model=venk c_r=0.00000098783341818 M_s=0931849.980906066 a=025958.529588940 k_p=147381.227474120 alpha=0.17527880356890363 H_amp_min=1e6\n```\n\n\u003cimg src=\"validation/jafit hysteresis model=venk c_r=0.00000098783341818 M_s=0931849.980906066 a=025958.529588940 k_p=147381.227474120 alpha=0.17527880356890363.png\" alt=\"\" height=\"200px\"\u003e\u003cimg src=\"validation/hysteresis model=venk c_r=0.00000098783341818 M_s=0931849.980906066 a=025958.529588940 k_p=147381.227474120 alpha=0.17527880356890363.png\" alt=\"\" height=\"200px\"\u003e\n\n### Against Altair Flux\n\nThe following invocation results in a curve matching the example material from Altair Flux.\n\n```shell\njafit model=venk  H_amp_max=1111  c_r=0.2107788 M_s=1306755.22 a=108.694943 k_p=177.625645 alpha=0.000294224757\n```\n\n\u003cimg src=\"validation/jafit-altair-flux-example-material.png\" alt=\"\" height=\"200px\"\u003e\u003cimg src=\"validation/Altair_Flux_example_material_curve.png\" alt=\"\" height=\"200px\"\u003e\n\n## Development\n\nTo run verification locally, simply say `nox`.\n\nIf you want to run PyTest only, you may want to `export NUMBA_DISABLE_JIT=1` beforehand, or uninstall Numba.\n\nTo profile, go like: `python3 -m cProfile -o out.prof -m jafit ../data/bh-lng37.tab`.\nThen you can use `flameprof` to visualize the collected data.\n\nTo evaluate the optimizer behaviors quickly, run the script in fast mode with `fast=1`.\nThis may render the results inaccurate, but it will be much faster.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzubax%2Fjafit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzubax%2Fjafit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzubax%2Fjafit/lists"}