Adds missing transient simulation settings

Adds maximum step size setting used by transient analysis solver,
and 'use initial conditions (uic)' setting. Enabling uic disables
DC operating point analysis and may introduce singularities. It requires
a careful selection of initial conditions of circuit elements.

Fixes https://gitlab.com/kicad/code/kicad/issues/2515
This commit is contained in:
Okan Demir 2023-04-06 23:48:11 +03:00 committed by Jeff Young
parent b2bf3229e6
commit 82e8198fee
3 changed files with 79 additions and 6 deletions

View File

@ -85,6 +85,7 @@ DIALOG_SIM_COMMAND::DIALOG_SIM_COMMAND( wxWindow* aParent,
m_transStep->SetValidator( m_spiceValidator ); m_transStep->SetValidator( m_spiceValidator );
m_transFinal->SetValidator( m_spiceValidator ); m_transFinal->SetValidator( m_spiceValidator );
m_transInitial->SetValidator( m_spiceEmptyValidator ); m_transInitial->SetValidator( m_spiceEmptyValidator );
m_transMaxStep->SetValidator( m_spiceEmptyValidator );
refreshUIControls(); refreshUIControls();
@ -261,15 +262,38 @@ bool DIALOG_SIM_COMMAND::TransferDataFromWindow()
if( !m_pgTransient->Validate() ) if( !m_pgTransient->Validate() )
return false; return false;
wxString initial; const SPICE_VALUE timeStep( m_transStep->GetValue() );
const SPICE_VALUE finalTime( m_transFinal->GetValue() );
SPICE_VALUE startTime;
if( !empty( m_transInitial ) ) if( !empty( m_transInitial ) )
initial = SPICE_VALUE( m_transInitial->GetValue() ).ToSpiceString(); startTime = SPICE_VALUE( m_transInitial->GetValue() );
m_simCommand.Printf( ".tran %s %s %s", wxString optionals;
SPICE_VALUE( m_transStep->GetValue() ).ToSpiceString(),
SPICE_VALUE( m_transFinal->GetValue() ).ToSpiceString(), if( m_useInitialConditions->GetValue() )
initial ); optionals = "uic";
if( !empty( m_transMaxStep ) )
optionals = SPICE_VALUE( m_transMaxStep->GetValue() ).ToSpiceString() + " " + optionals;
else if( !optionals.IsEmpty() )
{
SPICE_VALUE maxStep = ( finalTime - startTime ) / 50.0;
if( maxStep > timeStep )
maxStep = timeStep;
optionals = maxStep.ToSpiceString() + " " + optionals;
}
if( !empty( m_transInitial ) )
optionals = startTime.ToSpiceString() + " " + optionals;
else if( !optionals.IsEmpty() )
optionals = "0 " + optionals;
m_simCommand.Printf( ".tran %s %s %s", timeStep.ToSpiceString(), finalTime.ToSpiceString(),
optionals );
} }
else if( page == m_pgCustom ) // Custom directives else if( page == m_pgCustom ) // Custom directives
{ {
@ -510,6 +534,18 @@ bool DIALOG_SIM_COMMAND::parseCommand( const wxString& aCommand )
if( !tkn.IsEmpty() ) if( !tkn.IsEmpty() )
m_transInitial->SetValue( SPICE_VALUE( tkn ).ToSpiceString() ); m_transInitial->SetValue( SPICE_VALUE( tkn ).ToSpiceString() );
// Max step is an optional field
tkn = tokenizer.GetNextToken();
if( !tkn.IsEmpty() )
m_transMaxStep->SetValue( SPICE_VALUE( tkn ).ToSpiceString() );
// uic is an optional field
tkn = tokenizer.GetNextToken();
if( tkn == "uic" )
m_useInitialConditions->SetValue( true );
} }
else if( tkn == ".op" ) else if( tkn == ".op" )
{ {

View File

@ -394,6 +394,36 @@ DIALOG_SIM_COMMAND_BASE::DIALOG_SIM_COMMAND_BASE( wxWindow* parent, wxWindowID i
fgSizer6->Add( m_staticText24, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); fgSizer6->Add( m_staticText24, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_maxTimeLabel = new wxStaticText( m_pgTransient, wxID_ANY, _("Max. time step:"), wxDefaultPosition, wxDefaultSize, 0 );
m_maxTimeLabel->Wrap( -1 );
fgSizer6->Add( m_maxTimeLabel, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
m_transMaxStep = new wxTextCtrl( m_pgTransient, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizer6->Add( m_transMaxStep, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT|wxEXPAND, 5 );
m_transMaxStepUnits = new wxStaticText( m_pgTransient, wxID_ANY, _("seconds"), wxDefaultPosition, wxDefaultSize, 0 );
m_transMaxStepUnits->Wrap( -1 );
fgSizer6->Add( m_transMaxStepUnits, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxRIGHT, 5 );
m_staticText25 = new wxStaticText( m_pgTransient, wxID_ANY, _("(optional; default min{tstep, (tstop-tstart)/50})"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText25->Wrap( -1 );
fgSizer6->Add( m_staticText25, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_useInitialConditionsLabel = new wxStaticText( m_pgTransient, wxID_ANY, _("Use initial conditions:"), wxDefaultPosition, wxDefaultSize, 0 );
m_useInitialConditionsLabel->Wrap( -1 );
fgSizer6->Add( m_useInitialConditionsLabel, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
m_useInitialConditions = new wxCheckBox( m_pgTransient, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgSizer6->Add( m_useInitialConditions, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT|wxEXPAND, 5 );
fgSizer6->Add( 0, 0, 0, wxEXPAND, 5 );
m_staticText26 = new wxStaticText( m_pgTransient, wxID_ANY, _("(optional; default off)"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText26->Wrap( -1 );
fgSizer6->Add( m_staticText26, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
bSizer81->Add( fgSizer6, 0, wxALL|wxEXPAND, 5 ); bSizer81->Add( fgSizer6, 0, wxALL|wxEXPAND, 5 );

View File

@ -112,6 +112,13 @@ class DIALOG_SIM_COMMAND_BASE : public DIALOG_SHIM
wxTextCtrl* m_transInitial; wxTextCtrl* m_transInitial;
wxStaticText* m_transInitialUnits; wxStaticText* m_transInitialUnits;
wxStaticText* m_staticText24; wxStaticText* m_staticText24;
wxStaticText* m_maxTimeLabel;
wxTextCtrl* m_transMaxStep;
wxStaticText* m_transMaxStepUnits;
wxStaticText* m_staticText25;
wxStaticText* m_useInitialConditionsLabel;
wxCheckBox* m_useInitialConditions;
wxStaticText* m_staticText26;
wxPanel* m_pgCustom; wxPanel* m_pgCustom;
wxStaticText* m_staticText18; wxStaticText* m_staticText18;
wxTextCtrl* m_customTxt; wxTextCtrl* m_customTxt;