###################################################################################################
#
# PySpice - A Spice Package for Python
# Copyright (C) 2021 Fabrice Salvaire
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
####################################################################################################
"""This modules provides classes to handle analysis parameters.
"""
####################################################################################################
__all__ = [
'ACAnalysisParameters',
'AcSensitivityAnalysisParameters',
'DCAnalysisParameters',
'DcSensitivityAnalysisParameters',
'DistortionAnalysisParameters',
'MeasureParameters',
'NoiseAnalysisParameters',
'OperatingPointAnalysisParameters',
'PoleZeroAnalysisParameters',
'TransferFunctionAnalysisParameters',
'TransientAnalysisParameters',
]
####################################################################################################
import logging
####################################################################################################
from ..Tools.StringTools import join_list
from ..Unit import as_s, as_Hz
####################################################################################################
_module_logger = logging.getLogger(__name__)
####################################################################################################
[docs]class AnalysisParameters:
"""Base class for analysis parameters"""
_ANALYSIS_NAME = None
##############################################
@property
def analysis_name(self):
return self._ANALYSIS_NAME
##############################################
[docs] def to_list(self):
return ()
##############################################
def __str__(self):
return '.{0.analysis_name} {1}'.format(self, join_list(self.to_list()))
####################################################################################################
[docs]class OperatingPointAnalysisParameters(AnalysisParameters):
"""This class defines analysis parameters for operating point analysis."""
_ANALYSIS_NAME = 'op'
####################################################################################################
[docs]class DcSensitivityAnalysisParameters(AnalysisParameters):
"""This class defines analysis parameters for DC sensitivity analysis."""
_ANALYSIS_NAME = 'sens'
##############################################
def __init__(self, output_variable):
self._output_variable = output_variable
##############################################
@property
def output_variable(self):
return self._output_variable
##############################################
[docs] def to_list(self):
return (self._output_variable,)
####################################################################################################
[docs]class AcSensitivityAnalysisParameters(AnalysisParameters):
"""This class defines analysis parameters for AC sensitivity analysis."""
_ANALYSIS_NAME = 'sens'
##############################################
def __init__(self, output_variable, variation, number_of_points, start_frequency, stop_frequency):
if variation not in ('dec', 'oct', 'lin'):
raise ValueError("Incorrect variation type")
self._output_variable = output_variable
self._variation = variation
self._number_of_points = number_of_points
self._start_frequency = as_Hz(start_frequency)
self._stop_frequency = as_Hz(stop_frequency)
##############################################
@property
def output_variable(self):
return self._output_variable
@property
def variation(self):
return self._variation
@property
def number_of_points(self):
return self._number_of_points
@property
def start_frequency(self):
return self._start_frequency
@property
def stop_frequency(self):
return self._stop_frequency
##############################################
[docs] def to_list(self):
return (
self._output_variable,
self._variation,
self._number_of_points,
self._start_frequency,
self._stop_frequency
)
####################################################################################################
[docs]class DCAnalysisParameters(AnalysisParameters):
"""This class defines analysis parameters for DC analysis."""
_ANALYSIS_NAME = 'dc'
##############################################
def __init__(self, **kwargs):
self._parameters = []
for variable, value_slice in kwargs.items():
variable_lower = variable.lower()
if variable_lower[0] in ('v', 'i', 'r') or variable_lower == 'temp':
self._parameters += [variable, value_slice.start, value_slice.stop, value_slice.step]
else:
raise NameError('Sweep variable must be a voltage/current source, '
'a resistor or the circuit temperature')
##############################################
@property
def parameters(self):
return self._parameters
##############################################
[docs] def to_list(self):
return self._parameters
####################################################################################################
[docs]class ACAnalysisParameters(AnalysisParameters):
"""This class defines analysis parameters for AC analysis."""
_ANALYSIS_NAME = 'ac'
##############################################
def __init__(self, variation, number_of_points, start_frequency, stop_frequency):
# Fixme: use mixin
if variation not in ('dec', 'oct', 'lin'):
raise ValueError("Incorrect variation type")
self._variation = variation
self._number_of_points = number_of_points
self._start_frequency = as_Hz(start_frequency)
self._stop_frequency = as_Hz(stop_frequency)
##############################################
@property
def variation(self):
return self._variation
@property
def number_of_points(self):
return self._number_of_points
@property
def start_frequency(self):
return self._start_frequency
@property
def stop_frequency(self):
return self._stop_frequency
##############################################
[docs] def to_list(self):
return (
self._variation,
self._number_of_points,
self._start_frequency,
self._stop_frequency
)
####################################################################################################
[docs]class TransientAnalysisParameters(AnalysisParameters):
"""This class defines analysis parameters for transient analysis."""
_ANALYSIS_NAME = 'tran'
##############################################
def __init__(self, step_time, end_time, start_time=0, max_time=None, use_initial_condition=False):
self._step_time = as_s(step_time)
self._end_time = as_s(end_time)
self._start_time = as_s(start_time)
self._max_time = as_s(max_time, none=True)
self._use_initial_condition = use_initial_condition
##############################################
@property
def step_time(self):
return self._step_time
@property
def end_time(self):
return self._end_time
@property
def start_time(self):
return self._start_time
@property
def max_time(self):
return self._max_time
@property
def use_initial_condition(self):
return self._use_initial_condition
##############################################
[docs] def to_list(self):
return (
self._step_time,
self._end_time,
self._start_time,
self._max_time,
'uic' if self._use_initial_condition else None,
)
####################################################################################################
[docs]class MeasureParameters(AnalysisParameters):
"""This class defines measurements on analysis.
"""
_ANALYSIS_NAME = 'meas'
##############################################
def __init__(self, analysis_type, name, *args):
_analysis_type = str(analysis_type).upper()
if _analysis_type not in ('AC', 'DC', 'OP', 'TRAN', 'TF', 'NOISE'):
raise ValueError('Incorrect analysis type {}'.format(analysis_type))
self._parameters = [_analysis_type, name, *args]
##############################################
@property
def parameters(self):
return self._parameters
##############################################
[docs] def to_list(self):
return self._parameters
####################################################################################################
[docs]class PoleZeroAnalysisParameters(AnalysisParameters):
"""This class defines analysis parameters for pole-zero analysis."""
_ANALYSIS_NAME = 'pz'
##############################################
def __init__(self, node1, node2, node3, node4, tf_type, pz_type):
self._nodes = (node1, node2, node3, node4)
self._tf_type = tf_type # transfert_function
self._pz_type = pz_type # pole_zero
##############################################
@property
def node1(self):
return self._nodes[0]
@property
def node2(self):
return self._nodes[1]
[docs] def node3(self):
return self._nodes[2]
@property
def node4(self):
return self._nodes[3]
@property
def tf_type(self):
return self._tf_type
@property
def pz_type(self):
return self._pz_type
##############################################
[docs] def to_list(self):
return list(self._nodes) + [self._tf_type, self._pz_type]
####################################################################################################
[docs]class NoiseAnalysisParameters(AnalysisParameters):
"""This class defines analysis parameters for noise analysis."""
_ANALYSIS_NAME = 'noise'
##############################################
def __init__(self, output, src, variation, points, start_frequency, stop_frequency, points_per_summary):
self._output = output
self._src = src
self._variation = variation
self._points = points
self._start_frequency = start_frequency
self._stop_frequency = stop_frequency
self._points_per_summary = points_per_summary
##############################################
@property
def output(self):
return self._output
@property
def src(self):
return self._src
@property
def variation(self):
return self._variation
@property
def points(self):
return self._points
# Fixme: mixin
@property
def start_frequency(self):
return self._start_frequency
@property
def stop_frequency(self):
return self._stop_frequency
@property
def points_per_summary(self):
return self._points_per_summary
##############################################
[docs] def to_list(self):
parameters = [
self._output,
self._src,
self._variation,
self._points,
self._start_frequency,
self._stop_frequency,
]
if self._points_per_summary:
parameters.append(self._points_per_summary)
return parameters
####################################################################################################
[docs]class DistortionAnalysisParameters(AnalysisParameters):
"""This class defines analysis parameters for distortion analysis."""
_ANALYSIS_NAME = 'disto'
##############################################
def __init__(self, variation, points, start_frequency, stop_frequency, f2overf1):
self._variation = variation
self._points = points
self._start_frequency = start_frequency
self._stop_frequency = stop_frequency
self._f2overf1 = f2overf1
##############################################
@property
def variation(self):
return self._variation
@property
def points(self):
return self._points
@property
def start_frequency(self):
return self._start_frequency
@property
def stop_frequency(self):
return self._stop_frequency
@property
def f2overf1(self):
return self._f2overf1
##############################################
[docs] def to_list(self):
parameters = [
self._variation,
self._points,
self._start_frequency,
self._stop_frequency,
]
if self._f2overf1:
parameters.append(self._f2overf1)
return parameters
####################################################################################################
[docs]class TransferFunctionAnalysisParameters(AnalysisParameters):
"""This class defines analysis parameters for transfer function (.tf) analysis."""
_ANALYSIS_NAME = 'tf'
##############################################
def __init__(self, outvar, insrc):
self._outvar = outvar
self._insrc = insrc
##############################################
@property
def outvar(self):
return self._outvar
@property
def insrc(self):
return self._insrc
##############################################
[docs] def to_list(self):
return (self._outvar, self._insrc)