diff --git a/PySpice/Spice/Simulation.py b/PySpice/Spice/Simulation.py index 62ad4da8a..d79676a31 100644 --- a/PySpice/Spice/Simulation.py +++ b/PySpice/Spice/Simulation.py @@ -58,7 +58,6 @@ def to_list(self): ############################################## def __str__(self): - return '.{0.analysis_name} {1}'.format(self, join_list(self.to_list())) #################################################################################################### @@ -80,7 +79,6 @@ class DcSensitivityAnalysisParameters(AnalysisParameters): ############################################## def __init__(self, output_variable): - self._output_variable = output_variable ############################################## @@ -92,7 +90,6 @@ def output_variable(self): ############################################## def to_list(self): - return ( self._output_variable, ) @@ -144,7 +141,6 @@ def stop_frequencyr(self): ############################################## def to_list(self): - return ( self._output_variable, self._variation, @@ -183,7 +179,6 @@ def parameters(self): ############################################## def to_list(self): - return self._parameters #################################################################################################### @@ -297,6 +292,37 @@ def to_list(self): #################################################################################################### +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 + + ############################################## + + def to_list(self): + return self._parameters + +#################################################################################################### + class CircuitSimulation: """Define and generate the spice instruction to perform a circuit simulation. @@ -315,6 +341,7 @@ def __init__(self, circuit, **kwargs): self._circuit = circuit self._options = {} # .options + self._measures = [] # .measure self._initial_condition = {} # .ic self._saved_nodes = set() self._analyses = {} @@ -424,27 +451,27 @@ def save_currents(self, value): ############################################## def reset_analysis(self): - self._analyses.clear() ############################################## def analysis_iter(self): - return self._analyses.values() ############################################## def _add_analysis(self, analysis_parameters): - self._analyses[analysis_parameters.analysis_name] = analysis_parameters ############################################## - def operating_point(self): + def _add_measure(self, measure_parameters): + self._measures.append(measure_parameters) - """Compute the operating point of the circuit with capacitors open and inductors shorted.""" + ############################################## + def operating_point(self): + """Compute the operating point of the circuit with capacitors open and inductors shorted.""" self._add_analysis(OperatingPointAnalysisParameters()) ############################################## @@ -586,6 +613,29 @@ def ac(self, variation, number_of_points, start_frequency, stop_frequency): ############################################## + def measure(self, analysis_type, name, *args): + + """Add a measure in the circuit. + + Examples of usage:: + + simulator.measure('TRAN', 'tdiff', 'TRIG AT=10m', 'TARG v(n1) VAL=75.0 CROSS=1') + simulator.measure('tran', 'tdiff', 'TRIG AT=0m', f"TARG par('v(n1)-v(derate)') VAL=0 CROSS=1") + + Note: can be used with the .options AUTOSTOP to stop the simulation at Trigger. + + Spice syntax: + + .. code:: spice + + .meas tran tdiff TRIG AT=0m TARG v(n1) VAL=75.0 CROSS=1 + + """ + + self._add_measure(MeasureParameters(analysis_type, name, *args)) + + ############################################## + def transient(self, step_time, end_time, start_time=0, max_time=None, use_initial_condition=False): @@ -646,6 +696,8 @@ def __str__(self): else: all_str = '' netlist += '.save ' + all_str + join_list(saved_nodes) + os.linesep + for measure_parameters in self._measures: + netlist += str(measure_parameters) + os.linesep for analysis_parameters in self._analyses.values(): netlist += str(analysis_parameters) + os.linesep netlist += '.end' + os.linesep @@ -732,29 +784,24 @@ def _run(self, analysis_method, *args, **kwargs): ############################################## def operating_point(self, *args, **kwargs): - return self._run('operating_point', *args, **kwargs) ############################################## def dc(self, *args, **kwargs): - return self._run('dc', *args, **kwargs) ############################################## def dc_sensitivity(self, *args, **kwargs): - return self._run('dc_sensitivity', *args, **kwargs) ############################################## def ac(self, *args, **kwargs): - return self._run('ac', *args, **kwargs) ############################################## def transient(self, *args, **kwargs): - return self._run('transient', *args, **kwargs)