Skip to content

Resistance functions

Those functions are used to compute the resistance of a given system. They are all defined in the resistance module for version upside of 1.2.0.

GMR_expr()

Get the symbolic expression for the GMR.

Returns:

Type Description
Callable[[float, float, float, float], float]

GMR function: Callable[[theta1, phi1, theta2, phi2], float]

Source code in cmtj/utils/resistance.py
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
def GMR_expr() -> Callable[[float, float, float, float], float]:
    """Get the symbolic expression for the GMR.

    :returns: GMR function: Callable[[theta1, phi1, theta2, phi2], float]
    """
    GMR_s = sym.Symbol(r"\mathrm{GMR}")
    theta1 = sym.Symbol(r"\theta_1")
    phi1 = sym.Symbol(r"\phi_1")
    m1 = sym.Matrix(
        [
            sym.sin(theta1) * sym.cos(phi1),
            sym.sin(theta1) * sym.sin(phi1),
            sym.cos(theta1),
        ]
    )
    theta2 = sym.Symbol(r"\theta_2")
    phi2 = sym.Symbol(r"\phi_2")
    m2 = sym.Matrix(
        [
            sym.sin(theta2) * sym.cos(phi2),
            sym.sin(theta2) * sym.sin(phi2),
            sym.cos(theta2),
        ]
    )
    Rf = GMR_s * (1 - m1.dot(m2)) / 2
    dRdt1 = sym.diff(Rf, theta1)
    dRdp1 = sym.diff(Rf, phi1)
    dRdt2 = sym.diff(Rf, theta2)
    dRdp2 = sym.diff(Rf, phi2)
    linearised_terms = sym.symbols(r"\partial\theta_1, \partial\phi_1, \partial\theta_2, \partial\phi_2")
    dRf = (
        dRdt1 * linearised_terms[0]
        + dRdp1 * linearised_terms[1]
        + dRdt2 * linearised_terms[2]
        + dRdp2 * linearised_terms[3]
    )

    Rf_func = sym.lambdify([GMR_s, [theta1, phi1, theta2, phi2]], Rf)
    dRf_func = sym.lambdify([GMR_s, [theta1, phi1, theta2, phi2], linearised_terms], dRf)
    return Rf_func, dRf_func

Rxx_parallel_bilayer_expr()

Get the symbolic expressions for the parallel and linearised resistance of a bilayer system.

Signals: - GMR: GMR - AMR1: AMR of layer 1 - SMR1: SMR of layer 1 - AMR2: AMR of layer 2 - SMR2: SMR of layer 2 - stationary angles: [t1, p1, t2, p2] - linearised angles: [dt1, dp1, dt2, dp2]

Function signatures - Rlin_func: linearised resistance function f(GMR, AMR1, SMR1, AMR2, SMR2, [t1, p1, t2, p2], [dt1, dp1, dt2, dp2]) - R_func: series resistance function f(GMR, AMR1, SMR1, AMR2, SMR2, [t1, p1, t2, p2])

Returns:

Type Description
tuple[Callable[[float, float, float, float, float, float, float, float, float, float, float, float, float, float], float], Callable[[float, float, float, float, float, float, float, float, float, float, float, float, float, float], float]]

linearised and parallel resistance functions

Source code in cmtj/utils/resistance.py
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
def Rxx_parallel_bilayer_expr() -> (
    tuple[
        Callable[
            [
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
            ],
            float,
        ],
        Callable[
            [
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
            ],
            float,
        ],
    ]
):
    """Get the symbolic expressions for the parallel and linearised resistance of a bilayer system.

    Signals:
    - GMR: GMR
    - AMR1: AMR of layer 1
    - SMR1: SMR of layer 1
    - AMR2: AMR of layer 2
    - SMR2: SMR of layer 2
    - stationary angles: [t1, p1, t2, p2]
    - linearised angles: [dt1, dp1, dt2, dp2]

    Function signatures
    - Rlin_func: linearised resistance function
        f(GMR, AMR1, SMR1, AMR2, SMR2, [t1, p1, t2, p2], [dt1, dp1, dt2, dp2])
    - R_func: series resistance function
        f(GMR, AMR1, SMR1, AMR2, SMR2, [t1, p1, t2, p2])

    :returns: linearised and parallel resistance functions
    """
    AMR_1 = sym.Symbol(r"\mathrm{AMR}_1")
    SMR_1 = sym.Symbol(r"\mathrm{SMR}_1")
    AMR_2 = sym.Symbol(r"\mathrm{AMR}_2")
    SMR_2 = sym.Symbol(r"\mathrm{SMR}_2")
    GMR_s = sym.Symbol(r"\mathrm{GMR}")
    R_1, t1, p1, m1 = Rxx_symbolic(1, AMR_1, SMR_1)
    R_2, t2, p2, m2 = Rxx_symbolic(2, AMR_2, SMR_2)
    gmr_term = GMR_s * (1 - m1.dot(m2)) / 2

    Rparallel = gmr_term + (R_1 * R_2) / (R_1 + R_2 + EPS)
    linearised_terms = sym.symbols(r"\partial\theta_1, \partial\phi_1, \partial\theta_2, \partial\phi_2")
    dRdtheta1 = sym.diff(Rparallel, t1) * linearised_terms[0]
    dRdphi1 = sym.diff(Rparallel, p1) * linearised_terms[1]
    dRdtheta2 = sym.diff(Rparallel, t2) * linearised_terms[2]
    dRdphi2 = sym.diff(Rparallel, p2) * linearised_terms[3]

    linearised_R = dRdtheta1 + dRdtheta2 + dRdphi1 + dRdphi2

    Rlin_func = sym.lambdify(
        [GMR_s, AMR_1, SMR_1, AMR_2, SMR_2, [t1, p1, t2, p2], linearised_terms],
        linearised_R,
    )
    R_func = sym.lambdify([GMR_s, AMR_1, SMR_1, AMR_2, SMR_2, [t1, p1, t2, p2]], Rparallel)

    return Rlin_func, R_func

Rxx_series_bilayer_expr()

Get the symbolic expressions for the series and linearised resistance of a bilayer system.

Signals: - GMR: GMR - AMR1: AMR of layer 1 - SMR1: SMR of layer 1 - AMR2: AMR of layer 2 - SMR2: SMR of layer 2 - stationary angles: [t1, p1, t2, p2] - linearised angles: [dt1, dp1, dt2, dp2]

Function signatures - Rlin_func: linearised resistance function f(GMR, AMR1, SMR1, AMR2, SMR2, [t1, p1, t2, p2], [dt1, dp1, dt2, dp2]) - R_func: series resistance function f(GMR, AMR1, SMR1, AMR2, SMR2, [t1, p1, t2, p2])

Returns:

Type Description
tuple[Callable[[float, float, float, float, float, float, float, float, float, float, float, float, float, float], float], Callable[[float, float, float, float, float, float, float, float, float, float, float, float, float, float], float]]

linearised and series resistance functions

Source code in cmtj/utils/resistance.py
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
def Rxx_series_bilayer_expr() -> (
    tuple[
        Callable[
            [
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
            ],
            float,
        ],
        Callable[
            [
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
                float,
            ],
            float,
        ],
    ]
):
    """Get the symbolic expressions for the series and linearised resistance of a bilayer system.

    Signals:
    - GMR: GMR
    - AMR1: AMR of layer 1
    - SMR1: SMR of layer 1
    - AMR2: AMR of layer 2
    - SMR2: SMR of layer 2
    - stationary angles: [t1, p1, t2, p2]
    - linearised angles: [dt1, dp1, dt2, dp2]

    Function signatures
    - Rlin_func: linearised resistance function
        f(GMR, AMR1, SMR1, AMR2, SMR2, [t1, p1, t2, p2], [dt1, dp1, dt2, dp2])
    - R_func: series resistance function
        f(GMR, AMR1, SMR1, AMR2, SMR2, [t1, p1, t2, p2])

    :returns: linearised and series resistance functions
    """
    AMR_1 = sym.Symbol(r"\mathrm{AMR}_1")
    SMR_1 = sym.Symbol(r"\mathrm{SMR}_1")
    AMR_2 = sym.Symbol(r"\mathrm{AMR}_2")
    SMR_2 = sym.Symbol(r"\mathrm{SMR}_2")
    GMR_s = sym.Symbol(r"\mathrm{GMR}")
    R_1, t1, p1, m1 = Rxx_symbolic(1, AMR_1, SMR_1)
    R_2, t2, p2, m2 = Rxx_symbolic(2, AMR_2, SMR_2)
    gmr_term = GMR_s * (1 - m1.dot(m2)) / 2

    Rseries = gmr_term + R_1 + R_2
    linearised_terms = sym.symbols(r"\partial\theta_1, \partial\phi_1, \partial\theta_2, \partial\phi_2")
    dRdtheta1 = sym.diff(Rseries, t1) * linearised_terms[0]
    dRdphi1 = sym.diff(Rseries, p1) * linearised_terms[1]
    dRdtheta2 = sym.diff(Rseries, t2) * linearised_terms[2]
    dRdphi2 = sym.diff(Rseries, p2) * linearised_terms[3]

    linearised_R = dRdtheta1 + dRdtheta2 + dRdphi1 + dRdphi2

    Rlin_func = sym.lambdify(
        [GMR_s, AMR_1, SMR_1, AMR_2, SMR_2, [t1, p1, t2, p2], linearised_terms],
        linearised_R,
    )
    R_func = sym.lambdify([GMR_s, AMR_1, SMR_1, AMR_2, SMR_2, [t1, p1, t2, p2]], Rseries)

    return Rlin_func, R_func

Rxx_symbolic(id, AMR, SMR) cached

Compute the Rxx resistance for a given layer.

Parameters:

Name Type Description Default
id int

layer id

required
AMR float

anisotropic magnetoresistance

required
SMR float

spin Hall magnetoresistance

required
Source code in cmtj/utils/resistance.py
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
@lru_cache(maxsize=5)
def Rxx_symbolic(id: int, AMR: float, SMR: float) -> tuple[float, sym.Symbol, sym.Symbol, sym.Matrix]:
    """Compute the Rxx resistance for a given layer.
    :param id: layer id
    :param AMR: anisotropic magnetoresistance
    :param SMR: spin Hall magnetoresistance
    """
    theta1 = sym.Symbol(r"\theta_" + str(id))
    phi1 = sym.Symbol(r"\phi_" + str(id))
    m = sym.Matrix(
        [
            sym.sin(theta1) * sym.cos(phi1),
            sym.sin(theta1) * sym.sin(phi1),
            sym.cos(theta1),
        ]
    )
    return AMR * m[0] ** 2 + SMR * m[1] ** 2, theta1, phi1, m

Rxy_symbolic(id, AMR, SMR, AHE, w_l) cached

Compute the Rxy resistance for a given layer.

Parameters:

Name Type Description Default
id int

layer id

required
AMR float

anisotropic magnetoresistance

required
SMR float

spin Hall magnetoresistance

required
AHE float

anomalous Hall effect

required
w_l float

width to length ratio

required
Source code in cmtj/utils/resistance.py
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
@lru_cache(maxsize=5)
def Rxy_symbolic(
    id: int, AMR: float, SMR: float, AHE: float, w_l: float
) -> tuple[float, sym.Symbol, sym.Symbol, sym.Matrix]:
    """Compute the Rxy resistance for a given layer.
    :param id: layer id
    :param AMR: anisotropic magnetoresistance
    :param SMR: spin Hall magnetoresistance
    :param AHE: anomalous Hall effect
    :param w_l: width to length ratio
    """
    theta1 = sym.Symbol(r"\theta_" + str(id))
    phi1 = sym.Symbol(r"\phi_" + str(id))
    m = sym.Matrix(
        [
            sym.sin(theta1) * sym.cos(phi1),
            sym.sin(theta1) * sym.sin(phi1),
            sym.cos(theta1),
        ]
    )
    return (0.5 * AHE * m[-1]) + w_l * (SMR - AMR) * m[0] * m[1], theta1, phi1, m

angular_calculate_resistance_gmr(Rp, Rap, theta_1, phi_1, theta_2, phi_2)

Computes the GMR using parallel and antiparallel resistance.

Parameters:

Name Type Description Default
Rp float

parallel resistance

required
Rap float

antiparallel resistance

required
theta_1 np.ndarray

angle of layer 1

required
phi_1 np.ndarray

angle of layer 1

required
theta_2 np.ndarray

angle of layer 2

required
phi_2 np.ndarray

angle of layer 2

required
Source code in cmtj/utils/resistance.py
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
def angular_calculate_resistance_gmr(
    Rp: float,
    Rap: float,
    theta_1: np.ndarray,
    phi_1: np.ndarray,
    theta_2: np.ndarray,
    phi_2: np.ndarray,
) -> np.ndarray:
    """Computes the GMR using parallel and antiparallel resistance.
    :param Rp: parallel resistance
    :param Rap: antiparallel resistance
    :param theta_1: angle of layer 1
    :param phi_1: angle of layer 1
    :param theta_2: angle of layer 2
    :param phi_2: angle of layer 2
    """
    m1 = np.array(
        [
            np.cos(theta_1) * np.cos(phi_1),
            np.cos(theta_1) * np.sin(phi_1),
            np.sin(theta_1),
        ]
    )
    m2 = np.array(
        [
            np.cos(theta_2) * np.cos(phi_2),
            np.cos(theta_2) * np.sin(phi_2),
            np.sin(theta_2),
        ]
    )
    return compute_gmr(Rp, Rap, m1, m2)

calculate_linearised_resistance(GMR, AMR, SMR)

Compute the resistance of the two FM bilayer system from the linearised angles.

Parameters:

Name Type Description Default
GMR float

GMR

required
AMR list[float]

AMR

required
SMR list[float]

SMR

required
Source code in cmtj/utils/resistance.py
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
def calculate_linearised_resistance(
    GMR: float,
    AMR: list[float],
    SMR: list[float],
) -> tuple[float, float, float, sym.Symbol, sym.Symbol, sym.Symbol, sym.Symbol]:
    """
    Compute the resistance of the two FM bilayer system from the linearised angles.

    :param GMR: GMR
    :param AMR: AMR
    :param SMR: SMR
    """

    Rxx1, theta1, phi1, m1 = Rxx_symbolic(1, AMR[0], SMR[0])
    Rxx2, theta2, phi2, m2 = Rxx_symbolic(2, AMR[1], SMR[1])
    GMR_resistance = GMR * (1 - (m1.dot(m2))) / 2.0
    return Rxx1, Rxx2, GMR_resistance, theta1, phi1, theta2, phi2

calculate_linearised_resistance_parallel(GMR, AMR, SMR, stationary_angles, linearised_angles)

Compute the parallel resistance of the two FM bilayer system from the linearised angles.

Parameters:

Name Type Description Default
GMR float

GMR

required
AMR list[float]

AMR

required
SMR list[float]

SMR

required
stationary_angles list[float]

stationary angles [t1, p1, t2, p2]

required
linearised_angles list[float]

linearised angles [dt1, dp1, dt2, dp2]

required
Source code in cmtj/utils/resistance.py
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
def calculate_linearised_resistance_parallel(
    GMR: float,
    AMR: list[float],
    SMR: list[float],
    stationary_angles: list[float],
    linearised_angles: list[float],
):
    """
    Compute the parallel resistance of the two FM bilayer system from the linearised angles.

    :param GMR: GMR
    :param AMR: AMR
    :param SMR: SMR
    :param stationary_angles: stationary angles [t1, p1, t2, p2]
    :param linearised_angles: linearised angles [dt1, dp1, dt2, dp2]
    """
    t01, p01 = stationary_angles[:2]
    t02, p02 = stationary_angles[2:]
    dt1, dp1 = linearised_angles[:2]
    dt2, dp2 = linearised_angles[2:]
    Rxx1, Rxx2, GMR_resistance, theta1, phi1, theta2, phi2 = calculate_linearised_resistance(GMR, AMR, SMR)
    Rparallel = GMR_resistance
    if any(AMR) or any(SMR):
        Rparallel += (Rxx1 * Rxx2) / (Rxx1 + Rxx2 + EPS)
    elif GMR == 0:
        return 0, 0
    dRparallel = (
        sym.diff(Rparallel, theta1) * dt1
        + sym.diff(Rparallel, phi1) * dp1
        + sym.diff(Rparallel, theta2) * dt2
        + sym.diff(Rparallel, phi2) * dp2
    )
    if isinstance(dRparallel, (list, np.ndarray)):
        dRparallel = dRparallel[0]
    dRparallel = dRparallel.subs(
        {
            theta1: t01,
            phi1: p01,
            theta2: t02,
            phi2: p02,
        }
    ).evalf()
    Rparallel = Rparallel.subs(
        {
            theta1: t01,
            phi1: p01,
            theta2: t02,
            phi2: p02,
        }
    ).evalf()
    return dRparallel, Rparallel

calculate_linearised_resistance_series(GMR, AMR, SMR, stationary_angles, linearised_angles)

Compute the resistance of the two FM bilayer system from the linearised angles.

Parameters:

Name Type Description Default
GMR float

GMR

required
AMR list[float]

AMR

required
SMR list[float]

SMR

required
stationary_angles list[float]

stationary angles [t1, p1, t2, p2]

required
linearised_angles list[float]

linearised angles [dt1, dp1, dt2, dp2]

required
Source code in cmtj/utils/resistance.py
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
def calculate_linearised_resistance_series(
    GMR: float,
    AMR: list[float],
    SMR: list[float],
    stationary_angles: list[float],
    linearised_angles: list[float],
) -> tuple[float, float]:
    """
    Compute the resistance of the two FM bilayer system from the linearised angles.
    :param GMR: GMR
    :param AMR: AMR
    :param SMR: SMR
    :param stationary_angles: stationary angles [t1, p1, t2, p2]
    :param linearised_angles: linearised angles [dt1, dp1, dt2, dp2]
    """
    t01, p01 = stationary_angles[:2]
    t02, p02 = stationary_angles[2:]
    dt1, dp1 = linearised_angles[:2]
    dt2, dp2 = linearised_angles[2:]
    Rxx1, Rxx2, GMR_resistance, theta1, phi1, theta2, phi2 = calculate_linearised_resistance(GMR, AMR, SMR)
    Rseries = GMR_resistance + Rxx1 + Rxx2
    dRseries = (
        sym.diff(Rseries, theta1) * dt1
        + sym.diff(Rseries, phi1) * dp1
        + sym.diff(Rseries, theta2) * dt2
        + sym.diff(Rseries, phi2) * dp2
    )

    dRseries = dRseries.subs(
        {
            theta1: t01,
            phi1: p01,
            theta2: t02,
            phi2: p02,
        }
    ).evalf()
    Rseries = Rseries.subs(
        {
            theta1: t01,
            phi1: p01,
            theta2: t02,
            phi2: p02,
        }
    ).evalf()
    return dRseries, Rseries

calculate_magnetoresistance(Rp, Rap, m)

Computes the magnetoresistance using parallel and antiparallel resistance.

Parameters:

Name Type Description Default
Rp float

parallel resistance

required
Rap float

antiparallel resistance

required
m np.ndarray

magnetisation, 2 layers of shape [2, 3, T] where T is the time component

required
Source code in cmtj/utils/resistance.py
77
78
79
80
81
82
83
84
85
86
87
def calculate_magnetoresistance(Rp: float, Rap: float, m: np.ndarray) -> np.ndarray:
    """Computes the magnetoresistance using parallel and antiparallel resistance.
    :param Rp: parallel resistance
    :param Rap: antiparallel resistance
    :param m: magnetisation, 2 layers of shape [2, 3, T] where T is the time component
    """
    if not isinstance(m, np.ndarray):
        m = np.asarray(m)
    if m.shape[0] != 2:
        raise ValueError("The magnetoresistance can only be computed for 2 layers" f". Current shape {m.shape}")
    return Rp + 0.5 * (Rap - Rp) * np.sum(m[0] * m[1], axis=0)

calculate_resistance_parallel(Rx0, Ry0, AMR, AHE, SMR, m, l, w)

Calculates the resistance of the system in parallel. If you want to compute the resistance for an entire time series, pass m as a 3D array. [number_of_layers, 3, T] where T is the time component. Uses Kim's formula from the paper: https://link.aps.org/doi/10.1103/PhysRevLett.116.097201

Parameters:

Name Type Description Default
Rx0 list[float]

resistance offset in longitudinal direction

required
Ry0 list[float]

resistance offset in transverse direction

required
AMR list[float]

anisotropic magnetoresistance

required
AHE list[float]

anomalous Hall effect

required
SMR list[float]

spin Hall magnetoresistance

required
m list[float]

magnetisation of the layers. Shape [number_of_layers, 3, T]

required
l list[float]

length of the layers

required
w list[float]

width of the layers

required
Source code in cmtj/utils/resistance.py
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
def calculate_resistance_parallel(
    Rx0: list[float],
    Ry0: list[float],
    AMR: list[float],
    AHE: list[float],
    SMR: list[float],
    m: list[float],
    l: list[float],
    w: list[float],
) -> tuple[np.ndarray, np.ndarray]:
    """Calculates the resistance of the system in parallel.
    If you want to compute the resistance for an entire time series, pass m as a 3D array.
    [number_of_layers, 3, T] where T is the time component.
    Uses Kim's formula from the paper:
    https://link.aps.org/doi/10.1103/PhysRevLett.116.097201

    :param Rx0: resistance offset in longitudinal direction
    :param Ry0: resistance offset in transverse direction
    :param AMR: anisotropic magnetoresistance
    :param AHE: anomalous Hall effect
    :param SMR: spin Hall magnetoresistance
    :param m: magnetisation of the layers. Shape [number_of_layers, 3, T]
    :param l: length of the layers
    :param w: width of the layers
    """
    SxAll, SyAll = compute_resistance(Rx0, Ry0, AMR, AHE, SMR, m, l, w)
    Rx = 1.0 / np.sum(1.0 / SxAll, axis=0)
    Ry = 1.0 / np.sum(1.0 / SyAll, axis=0)
    return Rx, Ry

calculate_resistance_series(Rx0, Ry0, AMR, AHE, SMR, m, l, w)

Calculates the resistance of the system in series. If you want to compute the resistance for an entire time series, pass m as a 3D array. [number_of_layers, 3, T] where T is the time component. Uses Kim's formula from the paper: https://link.aps.org/doi/10.1103/PhysRevLett.116.097201

Parameters:

Name Type Description Default
Rx0 list[float]

resistance offset in longitudinal direction

required
Ry0 list[float]

resistance offset in transverse direction

required
AMR list[float]

anisotropic magnetoresistance

required
AHE list[float]

anomalous Hall effect

required
SMR list[float]

spin Hall magnetoresistance

required
m list[float]

magnetisation of the layers. Shape [number_of_layers, 3, T]

required
l list[float]

length of the layers

required
w list[float]

width of the layers

required
Source code in cmtj/utils/resistance.py
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
def calculate_resistance_series(
    Rx0: list[float],
    Ry0: list[float],
    AMR: list[float],
    AHE: list[float],
    SMR: list[float],
    m: list[float],
    l: list[float],
    w: list[float],
) -> tuple[np.ndarray, np.ndarray]:
    """Calculates the resistance of the system in series.
    If you want to compute the resistance for an entire time series, pass m as a 3D array.
    [number_of_layers, 3, T] where T is the time component.
    Uses Kim's formula from the paper:
    https://link.aps.org/doi/10.1103/PhysRevLett.116.097201

    :param Rx0: resistance offset in longitudinal direction
    :param Ry0: resistance offset in transverse direction
    :param AMR: anisotropic magnetoresistance
    :param AHE: anomalous Hall effect
    :param SMR: spin Hall magnetoresistance
    :param m: magnetisation of the layers. Shape [number_of_layers, 3, T]
    :param l: length of the layers
    :param w: width of the layers
    """
    SxAll, SyAll = compute_resistance(Rx0, Ry0, AMR, AHE, SMR, m, l, w)
    Rx = np.sum(SxAll, axis=0)
    Ry = np.sum(SyAll, axis=0)
    return Rx, Ry

compute_gmr(Rp, Rap, m1, m2)

Computes the GMR using parallel and antiparallel resistance.

Parameters:

Name Type Description Default
Rp float

parallel resistance

required
Rap float

antiparallel resistance

required
m1 np.ndarray

magnetisation of layer 1

required
m2 np.ndarray

magnetisation of layer 2

required
Source code in cmtj/utils/resistance.py
68
69
70
71
72
73
74
def compute_gmr(Rp: float, Rap: float, m1: np.ndarray, m2: np.ndarray) -> np.ndarray:
    """Computes the GMR using parallel and antiparallel resistance.
    :param Rp: parallel resistance
    :param Rap: antiparallel resistance
    :param m1: magnetisation of layer 1
    :param m2: magnetisation of layer 2"""
    return Rp + 0.5 * (Rap - Rp) * (1 - np.sum(m1 * m2, axis=0))

compute_resistance(Rx0, Ry0, AMR, AHE, SMR, m, l, w)

Computes the resistance of the system.

If you want to compute the resistance for an entire time series, pass m as a 3D array with shape [number_of_layers, 3, T], where T is the time component. [number_of_layers, 3, T] where T is the time component.

Parameters:

Name Type Description Default
Rx0 list[float]

resistance offset in longitudinal direction

required
Ry0 list[float]

resistance offset in transverse direction

required
AMR list[float]

anisotropic magnetoresistance

required
AHE list[float]

anomalous Hall effect

required
SMR list[float]

spin Hall magnetoresistance

required
m Union[list[float], np.ndarray]

magnetisation of the layers. Shape [number_of_layers, 3, T]

required
l list[float]

length of the layers

required
w list[float]

width of the layers

required
Source code in cmtj/utils/resistance.py
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
def compute_resistance(
    Rx0: list[float],
    Ry0: list[float],
    AMR: list[float],
    AHE: list[float],
    SMR: list[float],
    m: Union[list[float], np.ndarray],
    l: list[float],
    w: list[float],
) -> tuple[list[float], list[float]]:
    """Computes the resistance of the system.

    If you want to compute the resistance for an entire time series, pass m as a 3D array
    with shape [number_of_layers, 3, T], where T is the time component.
    [number_of_layers, 3, T] where T is the time component.

    :param Rx0: resistance offset in longitudinal direction
    :param Ry0: resistance offset in transverse direction
    :param AMR: anisotropic magnetoresistance
    :param AHE: anomalous Hall effect
    :param SMR: spin Hall magnetoresistance
    :param m: magnetisation of the layers. Shape [number_of_layers, 3, T]
    :param l: length of the layers
    :param w: width of the layers
    """
    number_of_layers = len(Rx0)
    if not isinstance(m, np.ndarray):
        m = np.asarray(m)
    if m.ndim == 2:
        SxAll = np.zeros((number_of_layers,))
        SyAll = np.zeros((number_of_layers,))

    elif m.ndim == 3:
        SxAll = np.zeros((number_of_layers, m.shape[2]))
        SyAll = np.zeros((number_of_layers, m.shape[2]))

    for i in range(number_of_layers):
        w_l = w[i] / l[i]
        SxAll[i] = Rx0[i] + (AMR[i] * m[i, 0] ** 2 + SMR[i] * m[i, 1] ** 2)
        SyAll[i] = Ry0[i] + 0.5 * AHE[i] * m[i, 2] + (w_l) * (SMR[i] - AMR[i]) * m[i, 0] * m[i, 1]
    return SxAll, SyAll

compute_sd(dynamic_r, dynamic_i, integration_step)

Computes the SD voltage.

Parameters:

Name Type Description Default
dynamic_r np.ndarray

magnetoresistance from log

required
dynamic_i np.ndarray

excitation current

required
integration_step float

integration paramemter from run_simulation

required
Source code in cmtj/utils/resistance.py
12
13
14
15
16
17
18
19
20
21
22
def compute_sd(dynamic_r: np.ndarray, dynamic_i: np.ndarray, integration_step: float) -> np.ndarray:
    """Computes the SD voltage.

    :param dynamic_r: magnetoresistance from log
    :param dynamic_i: excitation current
    :param integration_step: integration paramemter from run_simulation
    """
    SD = -dynamic_i * dynamic_r
    fs = 1.0 / integration_step
    SD_dc = Filters.butter_lowpass_filter(SD, cutoff=10e6, fs=fs, order=3)
    return np.mean(SD_dc)