Source code for memtorch.bh.memristor.Data_Driven

import math

import numpy as np

import memtorch
from memtorch.utils import clip
from .Memristor import Memristor as Memristor


[docs]class Data_Driven(Memristor): """A Data-Driven Verilog-A ReRAM Model (https://eprints.soton.ac.uk/411693/). Parameters ---------- time_series_resolution : float Time series resolution (s). r_off : float Off (maximum) resistance of the device (ohms). r_on : float On (minimum) resistance of the device (ohms). A_p : float A_p model parameter. A_n : float A_n model parameter. t_p : float t_p model parameter. t_n : float t_n model parameter. k_p : float k_p model parameter. k_n : float k_n model parameter. r_p : float r_p voltage-dependent resistive boundary function coefficients. r_n : float r_n voltage-dependent resistive boundary function coefficients. eta : int Switching direction to stimulus polarity. a_p : float a_p model parameter. a_n : float a_n model parameter. b_p : float b_p model parameter. b_n : float b_n model parameter. """ def __init__( self, time_series_resolution=1e-8, r_off=17e3, r_on=1280, A_p=743.47, A_n=-68012.28374, t_p=6.51, t_n=0.31645, k_p=5.11e-4, k_n=1.17e-3, r_p=[16719, 0], r_n=[29304.82557, 23692.77225], eta=1, a_p=0.24, a_n=0.24, b_p=3, b_n=3, **kwargs ): args = memtorch.bh.unpack_parameters(locals()) super(Data_Driven, self).__init__( args.r_off, args.r_on, args.time_series_resolution, 0, 0 ) self.A_p = args.A_p self.A_n = args.A_n self.t_p = args.t_p self.t_n = args.t_n self.k_p = args.k_p self.k_n = args.k_n self.r_p = args.r_p self.r_n = args.r_n self.eta = args.eta self.a_p = args.a_p self.a_n = args.a_n self.b_p = args.b_p self.b_n = args.b_n self.g = 1 / self.r_on
[docs] def simulate(self, voltage_signal, return_current=False): len_voltage_signal = 1 try: len_voltage_signal = len(voltage_signal) except: voltage_signal = [voltage_signal] if return_current: current = np.zeros(len_voltage_signal) np.seterr(all="raise") for t in range(0, len_voltage_signal): current_ = self.current(voltage_signal[t]) self.g = 1 / self.resistance(voltage_signal[t]) if return_current: current[t] = current_ if return_current: return current
[docs] def current(self, voltage): """Method to determine the current of the model given an applied voltage. Parameters ---------- voltage : float The current applied voltage (V). Returns ------- float The observed current (A). """ if voltage > 0: return self.a_p * self.g * math.sinh(self.b_p * voltage) else: return self.a_n * self.g * math.sinh(self.b_n * voltage)
[docs] def resistance(self, voltage): """Method to determine the resistance of the model given an applied voltage. Parameters ---------- voltage : float The current applied voltage (V). Returns ------- float The observed resistance (Ω). """ def r_pn(voltage, r_pn): sum = 0 for m_pn in range(0, len(r_pn)): sum += r_pn[m_pn] * (voltage ** (m_pn)) return sum if voltage > 0: r_pn_eval = r_pn(voltage, self.r_p) resistance_ = ( np.log( np.exp(self.eta * self.k_p * r_pn_eval) + np.exp( -self.eta * self.k_p * (self.A_p * (math.exp(self.t_p * abs(voltage)) - 1)) * self.time_series_resolution ) * ( np.exp(self.eta * self.k_p * (1 / self.g)) - np.exp(self.eta * self.k_p * r_pn_eval) ) ) / self.k_p ) if resistance_ > self.eta * r_pn_eval: return 1 / self.g else: return max( min(resistance_, self.r_off), self.r_on ) # Artificially confine the resistance between r_on and r_off elif voltage < 0: r_pn_eval = r_pn(voltage, self.r_n) resistance_ = ( -np.log( np.exp( -self.eta * self.k_n * (1 / self.g) + self.eta * self.k_n * (self.A_n * (-1 + np.exp(self.t_n * abs(voltage)))) * self.time_series_resolution ) - np.exp(-self.eta * self.k_n * r_pn_eval) * ( -1 + np.exp( self.eta * self.k_n * (self.A_n * (-1 + np.exp(self.t_n * abs(voltage)))) * self.time_series_resolution ) ) ) / self.k_n ) if resistance_ < self.eta * r_pn_eval: return 1 / self.g else: return max( min(resistance_, self.r_off), self.r_on ) # Artificially confine the resistance between r_on and r_off else: return 1 / self.g
[docs] def set_conductance(self, conductance): conductance = clip(conductance, 1 / self.r_off, 1 / self.r_on) self.g = conductance
[docs] def plot_hysteresis_loop( self, duration=1e-3, voltage_signal_amplitude=1.5, voltage_signal_frequency=10e3, return_result=False, ): return super().plot_hysteresis_loop( self, duration=duration, voltage_signal_amplitude=voltage_signal_amplitude, voltage_signal_frequency=voltage_signal_frequency, return_result=return_result, )
[docs] def plot_bipolar_switching_behaviour( self, voltage_signal_amplitude=1.5, voltage_signal_frequency=10e3, log_scale=True, return_result=False, ): return super().plot_bipolar_switching_behaviour( self, voltage_signal_amplitude=voltage_signal_amplitude, voltage_signal_frequency=voltage_signal_frequency, log_scale=log_scale, return_result=return_result, )