diff --git a/PySpice/Spice/HighLevelElement.py b/PySpice/Spice/HighLevelElement.py index dbce6238..b5fc0775 100644 --- a/PySpice/Spice/HighLevelElement.py +++ b/PySpice/Spice/HighLevelElement.py @@ -65,6 +65,8 @@ class SinusoidalMixin(SourceMixinAbc): +------+----------------+---------------+-------+ | Df + damping factor + 0.01 + 1/sec | +------+----------------+---------------+-------+ + | phi + sin_phase + 0.0 + deg | + +------+----------------+---------------+-------+ The shape of the waveform is described by the following formula: @@ -72,12 +74,14 @@ class SinusoidalMixin(SourceMixinAbc): V(t) = \begin{cases} V_o & \text{if}\ 0 \leq t < T_d, \\ - V_o + V_a e^{-D_f(t-T_d)} \sin\left(2\pi f (t-T_d)\right) & \text{if}\ T_d \leq t < T_{stop}. + V_o + V_a e^{-D_f(t-T_d)} \sin\left(2\pi f (t-T_d) + \phi\right) & \text{if}\ T_d \leq t < T_{stop}. + V_o + V_a e^{-D_f(t-T_d)} \sin\left(2\pi f (t-T_d) + \phi\right) & \text{if}\ T_d \leq t < T_{stop}. \end{cases} Spice syntax:: - SIN ( Voffset Vamplitude Freq Tdelay DampingFactor ) + SIN ( Voffset Vamplitude Freq Tdelay DampingFactor Phase) + SIN ( Voffset Vamplitude Freq Tdelay DampingFactor Phase) Public Attributes: @@ -95,6 +99,10 @@ class SinusoidalMixin(SourceMixinAbc): :attr:`offset` + :attr:`phase` (phase of the AC component) + + :attr:`sin_phase` (phase of the sinusoidal component) + """ ############################################## @@ -102,16 +110,36 @@ class SinusoidalMixin(SourceMixinAbc): def __init__(self, dc_offset=0, ac_magnitude=1, - offset=0, amplitude=1, frequency=50, - delay=0, damping_factor=0): + ac_phase=0, + offset=None, amplitude=None, frequency=None, + delay=None, damping_factor=None, sin_phase=None): + + self.no_sin_part = False + if all(x is None for x in (offset, amplitude, frequency, delay, damping_factor, sin_phase)): + self.no_sin_part = True + if offset is None: + offset = 0 + if amplitude is None: + amplitude = 1 + if frequency is None: + frequency = 50 + if delay is None: + delay = 0 + if sin_phase is None: + sin_phase = 0 self.dc_offset = self.AS_UNIT(dc_offset) self.ac_magnitude = self.AS_UNIT(ac_magnitude) + self.ac_phase = ac_phase + self.ac_phase = ac_phase self.offset = self.AS_UNIT(offset) self.amplitude = self.AS_UNIT(amplitude) self.frequency = as_Hz(frequency) # Fixme: protect by setter? self.delay = as_s(delay) - self.damping_factor = as_Hz(damping_factor) + self.damping_factor = damping_factor + self.sin_phase = sin_phase # TODO: implement unit (as_deg?) + + ############################################## @@ -129,11 +157,16 @@ def period(self): ############################################## def format_spice_parameters(self): - sin_part = join_list((self.offset, self.amplitude, self.frequency, self.delay, self.damping_factor)) - return join_list(( - 'DC {} AC {}'.format(*str_spice_list(self.dc_offset, self.ac_magnitude)), - 'SIN({})'.format(sin_part), - )) + sin_part = join_list((self.offset, self.amplitude, self.frequency, self.delay, self.damping_factor, self.sin_phase)) + if self.no_sin_part: + return join_list(( + 'DC {} AC {} {}'.format(*str_spice_list(self.dc_offset, self.ac_magnitude, self.ac_phase)), + )) + else: + return join_list(( + 'DC {} AC {} {}'.format(*str_spice_list(self.dc_offset, self.ac_magnitude, self.ac_phase)), + 'SIN({})'.format(sin_part), + )) #################################################################################################### diff --git a/PySpice/Spice/NgSpice/Shared.py b/PySpice/Spice/NgSpice/Shared.py index 183c08a4..2878093e 100644 --- a/PySpice/Spice/NgSpice/Shared.py +++ b/PySpice/Spice/NgSpice/Shared.py @@ -90,7 +90,7 @@ import numpy as np from cffi import FFI - +import warnings #################################################################################################### from PySpice.Config import ConfigInstall @@ -621,6 +621,9 @@ def _send_char(message_c, ngspice_id, user_data): if content.startswith('Warning:'): func = self._logger.warning # elif content.startswith('Warning:'): + elif content.startswith('Error: Using SPARSE 1.3') or content.startswith('Error: bad set form'): + func = lambda x: None + else: self._error_in_stderr = True func = self._logger.error @@ -636,6 +639,7 @@ def _send_char(message_c, ngspice_id, user_data): # if self._error_in_stdout: # self._logger.warning(content) + # Fixme: ??? return self.send_char(message, ngspice_id) @@ -848,7 +852,8 @@ def exec_command(self, command, join_lines=True): raise NameError("ngSpice_Command '{}' returned {}".format(command, rc)) if self._error_in_stdout or self._error_in_stderr: - raise NgSpiceCommandError("Command '{}' failed".format(command)) + # raise NgSpiceCommandError("Command '{}' failed".format(command)) + warnings.warn('NgSpiceCommandError: Command {} warning'.format(command)) if join_lines: return self.stdout @@ -1167,7 +1172,8 @@ def load_circuit(self, circuit): # Fixme: https://sourceforge.net/p/ngspice/bugs/496/ if self._error_in_stdout: self._logger.error('\n' + self.stdout) - raise NgSpiceCircuitError('') + # raise NgSpiceCircuitError('') + warnings.warn('NgSpiceCircuitError') # for line in circuit_lines: # rc = self._ngspice_shared.ngSpice_Command(('circbyline ' + line).encode('utf8'))