Skip to content

Commit

Permalink
Merge pull request #92 from LemurPwned/feat/new-vsd
Browse files Browse the repository at this point in the history
Feat/new vsd
  • Loading branch information
LemurPwned authored Feb 14, 2025
2 parents 70210f0 + 1fb9f14 commit 870dbda
Show file tree
Hide file tree
Showing 20 changed files with 1,441 additions and 61 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

# 1.6.1

- Small fixes to the noise interfaces and resistance functions.
- Documentation updates: added a tutorial on custom dipole interactions + interface fixes and typing.

# 1.6.0

- Extended the `Stack` models allowing for non-symmetric coupling between devices.
Expand Down
26 changes: 25 additions & 1 deletion cmtj/models/general_sb.py
Original file line number Diff line number Diff line change
Expand Up @@ -861,8 +861,32 @@ def _compute_numerical_inverse(self, A_matrix):
A_inv_np = np.linalg.inv(A_np)
return sym.Matrix(A_inv_np)

@lru_cache(maxsize=1000) # noqa: B019
def _compute_A_and_V_matrices(self, n, Vdc_ex_variable, H, frequency):
A_matrix = sym.zeros(2 * n, 2 * n)
V_matrix = sym.zeros(2 * n, 1)
U = self.create_energy(H=H, volumetric=False)
omega = sym.Symbol(r"\omega") if frequency is None else 2 * sym.pi * frequency
for i, layer in enumerate(self.layers):
rhs = layer.rhs_spherical_llg(U / layer.thickness, osc=True)
alpha_factor = 1 + layer.alpha**2
V_matrix[2 * i] = sym.diff(rhs[0] * alpha_factor, Vdc_ex_variable)
V_matrix[2 * i + 1] = sym.diff(rhs[1] * alpha_factor, Vdc_ex_variable)
theta, phi = layer.get_coord_sym()
fn_theta = (omega * sym.I * theta - rhs[0]) * alpha_factor
fn_phi = (omega * sym.I * phi - rhs[1]) * alpha_factor
# the functions are only valid for that row i (theta) and i + 1 (phi)
# so we only need to compute the derivatives for the other layers
# for the other layers, the derivatives are zero
for j, layer_j in enumerate(self.layers):
theta_, phi_ = layer_j.get_coord_sym()
A_matrix[2 * i, 2 * j] = sym.diff(fn_theta, theta_)
A_matrix[2 * i, 2 * j + 1] = sym.diff(fn_theta, phi_)
A_matrix[2 * i + 1, 2 * j] = sym.diff(fn_phi, theta_)
A_matrix[2 * i + 1, 2 * j + 1] = sym.diff(fn_phi, phi_)
return A_matrix, V_matrix

@lru_cache(maxsize=1000) # noqa: B019
def _compute_A_and_V_matrices_old(self, n, Vdc_ex_variable, H, frequency):
A_matrix = sym.zeros(2 * n, 2 * n)
V_matrix = sym.zeros(2 * n, 1)
U = self.create_energy(H=H, volumetric=False)
Expand Down
11 changes: 10 additions & 1 deletion cmtj/reservoir/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -159,5 +159,14 @@ def computeDipoleInteractionNoumra(
...

def nullDipoleInteraction(r1: cmtj.CVector, r2: cmtj.CVector, layer1: cmtj.Layer, layer2: cmtj.Layer) -> cmtj.CVector:
"""Compute null dipole interaction between two junctions."""
"""Compute null dipole interaction between two junctions.
This is a placeholder function that returns a zero vector.
:param r1: Position vector of the first junction
:param r2: Position vector of the second junction
:param layer1: Magnetic layer of the first junction
:param layer2: Magnetic layer of the second junction
:return: Zero vector
"""
...
38 changes: 37 additions & 1 deletion cmtj/utils/parallel.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
from multiprocess import Pool
from tqdm import tqdm

__all__ = ["distribute"]
from ..models.general_sb import LayerDynamic

__all__ = ["distribute", "parallel_vsd_sb_model"]


def distribute(
Expand Down Expand Up @@ -47,3 +49,37 @@ def func_wrapper(iterable):
iterable, output = result
indx = indexes[iterables.index(iterable)]
yield indx, output


def parallel_vsd_sb_model(
simulation_fn: Callable,
frequencies: list[float],
Hvecs: list[list[float]],
layers: list[LayerDynamic],
J1: list[float] = None,
J2: list[float] = None,
iDMI: list[float] = None,
n_cores: int = None,
):
"""
Parallelise the VSD SB model.
:param simulation_fn: function to be distributed.
This function must take a tuple of arguments, where the first argument is the
frequency, then Hvectors, the list of layers and finally the list of J1 and J2 values.
:param frequencies: list of frequencies
:param Hvecs: list of Hvectors in cartesian coordinates
:param layers: list of layers
:param J1: list of J1 values
:param J2: list of J2 values
:param n_cores: number of cores to use.
:returns: list of simulation_fn outputs for each frequency
"""
if J1 is None:
J1 = [0] * (len(layers) - 1)
if J2 is None:
J2 = [0] * (len(layers) - 1)
if iDMI is None:
iDMI = [0] * (len(layers) - 1)
args = [(f, Hvecs, *layers, J1, J2, iDMI) for f in frequencies]
with Pool(processes=n_cores) as pool:
return list(tqdm(pool.imap(simulation_fn, args), total=len(frequencies)))
Loading

0 comments on commit 870dbda

Please sign in to comment.