diff --git a/cmtj/models/domain_dynamics.py b/cmtj/models/domain_dynamics.py index 075f5ef..1520f7e 100644 --- a/cmtj/models/domain_dynamics.py +++ b/cmtj/models/domain_dynamics.py @@ -172,10 +172,7 @@ def get_unrelaxed_domain_width(self, effective=False): """Domain width is based off the effective perpendicular anisotropy. We reduce the perpendicular anisotropy by demagnetising field""" # Keff = self.Ku - 0.5*mu0*(self.Ms)**2 - if effective: - Keff = self.Ku - (0.5 * mu0) * (self.Ms**2) - else: - Keff = self.Ku + Keff = self.Ku - (0.5 * mu0) * (self.Ms**2) if effective else self.Ku return math.sqrt(self.A / Keff) def set_current_function(self, driver: Callable): diff --git a/cmtj/models/general_sb.py b/cmtj/models/general_sb.py index f94a27c..c4b2839 100644 --- a/cmtj/models/general_sb.py +++ b/cmtj/models/general_sb.py @@ -26,9 +26,7 @@ def wrap_fn(*args): @njit def fast_norm(x): """Fast norm function for 1D arrays.""" - sum_ = 0 - for x_ in x: - sum_ += x_**2 + sum_ = sum(x_**2 for x_ in x) return math.sqrt(sum_) @@ -42,8 +40,9 @@ def general_hessian_functional(N: int): for i in range(N): # indx_i = str(i + 1) # for display purposes indx_i = str(i) - all_symbols.append(sym.Symbol(r"\theta_" + indx_i)) - all_symbols.append(sym.Symbol(r"\phi_" + indx_i)) + all_symbols.extend( + (sym.Symbol(r"\theta_" + indx_i), sym.Symbol(r"\phi_" + indx_i)) + ) energy_functional_expr = sym.Function("E")(*all_symbols) return get_hessian_from_energy_expr( N, energy_functional_expr), energy_functional_expr @@ -76,16 +75,13 @@ def get_hessian_from_energy_expr(N: int, energy_functional_expr: sym.Expr): hessian[2 * i + 1][2 * j + 1] = expr hessian[2 * j + 1][2 * i + 1] = expr + s1 = sym.Symbol(r"\theta_" + indx_i) + s2 = sym.Symbol(r"\phi_" + indx_j) + expr = sym.diff(energy_functional_expr, s1, s2) if i == j: - s1 = sym.Symbol(r"\theta_" + indx_i) - s2 = sym.Symbol(r"\phi_" + indx_j) - expr = sym.diff(energy_functional_expr, s1, s2) hessian[2 * i + 1][2 * j] = expr + sym.I * z hessian[2 * i][2 * j + 1] = expr - sym.I * z else: - s1 = sym.Symbol(r"\theta_" + indx_i) - s2 = sym.Symbol(r"\phi_" + indx_j) - expr = sym.diff(energy_functional_expr, s1, s2) hessian[2 * i][2 * j + 1] = expr hessian[2 * j + 1][2 * i] = expr @@ -185,11 +181,11 @@ def symbolic_layer_energy(self, H: sym.Matrix, J1top: float, top_iec_energy = 0 bottom_iec_energy = 0 - if not (top_layer is None): + if top_layer is not None: other_m = top_layer.get_m_sym() top_iec_energy = -(J1top / self.thickness) * m.dot(other_m) - ( J2top / self.thickness) * m.dot(other_m)**2 - if not (down_layer is None): + if down_layer is not None: other_m = down_layer.get_m_sym() bottom_iec_energy = -(J1bottom / self.thickness) * m.dot( other_m) - (J2bottom / self.thickness) * m.dot(other_m)**2 @@ -210,11 +206,7 @@ def no_iec_symbolic_layer_energy(self, H: sym.Matrix): def sb_correction(self): omega = sym.Symbol(r'\omega') - # we use unreduced gamma - # later we don't need to divide omega by 2pi - # idk but if we use reduced gamma it numerically breaks lol - Z = (omega / gamma) * self.Ms * sym.sin(self.theta) * self.thickness - return Z + return (omega / gamma) * self.Ms * sym.sin(self.theta) * self.thickness @dataclass @@ -230,7 +222,7 @@ def __post_init__(self): if len(self.layers) != len(self.J2) + 1: raise ValueError("Number of layers must be 1 more than J2.") - id_sets = set([layer._id for layer in self.layers]) + id_sets = {layer._id for layer in self.layers} ideal_set = set(range(len(self.layers))) if id_sets != ideal_set: raise ValueError("Layer ids must be 0, 1, 2, ... and unique") @@ -286,7 +278,7 @@ def create_energy(self, top_layer, bottom_layer) else: # surface energy for correct angular gradient - for i, layer in enumerate(self.layers): + for layer in self.layers: # to avoid dividing J by thickness energy += layer.no_iec_symbolic_layer_energy( H) * layer.thickness @@ -322,13 +314,12 @@ def create_energy_hessian(self, equilibrium_position: List[float]): hessian[2 * i + 1][2 * j + 1] = expr hessian[2 * j + 1][2 * i + 1] = expr + expr = sym.diff(sym.diff(energy, theta_i), phi_j) # mixed terms if i == j: - expr = sym.diff(sym.diff(energy, theta_i), phi_j) hessian[2 * i + 1][2 * j] = expr + sym.I * z hessian[2 * i][2 * j + 1] = expr - sym.I * z else: - expr = sym.diff(sym.diff(energy, theta_i), phi_j) hessian[2 * i][2 * j + 1] = expr hessian[2 * j + 1][2 * i] = expr @@ -347,10 +338,8 @@ def get_gradient_expr(self, accel="math"): symbols = [] for layer in self.layers: (theta, phi) = layer.get_coord_sym() - grad_vector.append(sym.diff(energy, theta)) - grad_vector.append(sym.diff(energy, phi)) - symbols.append(theta) - symbols.append(phi) + grad_vector.extend((sym.diff(energy, theta), sym.diff(energy, phi))) + symbols.extend((theta, phi)) return sym.lambdify(symbols, grad_vector, accel) def adam_gradient_descent(self, @@ -508,9 +497,7 @@ def analytical_roots(self): energy_expression=system_energy, subs={}) subs.update(self.get_ms_subs()) - # substitute all known values - solutions = [s.subs(subs) for s in root_expr] - return solutions + return [s.subs(subs) for s in root_expr] def get_subs(self, equilibrium_position: List[float]): """Returns the substitution dictionary for the energy expression.""" @@ -528,7 +515,7 @@ def get_ms_subs(self): r"t_{" + str(layer._id) + r"}": layer.thickness for layer in self.layers } - return {**a, **b} + return a | b def set_H(self, H: VectorObj): """Sets the external field.""" diff --git a/cmtj/models/oersted.py b/cmtj/models/oersted.py index ed81721..9fe44ff 100644 --- a/cmtj/models/oersted.py +++ b/cmtj/models/oersted.py @@ -65,9 +65,7 @@ def ampere_law(self, other_block: 'Block'): (other_block.x, other_block.y)) def __eq__(self, __o: 'Block') -> bool: - if (self.ix == __o.ix) and (self.iy == __o.iy) and (self.iz == __o.iz): - return True - return False + return self.ix == __o.ix and self.iy == __o.iy and self.iz == __o.iz class Structure: diff --git a/cmtj/utils/energy.py b/cmtj/utils/energy.py index dcb682c..9dc7181 100644 --- a/cmtj/utils/energy.py +++ b/cmtj/utils/energy.py @@ -22,7 +22,7 @@ def compute_from_log(self) -> Dict[str, List[float]]: Computes a log of energies over time and returns it in the same form of the """ - field_keys = list(set((k[:-1] for k in self.log if "_H" in k))) + field_keys = list({k[:-1] for k in self.log if "_H" in k}) mag_k = (k.replace("_mx", "") for k in self.log if "_mx" in k) mag_vectors = { k: np.asarray([ diff --git a/cmtj/utils/filters.py b/cmtj/utils/filters.py index 4710160..72e2ca4 100644 --- a/cmtj/utils/filters.py +++ b/cmtj/utils/filters.py @@ -36,8 +36,7 @@ def butter_bandpass_filter(data: np.ndarray, b, a = butter(order, [pass_freq[0], pass_freq[1]], btype="bandpass", analog=False) - y = lfilter(b, a, data, zi=None) - return y + return lfilter(b, a, data, zi=None) @staticmethod def butter_lowpass_filter(data: np.ndarray, @@ -53,8 +52,7 @@ def butter_lowpass_filter(data: np.ndarray, nyq = 0.5 * fs normal_cutoff = cutoff / nyq b, a = butter(order, normal_cutoff, btype="low", analog=False) - y = lfilter(b, a, data, zi=None) - return y + return lfilter(b, a, data, zi=None) @staticmethod def detrend_axis(arr, axis): @@ -63,8 +61,4 @@ def detrend_axis(arr, axis): :param axis: axis along which to detrend """ medians = np.median(arr, axis=axis) - if axis: - detrended = (arr.T - medians).T - else: - detrended = arr - medians - return detrended + return (arr.T - medians).T if axis else arr - medians diff --git a/cmtj/utils/plotting.py b/cmtj/utils/plotting.py index 7a97454..8755e2d 100644 --- a/cmtj/utils/plotting.py +++ b/cmtj/utils/plotting.py @@ -170,7 +170,7 @@ def create_coordinates_plot(axes, zs[:, 0] = ys[:, 0] zs[:, 1:] = (ys[:, 1:] - ymins[1:]) / dys[1:] * dys[0] + ymins[0] - axes = [host] + [host.twinx() for i in range(ys.shape[1] - 1)] + axes = [host] + [host.twinx() for _ in range(ys.shape[1] - 1)] for i, ax in enumerate(axes): ax.set_ylim(ymins[i], ymaxs[i]) ax.spines['top'].set_visible(False) @@ -196,19 +196,20 @@ def create_coordinates_plot(axes, # x-coordinate of the control vertices: at each integer (for the axes) and two inbetween # y-coordinate: repeat every point three times, except the first and last only twice verts = list( - zip([ - x for x in np.linspace( - 0, len(ys) - 1, len(ys) * 3 - 2, endpoint=True) - ], - np.repeat(zs[j, :], 3)[1:-1])) + zip( + list( + np.linspace( + 0, len(ys) - 1, len(ys) * 3 - 2, endpoint=True + ) + ), + np.repeat(zs[j, :], 3)[1:-1], + ) + ) # for x,y in verts: host.plot(x, y, 'go') # to show the control points of the beziers codes = [Path.MOVETO ] + [Path.CURVE4 for _ in range(len(verts) - 1)] path = Path(verts, codes) - if ys[j, -1] == 0: - alpha = alpha_black - else: - alpha = 0.8 + alpha = alpha_black if ys[j, -1] == 0 else 0.8 patch = patches.PathPatch(path, facecolor='none', lw=.5, @@ -277,7 +278,7 @@ def create_stack(ax, verticalalignment='center', fontsize=text_fontsize, zorder=11) - if not (angle is None): + if angle is not None: [dx, dy] = np.dot(rotation_matrix(np.deg2rad(angle)), [x, y]) x_mid = dx / 2 y_mid = dy / 2 diff --git a/cmtj/utils/resistance.py b/cmtj/utils/resistance.py index 72f851d..b1e29e3 100644 --- a/cmtj/utils/resistance.py +++ b/cmtj/utils/resistance.py @@ -53,8 +53,7 @@ def calculate_magnetoresistance(Rp: float, Rap: float, m: np.ndarray): raise ValueError( "The magnetoresistance can only be computed for 2 layers" f". Current shape {m.shape}") - R = Rp + 0.5 * (Rap - Rp) * np.sum(m[0] * m[1], axis=0) - return R + return Rp + 0.5 * (Rap - Rp) * np.sum(m[0] * m[1], axis=0) def calculate_resistance_parallel(Rx0: List[float], Ry0: List[float], diff --git a/cmtj/utils/solvers.py b/cmtj/utils/solvers.py index 54fe005..4c7402a 100644 --- a/cmtj/utils/solvers.py +++ b/cmtj/utils/solvers.py @@ -43,6 +43,4 @@ def find(self, f, *args, **kwargs): def find_root(self, f, x0, *args, fprime=None): sol = root(f, x0, args=args, jac=fprime, method="hybr") - if sol.success: - return sol.x[0] - return None + return sol.x[0] if sol.success else None diff --git a/examples/networks/training.py b/examples/networks/training.py index 07d4241..68f78d5 100644 --- a/examples/networks/training.py +++ b/examples/networks/training.py @@ -85,7 +85,6 @@ def __init__(self, else: raise ValueError(f"Unknown loss type: {loss_type}") - infeat = 2998 * 80 self.model = nn.Sequential( nn.Flatten(), nn.Linear(in_features=infeat, out_features=2048), nn.ReLU(), nn.Dropout(p=1 - keep_prob), @@ -162,8 +161,7 @@ def validation_epoch_end(self, outputs): return {'val_loss': avg_loss} def configure_optimizers(self): - opt = torch.optim.Adam(self.parameters(), lr=self.hparams.lr) - return opt + return torch.optim.Adam(self.parameters(), lr=self.hparams.lr) if __name__ == "__main__": diff --git a/setup.py b/setup.py index b4c3c70..2cf1fee 100644 --- a/setup.py +++ b/setup.py @@ -122,10 +122,7 @@ def build_extensions(self): opts.append("-fvisibility=hidden") for ext in self.extensions: - ext.define_macros = [ - ("VERSION_INFO", - '"{}"'.format(self.distribution.get_version())) - ] + ext.define_macros = [("VERSION_INFO", f'"{self.distribution.get_version()}"')] ext.extra_compile_args = opts ext.extra_link_args = link_opts build_ext.build_extensions(self)