Questions regarding spatial anisotropy profile ($K_{u1}$) and setting up concentric ring regions

30 views
Skip to first unread message

Patrick Myles

unread,
Jul 8, 2026, 12:56:43 PMJul 8
to mumax2

Hi everyone,

I have two questions regarding parameter assignment in Mumax3:

1. Is it possible to set uniaxial anisotropy ($K_{u1}$) directly as an analytical function of spatial coordinates $(x, y)$?

I would like to create a continuous, non-uniform anisotropy profile (e.g., a Gaussian distribution centered at the grid origin or a radial gradient). What is the correct and most efficient syntax to achieve this directly in the .mx3 script without pre-generating an OVF file?

2. Why does painting concentric ring regions using nested Circle() shapes fail?

I am trying to set up 6 concentric rings with different $K_{u1}$ values. Even when assigning regions from the largest circle to the smallest (or using .Sub()), the resulting output in the Web UI / saved spatial map shows only a single uniform disk instead of distinct concentric rings.

Could someone point out what is wrong with this approach or what the recommended workflow for concentric regions is? Here is a minimal example of my script:


SetGridSize(300, 300, 1)
SetCellSize(1e-9, 1e-9, 1e-9)

// Define radii
r0 := 20e-9
r1 := 40e-9
r2 := 60e-9
r3 := 80e-9
r4 := 100e-9
r5 := 120e-9

// Define nested regions from largest to smallest (Circle takes diameter)
DefRegion(6, Circle(2*r5))
DefRegion(5, Circle(2*r4))
DefRegion(4, Circle(2*r3))
DefRegion(3, Circle(2*r2))
DefRegion(2, Circle(2*r1))
DefRegion(1, Circle(2*r0))

Msat  = 1.4e6
Aex   = 15e-12
alpha = 0.1
anisU = vector(0, 0, 1)

// Set Ku1 per region
Ku1.SetRegion(1, 5e5)
Ku1.SetRegion(2, 4e5)
Ku1.SetRegion(3, 3e5)
Ku1.SetRegion(4, 2e5)
Ku1.SetRegion(5, 1e5)
Ku1.SetRegion(6, 0.5e5)

Msat.SetRegion(0, 0) // Zero Msat outside the rings

SaveAs(regions, "regions_out")
SaveAs(Ku1, "Ku1_out")
anisotropy.png

Thanks in advance for your help!

Антон Луценко

unread,
Jul 9, 2026, 5:13:30 AMJul 9
to mumax2
1. No, in mumax it's only via regions. There are a few other micromagnetic simulators that can do that, but they're going to be a bit slower. 
2. You would not expect to see anything different if you are looking at magnetization. Select "regions" in the UI and you should be able to see the rings. Also you can load regions_out.ovf into Python or Mathematica and visualize them, you should also see the rings. 

Also, I recommend against using Msat = 0, instead use SetGeom(Circle(2*r5)). 

Hope that helps! 

Josh Lauzier

unread,
Jul 10, 2026, 12:46:36 AMJul 10
to mumax2
Hi,

Previously in mumax3, specifically for a radially symmetric one, you would need to do it as you are already, with Circles. You can do it in a for loop. Something like:

imax:=5
for i:=0; i<=imax; i=i+1{
defregion(i, Circle(2*i*(120e-9-i*20e-9)))
Ku1.SetRegion(1, exp(-pow((i*20e-9)/100e-9, 2)) )
}

This isn't truly an arbitrary function, but specifically for a radially specific problem, you can parametrize the radius and use Circles. There are two caveats: You are still limited to regions, as Anton mentioned. In particular, there can only be 256 regions, even if you load from a file.Two, when you have overlapping regions like this, keep in mind that the latest assignment will overwrite the previous ones (this was correct in your original script where you started with bigger circles down to smaller, just mentioning in case it was accidental). 

However, with the latest release 3.12, I am happy to say that it is now possible to do arbitrary functions of f(x,y,z) via the new CustomQuantity() feature, as long as the effect you want can be represented by a Custom Field. CustomQuantity() allows a user to upgrade a slice with arbitrary values to a Quantity that can be used with CustomQuantity.  The slice used with CustomQuantity() should match the mesh size. The process goes something like:

1) Slices can already be built using analytical functions (for an example, look to the " Spinning hard disk" example on the examples page where they construct a slice with a Gaussian profile) or via Loadfile(). You would construct a slice of K values for each cell using NewScalarMask() or NewVectorMask() the same way as the hard disk example. 

2) Then, instead of using B_ext.add() as in the hard disk example to make an external field, you would call CustomQuantity on the slice to upgrade it to a Quantity. 

3) Once it is a Quantity, you can apply it as a CustomField using AddFieldTerm() (same with energy densities and AddEdensterm() ). For an example of Custom Fields, look to the "custom effective field terms" on the API page. It shows how to construct a uniaxial anisotropy via custom fields. The only difference for you will be instead of  Const(2*K/Ms), since your K is no longer constant you will have Mul( Const(2/Ms), Kvals), where Kvals is your CustomQuantity. 

The process is a bit involved, so I've attached an example file. You may need to tweak it slightly slightly but it should give the idea. If you have less than 256 regions, either method should be equivalent. The advantage of CustomQuantity() is that it's not limited to 256 regions, and not limited to the built-in Shapes. However, Custom Fields will in general be a bit slower and use a bit more memory during the actual simulation run compared to the native anisotropy implementation. Also, your fields/energies will show up under B_custom/Edens_Custom instead of the B_anis.

As Anton mentioned, I would double check your output, your existing script works as intended. Here is regions from the GUI. And Ku1:
mmhelp3.jpg

Cheers,
Josh L.
customquantityexample.txt
Reply all
Reply to author
Forward
0 new messages