|
| 1 | +import fidimag.extensions.clib |
| 2 | +import fidimag.extensions.micro_clib |
| 3 | +import numpy as np |
| 4 | + |
| 5 | + |
| 6 | +def skyrmion_number_slice(sim, at=None, zIndex=None): |
| 7 | + """ |
| 8 | + Returns the skyrmion number calculated on the x-y plane at a specific z |
| 9 | + co-ordinate. |
| 10 | +
|
| 11 | + The current fidimag skyrmion number function finds the skyrmion number for |
| 12 | + the first z co-ordinate in index order (unintentionally?). So the approach |
| 13 | + this function uses is to slice the spin array in the simulation object to |
| 14 | + only include the x-y plane as previously described. |
| 15 | +
|
| 16 | + Arguments: |
| 17 | + sim: LLG object with cuboidal mesh. |
| 18 | +
|
| 19 | + Optional Arguments: |
| 20 | + If neither of these arguments are specified, this function raises a |
| 21 | + ValueError. |
| 22 | +
|
| 23 | + at: None, "top", "centre", or "bottom" denoting where to slice in |
| 24 | + British English. https://en.wikipedia.org/wiki/Strike_It_Lucky |
| 25 | + zIndex: Integer (not a float), or None denoting the index at which to |
| 26 | + slice. Overrides "at" if not None. Bound by zIndex~[0, sim.mesh.nz-1] |
| 27 | +
|
| 28 | + Returns: |
| 29 | + skyrmionNumber (a float) |
| 30 | + """ |
| 31 | + |
| 32 | + # Deal with inputs. |
| 33 | + if zIndex is None: |
| 34 | + if at is "bottom": |
| 35 | + zIndex = 0 |
| 36 | + |
| 37 | + elif at is "centre": |
| 38 | + # Find the layer number that corresponds to the centre of the mesh, |
| 39 | + # preferring the lower layer in a tie. |
| 40 | + zIndex = sim.mesh.nz / 2. |
| 41 | + if sim.mesh.nz % 2 == 0: |
| 42 | + zIndex -= 0.5 |
| 43 | + zIndex -= 0.5 |
| 44 | + |
| 45 | + elif at is "top": |
| 46 | + zIndex = sim.mesh.nz - 1 # Indeces start at 0. |
| 47 | + |
| 48 | + else: |
| 49 | + raise ValueError("[skyrmion_number_slice]: Either " |
| 50 | + "'at=bottom|centre|top' or 'zIndex'=[integer] " |
| 51 | + "must be passed as arguments.") |
| 52 | + |
| 53 | + elif zIndex > sim.mesh.nz - 1 or zIndex < 0: |
| 54 | + raise ValueError("[skyrmion_number_slice]: 'zIndex={}' must be an " |
| 55 | + "integer between 0 and sim.mesh.nz - 1, which is " |
| 56 | + "'{}' for this simulation object." |
| 57 | + .format(zIndex, sim.mesh.nz - 1)) |
| 58 | + |
| 59 | + # Find the "length" of a slice in terms of the spin array. |
| 60 | + xyLength = sim.mesh.nx * sim.mesh.ny * 3 # The 3 represents (x,y,z). |
| 61 | + |
| 62 | + # Obtain slice of spins cleverly. This also works if the domain is flat |
| 63 | + # (i.e. nz=1, zIndex=0) |
| 64 | + spinSlice = sim.spin[int(xyLength * zIndex):int(xyLength * (zIndex + 1))] |
| 65 | + |
| 66 | + # Compute the skyrmion number for our spin slice. |
| 67 | + if sim._micromagnetic is True: |
| 68 | + return fidimag.extensions.micro_clib.compute_skyrmion_number(\ |
| 69 | + spinSlice, sim._skx_number, sim.mesh.nx, sim.mesh.ny, |
| 70 | + sim.mesh.nz, sim.mesh.neighbours) |
| 71 | + else: |
| 72 | + return fidimag.extensions.clib.compute_skyrmion_number(\ |
| 73 | + spinSlice, sim._skx_number, sim.mesh.nx, sim.mesh.ny, |
| 74 | + sim.mesh.nz, sim.mesh.neighbours) |
| 75 | + |
| 76 | + |
| 77 | +def skyrmion_number_lee(sim): |
| 78 | + """ |
| 79 | + Returns the skyrmion number calculated from a 3D sample, as defined in: |
| 80 | +
|
| 81 | + Lee, M, Kang, W, Onose, Y, et. al (2009) "Unusual Hall effect anomaly in |
| 82 | + MnSi under pressure". PRL. |
| 83 | +
|
| 84 | + Arguments: |
| 85 | + sim: LLG object with cuboidal mesh. |
| 86 | +
|
| 87 | + Returns: |
| 88 | + skyrmionNumber (a float) |
| 89 | + """ |
| 90 | + |
| 91 | + # Find the "length" of a slice in terms of the spin array. |
| 92 | + xyLength = sim.mesh.nx * sim.mesh.ny * 3 # The 3 represents (x, y, z). |
| 93 | + |
| 94 | + # Create an array to store skyrmion number values for each z slice. |
| 95 | + skyrmionNumbers = np.ndarray(sim.mesh.nz) |
| 96 | + |
| 97 | + # For each slice, compute the skyrmion number. |
| 98 | + for zI in range(len(skyrmionNumbers)): |
| 99 | + spinSlice = sim.spin[xyLength * zI:xyLength * (zI + 1)] |
| 100 | + |
| 101 | + if sim._micromagnetic is True: |
| 102 | + skyrmionNumbers[zI] = fidimag.extensions.micro_clib.compute_skyrmion_number(\ |
| 103 | + spinSlice, sim._skx_number, sim.mesh.nx, |
| 104 | + sim.mesh.ny, sim.mesh.nz, |
| 105 | + sim.mesh.neighbours) |
| 106 | + else: |
| 107 | + skyrmionNumbers[zI] = fidimag.extensions.clib.compute_skyrmion_number(\ |
| 108 | + spinSlice, sim._skx_number, sim.mesh.nx, |
| 109 | + sim.mesh.ny, sim.mesh.nz, |
| 110 | + sim.mesh.neighbours) |
| 111 | + |
| 112 | + # Return the average. This is equivalent to the integral in the equation. |
| 113 | + return skyrmionNumbers.mean() |
0 commit comments