From 4a8ce6aa04ce2477976605110fa54e081934e352 Mon Sep 17 00:00:00 2001 From: JoeyDelp Date: Thu, 7 Oct 2021 11:33:23 +0200 Subject: [PATCH 01/15] Implementation of a timestep reduction as preventative measure to account for user error. --- CMakeLists.txt | 2 +- README.md | 7 +- include/JoSIM/Matrix.hpp | 10 +- include/JoSIM/Simulation.hpp | 6 +- src/Matrix.cpp | 67 +++++++++++--- src/Simulation.cpp | 172 +++++++++++++---------------------- src/Transient.cpp | 3 +- src/Verbose.cpp | 6 ++ src/josim.cpp | 6 +- 9 files changed, 145 insertions(+), 134 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e3cf45c4..b1e2d739 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.14 FATAL_ERROR) -project(JoSIM VERSION 2.5.8) +project(JoSIM VERSION 2.6) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/README.md b/README.md index 43257df2..0b5c09df 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # JoSIM ### Superconductor Circuit Simulator -##### Testing: v2.5.8 - Status: [![Build Status](https://joeydelp.visualstudio.com/JoSIM/_apis/build/status/JoSIM-CI-Devel?branchName=testing)](https://joeydelp.visualstudio.com/JoSIM/_build/latest?definitionId=1&branchName=testing) +##### Testing: v2.6 - Status: [![Build Status](https://joeydelp.visualstudio.com/JoSIM/_apis/build/status/JoSIM-CI-Devel?branchName=testing)](https://joeydelp.visualstudio.com/JoSIM/_build/latest?definitionId=1&branchName=testing) -##### Stable: v2.5.8 - Status: [![Build Status](https://joeydelp.visualstudio.com/JoSIM/_apis/build/status/JoeyDelp.JoSIM?branchName=master)](https://joeydelp.visualstudio.com/JoSIM/_build/latest?definitionId=3&branchName=master) +##### Stable: v2.6 - Status: [![Build Status](https://joeydelp.visualstudio.com/JoSIM/_apis/build/status/JoeyDelp.JoSIM?branchName=master)](https://joeydelp.visualstudio.com/JoSIM/_build/latest?definitionId=3&branchName=master) --- @@ -35,6 +35,9 @@ Referencing: --- ## Changelog +### v2.6 +- WIP + ### v2.5.8 - Updated KLU to a 64-bit version capable of handling non-zero count larger than the maximum value of a 32-bit integer. - Included SuperLU 64-bit that can be activated using the *-x 1* switch (default 0 for KLU). diff --git a/include/JoSIM/Matrix.hpp b/include/JoSIM/Matrix.hpp index b40dacc8..9676d579 100644 --- a/include/JoSIM/Matrix.hpp +++ b/include/JoSIM/Matrix.hpp @@ -16,6 +16,9 @@ namespace JoSIM { class Matrix { + private: + std::vector nodeConfig, nodeConfig2; + bool needsTR_; public: AnalysisType analysisType = AnalysisType::Phase; std::vector sourcegen; @@ -26,18 +29,21 @@ namespace JoSIM { nodeconnections nc; std::unordered_set lm; int branchIndex; - std::vector nz, nz_orig; + std::vector nz; std::vector ci, rp; std::vector relevantTraces; std::vector relevantIndices; Matrix() {}; void create_matrix(Input& iObj); + void setup(Input& iObj); + void create_components(Input& iObj); + void handle_mutual_inductance(Input& iObj); + void reduce_step(Input& iObj); void create_csr(); void create_nz(); void create_ci(); void create_rp(); - void mod_timestep(const int factor); }; } // namespace JoSIM #endif diff --git a/include/JoSIM/Simulation.hpp b/include/JoSIM/Simulation.hpp index 645bd966..547d0770 100644 --- a/include/JoSIM/Simulation.hpp +++ b/include/JoSIM/Simulation.hpp @@ -30,7 +30,7 @@ namespace JoSIM { class Simulation { private: bool SLU = false; - std::vector x_, b_, xn2_, xn3_; + std::vector x_, b_; int simSize_; JoSIM::AnalysisType atyp_; bool minOut_; @@ -43,10 +43,10 @@ namespace JoSIM { klu_l_numeric* Numeric_; LUSolve lu; + void setup(Input& iObj, Matrix& mObj); void trans_sim(Matrix& mObj); void setup_b(Matrix& mObj, int i, double step, double factor = 1); - void reduce_step(Matrix& mObj, double factor, - int& stepCount, double currentStep); + void reduce_step(Input& iObj, Matrix& mObj); void handle_cs(Matrix& mObj, double& step, const int& i); void handle_resistors(Matrix& mObj); diff --git a/src/Matrix.cpp b/src/Matrix.cpp index 5ca912a4..5fa38861 100644 --- a/src/Matrix.cpp +++ b/src/Matrix.cpp @@ -16,16 +16,31 @@ using namespace JoSIM; void Matrix::create_matrix(Input& iObj) { + while (needsTR_) { + // Do matrix setup + setup(iObj); + // Create the components + create_components(iObj); + if (needsTR_) { + reduce_step(iObj); + } + } + // Handle mutual inductances + handle_mutual_inductance(iObj); + // Create the compressed storage row format required for simulation + create_csr(); +} + +void Matrix::setup(Input& iObj) { + needsTR_ = false; spread.get_spreads(iObj); - // Create a seperate thread that will be used for printing creation progress - std::thread printingThread; // Create a node counter variable int nodeCounter = 0; // Variables to store node configs since they are already identified here - std::vector nodeConfig( + nodeConfig.resize( iObj.netlist.expNetlist.size(), NodeConfig::GND); - // Optional, only available when 4 node components are detected - std::vector> nodeConfig2( + // Only available when 4 node components are detected + nodeConfig2.resize( iObj.netlist.expNetlist.size(), NodeConfig::GND); int cc = 0; for (auto& i : iObj.netlist.expNetlist) { @@ -40,13 +55,13 @@ void Matrix::create_matrix(Input& iObj) { Misc::vector_to_string(i.first)); } // Create a node map that maps the node names to numbers - if (i.first.at(1).find("GND") == + if (i.first.at(1).find("GND") == std::string::npos && i.first.at(1) != "0") { // Add the first node to the map if not ground if (nm.count(i.first.at(1)) == 0) nm[i.first.at(1)] = nodeCounter++; nodeConfig.at(cc) = NodeConfig::POSGND; } - if (i.first.at(2).find("GND") == + if (i.first.at(2).find("GND") == std::string::npos && i.first.at(2) != "0") { // Add the second node to the map if not ground if (nm.count(i.first.at(2)) == 0) nm[i.first.at(2)] = nodeCounter++; @@ -57,7 +72,7 @@ void Matrix::create_matrix(Input& iObj) { } } // If the device is as 4 node device - if (std::string("EFGHT").find(i.first.front().at(0)) != + if (std::string("EFGHT").find(i.first.front().at(0)) != std::string::npos) { // Ensure the device has at least 6 parts if (i.first.size() < 6) { @@ -90,6 +105,10 @@ void Matrix::create_matrix(Input& iObj) { nc.resize(nm.size()); // Set the index to the first branch current to the size of the node map branchIndex = nm.size(); +} + +void Matrix::create_components(Input& iObj) { + int cc = 0; ProgressBar bar; if (!iObj.argMin) { bar.create_thread(); @@ -99,8 +118,6 @@ void Matrix::create_matrix(Input& iObj) { bar.set_status_text("Creating Matrix"); bar.set_total((float)iObj.netlist.expNetlist.size()); } - // Counter for progress report - cc = 0; // Loop through all the components in the netlist for (auto it = iObj.netlist.expNetlist.begin(); it != iObj.netlist.expNetlist.end(); it++) { @@ -198,6 +215,11 @@ void Matrix::create_matrix(Input& iObj) { i, nodeConfig.at(cc), nodeConfig2.at(cc), nm, lm, nc, iObj.parameters, iObj.argAnal, iObj.transSim.tstep(), branchIndex)); + if (std::get(components.devices.back()).timestepDelay_ + <= 4) { + needsTR_ = true; + return; + } // Store the transmission line component list index for reference components.txIndices.emplace_back(components.devices.size() - 1); break; @@ -255,6 +277,10 @@ void Matrix::create_matrix(Input& iObj) { bar.complete(); std::cout << "\n"; } +} + +void Matrix::handle_mutual_inductance(Input& iObj) { + int cc = 0; ProgressBar bar2; if (!iObj.argMin && components.mutualinductances.size() != 0) { bar2.create_thread(); @@ -264,8 +290,6 @@ void Matrix::create_matrix(Input& iObj) { bar2.set_status_text("Adding Mutual Inductances"); bar2.set_total((float)iObj.netlist.expNetlist.size()); } - // Counter for progress report - cc = 0; // Loop through all identified mutual inductances for (const auto& s : components.mutualinductances) { // If not minimal printing @@ -329,14 +353,29 @@ void Matrix::create_matrix(Input& iObj) { } ++cc; } - // Create the compressed storage row format required for simulation - create_csr(); // Led the user know the matrix creation is complete if (!iObj.argMin && components.mutualinductances.size() != 0) { bar2.complete(); std::cout << "\n"; } +} +void Matrix::reduce_step(Input& iObj) { + iObj.transSim.tstep(iObj.transSim.tstep() / 5); + nodeConfig.clear(); + nodeConfig2.clear(); + Components newComponents; + components = newComponents; + nm.clear(); + nodeconnections newNC; + nc = newNC; + lm.clear(); + branchIndex = 0; + nz.clear(); + ci.clear(); + rp.clear(); + relevantIndices.clear(); + relevantTraces.clear(); } void Matrix::create_csr() { diff --git a/src/Simulation.cpp b/src/Simulation.cpp index 712f8b05..32335208 100644 --- a/src/Simulation.cpp +++ b/src/Simulation.cpp @@ -15,6 +15,45 @@ using namespace JoSIM; Simulation::Simulation(Input &iObj, Matrix &mObj) { + while (needsTR_) { + // Do generic simulation setup for given step size + setup(iObj, mObj); + // Do solver setup + if (SLU) { + // SLU setup + lu.create_matrix(mObj.rp.size() - 1, mObj.nz, mObj.ci, mObj.rp); + lu.factorize(); + } else { + // KLU setup + simOK_ = klu_l_defaults(&Common_); + assert(simOK_); + Symbolic_ = klu_l_analyze( + mObj.rp.size() - 1, &mObj.rp.front(), &mObj.ci.front(), &Common_); + Numeric_ = klu_l_factor( + &mObj.rp.front(), &mObj.ci.front(), &mObj.nz.front(), + Symbolic_, &Common_); + } + + // Run transient simulation + trans_sim(mObj); + // If step size is too large, reduce and try again + if (needsTR_) { + reduce_step(iObj, mObj); + } + + // Do solver cleanup + if (SLU) { + // SLU cleanup + lu.free(); + } else { + // KLU cleanup + klu_l_free_symbolic(&Symbolic_, &Common_); + klu_l_free_numeric(&Numeric_, &Common_); + } + } +} + +void Simulation::setup(Input& iObj, Matrix& mObj) { // Simulation setup SLU = iObj.SLU; simSize_ = iObj.transSim.simsize(); @@ -25,38 +64,16 @@ Simulation::Simulation(Input &iObj, Matrix &mObj) { stepSize_ = iObj.transSim.tstep(); prstep_ = iObj.transSim.prstep(); prstart_ = iObj.transSim.prstart(); + x_.clear(); x_.resize(mObj.branchIndex, 0.0); - if(!mObj.relevantTraces.empty()) { + if (!mObj.relevantTraces.empty()) { results.xVector.resize(mObj.branchIndex); - for (const auto &i : mObj.relevantIndices) { + for (const auto& i : mObj.relevantIndices) { results.xVector.at(i).emplace(); } } else { results.xVector.resize(mObj.branchIndex, std::vector(0)); } - if (SLU) { - // SLU setup - lu.create_matrix(mObj.rp.size() - 1, mObj.nz, mObj.ci, mObj.rp); - lu.factorize(); - // Run transient simulation - trans_sim(mObj); - // SLU cleanup - lu.free(); - } else { - // KLU setup - simOK_ = klu_l_defaults(&Common_); - assert(simOK_); - Symbolic_ = klu_l_analyze( - mObj.rp.size() - 1, &mObj.rp.front(), &mObj.ci.front(), &Common_); - Numeric_ = klu_l_factor( - &mObj.rp.front(), &mObj.ci.front(), &mObj.nz.front(), - Symbolic_, &Common_); - // Run transient simulation - trans_sim(mObj); - // KLU cleanup - klu_l_free_symbolic(&Symbolic_, &Common_); - klu_l_free_numeric(&Numeric_, &Common_); - } } void Simulation::trans_sim(Matrix &mObj) { @@ -82,6 +99,7 @@ void Simulation::trans_sim(Matrix &mObj) { } // Setup the b matrix setup_b(mObj, i, i * stepSize_); + if (needsTR_) return; // Assign x_prev the new b x_ = b_; // Solve Ax=b, storing the results in x_ @@ -109,6 +127,23 @@ void Simulation::trans_sim(Matrix &mObj) { } } +void Simulation::reduce_step(Input& iObj, Matrix& mObj) { + iObj.transSim.tstep(iObj.transSim.tstep() / 5); + bool tempMinOut = iObj.argMin; + if (!iObj.argMin) iObj.argMin = true; + Matrix newmObj; + mObj = newmObj; + // Create the matrix in csr format + mObj.create_matrix(iObj); + find_relevant_traces(iObj, mObj); + //// Dump expanded Netlist since it is no longer needed + //iObj.netlist.expNetlist.clear(); + //iObj.netlist.expNetlist.shrink_to_fit(); + if (!tempMinOut) iObj.argMin = tempMinOut; + results.xVector.clear(); + results.timeAxis.clear(); +} + void Simulation::setup_b( Matrix &mObj, int i, double step, double factor) { // Clear b matrix and reset @@ -150,83 +185,6 @@ void Simulation::setup_b( handle_tx(mObj, i, step); } -void Simulation::reduce_step( - Matrix &mObj, double factor, - int &stepCount, double currentStep) { - // Backup the current nonzeros - mObj.nz_orig = mObj.nz; - // Restore the previous x - x_ = xn3_; - // Remove the stored results for the larger timesteps - for(auto &i : results.xVector){ - if(i) { - i.value().pop_back(); - i.value().pop_back(); - } - } - results.timeAxis.pop_back(); - results.timeAxis.pop_back(); - // Determine how many steps to take using the reduced time step - int smallSteps = static_cast(20E-12 / (factor * stepSize_)); - // Update the non-zeros of each component to reflect the smaller timestep - for (auto &j : mObj.components.devices) { - BasicComponent &x = std::visit( - [](auto& x) -> BasicComponent &{ return x; }, - j); - x.update_timestep(factor); - x.step_back(); - } - // Recreate the non-zero matrix for the simulation - mObj.create_nz(); - // Do a new LU decomposition - klu_l_free_numeric(&Numeric_, &Common_); - Numeric_ = klu_l_factor( - &mObj.rp.front(), &mObj.ci.front(), &mObj.nz.front(), - Symbolic_, &Common_); - for(int i = 0; i < smallSteps; ++i) { - double smallStep = currentStep + i * (factor * stepSize_); - // Setup the b matrix - setup_b( - mObj, stepCount, smallStep, factor); - // Assign x_prev the new b - x_ = b_; - // Solve Ax=b, storing the results in x_ - simOK_ = klu_l_tsolve( - Symbolic_, Numeric_, mObj.rp.size() - 1, 1, &x_.front(), &Common_); - // If anything is a amiss, complain about it - if (!simOK_) Errors::simulation_errors(SimulationErrors::MATRIX_SINGULAR); - float test = smallStep / stepSize_; - // if(test == stepCount) { - // Store results (only requested, to prevent massive memory usage) - for(int j = 0; j < results.xVector.size(); ++j) { - if(smallStep >= prstart_) { - if(results.xVector.at(j)) { - results.xVector.at(j).value().emplace_back(x_.at(j)); - } - } - } - // Store the time step - if(smallStep >= prstart_) results.timeAxis.emplace_back(smallStep); - if(test == stepCount) { - stepCount++; - } - } - // Restore the timestep of all components to the correct values - for (auto &j : mObj.components.devices) { - BasicComponent &x = std::visit( - [](auto& x) -> BasicComponent &{ return x; }, - j); - x.update_timestep(1/factor); - } - // Recreate the non-zero matrix for the simulation - mObj.create_nz(); - // Do a new LU decomposition - klu_l_free_numeric(&Numeric_, &Common_); - Numeric_ = klu_l_factor( - &mObj.rp.front(), &mObj.ci.front(), &mObj.nz.front(), - Symbolic_, &Common_); -} - void Simulation::handle_cs(Matrix &mObj, double &step, const int &i) { for (const auto &j : mObj.components.currentsources) { @@ -355,11 +313,11 @@ void Simulation::handle_jj( ((2.0 * (stepSize_ * factor)) / 3.0)) * v0; // Ensure timestep is not too large if ((double)i/(double)simSize_ > 0.01) { - if (abs(temp.phi0_ - temp.pn1_) > (0.25 * 2 * Constants::PI)) { - // needsTR_ = true; - // return; - Errors::simulation_errors( - SimulationErrors::PHASEGUESS_TOO_LARGE, temp.netlistInfo.label_); + if (abs(temp.phi0_ - temp.pn1_) > (0.20 * 2 * Constants::PI)) { + needsTR_ = true; + return; + /*Errors::simulation_errors( + SimulationErrors::PHASEGUESS_TOO_LARGE, temp.netlistInfo.label_);*/ } } // (hbar / 2 * e) ( -(2 / h) φp1 + (1 / 2h) φp2 ) diff --git a/src/Transient.cpp b/src/Transient.cpp index 4d47dff3..3cb3de7f 100644 --- a/src/Transient.cpp +++ b/src/Transient.cpp @@ -69,8 +69,7 @@ void Transient::identify_simulation( tObj.tstop(1E-9); tObj.prstart(0); } - // While variable time step does not work yet - // If user provided time step is larger than 0.25ps + // If user provided time step is larger than 0.25ps junction will fail if (tObj.tstep() > 0.25E-12) { tObj.tstep(0.25E-12); } diff --git a/src/Verbose.cpp b/src/Verbose.cpp index 1e6a2402..c1a0e880 100644 --- a/src/Verbose.cpp +++ b/src/Verbose.cpp @@ -44,6 +44,12 @@ void Verbose::print_circuit_stats(const Input& iObj, const Matrix& mObj) { // Print the total component count std::cout << std::left << std::setw(26) << "Component count:" << mObj.components.devices.size() << "\n"; + // Print the total non-zero count + std::cout << std::left << std::setw(26) << "Non-zero count:" << + mObj.nz.size() << "\n"; + // Print matrix dimensions + std::cout << std::left << std::setw(26) << "MxN size:" << + mObj.rp.size() << "x" << mObj.rp.size() << "\n"; // Print the total jj count if (mObj.components.junctionIndices.size() != 0) { std::cout << std::left << std::setw(26) << "JJ count:" << diff --git a/src/josim.cpp b/src/josim.cpp index a3f89788..b04a7779 100644 --- a/src/josim.cpp +++ b/src/josim.cpp @@ -54,9 +54,9 @@ int main(int argc, mObj.create_matrix(iObj); // Do verbosity Verbose::handle_verbosity(iObj.argVerb, iObj, mObj); - // Dump expanded Netlist since it is no longer needed - iObj.netlist.expNetlist.clear(); - iObj.netlist.expNetlist.shrink_to_fit(); + //// Dump expanded Netlist since it is no longer needed + //iObj.netlist.expNetlist.clear(); + //iObj.netlist.expNetlist.shrink_to_fit(); // Find the relevant traces to store find_relevant_traces(iObj, mObj); // Create a simulation object From 7229f7cdb39c33329a0114b44a6efb8e01c2239d Mon Sep 17 00:00:00 2001 From: JoeyDelp Date: Thu, 14 Oct 2021 11:36:45 +0200 Subject: [PATCH 02/15] Implementation of subcircuit instance variation --- include/JoSIM/Errors.hpp | 1 + include/JoSIM/Input.hpp | 4 +- include/JoSIM/Netlist.hpp | 16 +++++-- src/Errors.cpp | 8 ++++ src/Netlist.cpp | 89 ++++++++++++++++++++++++++++----------- 5 files changed, 87 insertions(+), 31 deletions(-) diff --git a/include/JoSIM/Errors.hpp b/include/JoSIM/Errors.hpp index 63945029..0686b306 100644 --- a/include/JoSIM/Errors.hpp +++ b/include/JoSIM/Errors.hpp @@ -35,6 +35,7 @@ namespace JoSIM { MISSING_MAIN, UNKNOWN_SUBCKT, EMPTY_FILE, + IO_MISMATCH, UNKNOWN_CONTROL }; diff --git a/include/JoSIM/Input.hpp b/include/JoSIM/Input.hpp index 525b79b3..5259845f 100644 --- a/include/JoSIM/Input.hpp +++ b/include/JoSIM/Input.hpp @@ -32,8 +32,8 @@ namespace JoSIM { std::vector output_files; std::optional fileParentPath; - Input() {}; - Input(CliOptions& cli_options) { + Input() : netlist(*this) {}; + Input(CliOptions& cli_options) : netlist(*this) { argAnal = cli_options.analysis_type; argVerb = cli_options.verbose; argMin = cli_options.minimal; diff --git a/include/JoSIM/Netlist.hpp b/include/JoSIM/Netlist.hpp index 68bb96b5..64efda77 100644 --- a/include/JoSIM/Netlist.hpp +++ b/include/JoSIM/Netlist.hpp @@ -12,6 +12,8 @@ #include #include +typedef std::unordered_map s_map; + namespace JoSIM { struct pair_hash { template @@ -38,15 +40,20 @@ namespace JoSIM { }; }; + class Input; + class Netlist { + private: + Input& parent; void id_io_subc_label( - const tokens_t& lineTokens, tokens_t& io, + const tokens_t& lineTokens, tokens_t& io, s_map& params, std::string& subcktName, std::string& label, const std::unordered_map& subcircuits); bool rename_io_nodes( std::string& node, const tokens_t& subIO, const tokens_t& parentIO); - void expand_io( - Subcircuit& subc, const tokens_t& io, const std::string& label); + void expand_io(Subcircuit& subc, s_map& params, const tokens_t& io, + const std::string& label); + void insert_parameter(tokens_t& t, s_map& params); public: std::unordered_map< std::pair, tokens_t, pair_hash> models; @@ -58,7 +65,8 @@ namespace JoSIM { std::vector> expNetlist; int jjCount, compCount, subcktCounter, nestedSubcktCount, subcktTotal = 0; bool containsSubckt, argMin = false; - Netlist() : + Netlist(Input& p) : + parent(p), jjCount(0), compCount(0), subcktCounter(0), diff --git a/src/Errors.cpp b/src/Errors.cpp index 56e1b061..512cf5c8 100644 --- a/src/Errors.cpp +++ b/src/Errors.cpp @@ -157,6 +157,14 @@ void Errors::input_errors(InputErrors errorCode, string_o message) { formattedMessage += "Please check the input file and ensure that the file is not empty."; throw std::runtime_error(formattedMessage); + case InputErrors::IO_MISMATCH: + formattedMessage += + "The IO of line \"" + message.value_or("") + "\" does not " + "match the subcircuit IO.\n"; + formattedMessage += + "Please check the line and ensure correct IO and " + "that parameters do not contain spaces."; + throw std::runtime_error(formattedMessage); case InputErrors::UNKNOWN_CONTROL: formattedMessage += "The control \"" + message.value_or("") + "\" is not known.\n"; diff --git a/src/Netlist.cpp b/src/Netlist.cpp index c8626c73..66241b5e 100644 --- a/src/Netlist.cpp +++ b/src/Netlist.cpp @@ -13,28 +13,30 @@ using namespace JoSIM; void Netlist::id_io_subc_label( - const tokens_t& lineTokens, tokens_t& io, + const tokens_t& lineTokens, tokens_t& io, s_map& params, std::string& subcktName, std::string& label, const std::unordered_map& subcircuits) { // Id the label label = lineTokens.front(); + // Found flag + bool found = false; // Check the convention // At this point in the program all subcircuits should have been identified // Thus we can determine the convention from code - // If the token right after the label exists in the subcircuits map - if (subcircuits.count(lineTokens.at(1)) != 0) { - // This is the subcircuit name - subcktName = lineTokens.at(1); - // Assign the IO - io.assign(lineTokens.begin() + 2, lineTokens.end()); - // Else if the last token exists in the subcircuit map - } else if (subcircuits.count(lineTokens.back()) != 0) { - // Then this is the subcircuit name - subcktName = lineTokens.back(); - // Assign the IO - io.assign(lineTokens.begin() + 1, lineTokens.end() - 1); - // Else if the neither then this subcircuit surely does not exist - } else { + for (int i = 1; i < lineTokens.size(); ++i) { + if (subcircuits.count(lineTokens.at(i)) != 0) { + found = true; + subcktName = lineTokens.at(i); + } else if (lineTokens.at(i).find('=') != std::string::npos) { + std::string param, value; + param = lineTokens.at(i).substr(0, lineTokens.at(i).find('=')); + value = lineTokens.at(i).substr(lineTokens.at(i).find('=') + 1); + params[param] = value; + } else { + io.emplace_back(lineTokens.at(i)); + } + } + if (!found) { Errors::input_errors( InputErrors::UNKNOWN_SUBCKT, Misc::vector_to_string(lineTokens)); } @@ -59,12 +61,20 @@ bool Netlist::rename_io_nodes( return false; } -void Netlist::expand_io( - Subcircuit& subc, const tokens_t& io, const std::string& label) { +void Netlist::expand_io(Subcircuit& subc, s_map& params, const tokens_t& io, + const std::string& label) { + // Sanity check + if (io.size() != subc.io.size()) { + Errors::input_errors(InputErrors::IO_MISMATCH, label); + } // Loop through the identified subcircuit for (int k = 0; k < subc.lines.size(); ++k) { // Set shorthand for long variable name tokens_t& tokens = subc.lines.at(k).first; + // Check for value parameterization + if (params.count(tokens.front()) != 0) { + insert_parameter(tokens, params); + } // Append the label of the parent to the subcircuit label tokens.at(0) = tokens.at(0) + "|" + label; // Determine amount of nodes to process @@ -87,9 +97,33 @@ void Netlist::expand_io( } } +void Netlist::insert_parameter(tokens_t& t, s_map& params) { + std::string twonode = "RCLK"; + std::string fournode = "EFHGT"; + if (twonode.find(t.front().front()) != std::string::npos) { + t.at(3) = params.at(t.front()); + } else if (fournode.find(t.front().front()) != std::string::npos) { + if (t.front().front() == 'T') { + for (auto& i : t) { + if (i.find("TD=") != std::string::npos) { + i = "TD=" + params.at(t.front()); + } + } + } else { + t.at(5) = params.at(t.front()); + } + } else if (t.front().front() == 'B') { + for (auto& i : t) { + if (i.find("AREA=") != std::string::npos) { + i = "AREA=" + params.at(t.front()); + } else if (i.find("IC=") != std::string::npos) { + i = "IC=" + params.at(t.front()); + } + } + } +} + void Netlist::expand_subcircuits() { - // Variable to store io - tokens_t io; // std::vector> moddedLines; std::string subcktName, label; // Loop through subcircuits, line by line @@ -133,14 +167,17 @@ void Netlist::expand_subcircuits() { tokens_t& subcCurrentLine = subcircuit.lines.at(j).first; // If the line denotes a subcircuit if (subcCurrentLine.front().at(0) == 'X') { + // Variable to store io and parameters + tokens_t io; + s_map params; id_io_subc_label( - subcCurrentLine, io, subcktName, label, subcircuits); + subcCurrentLine, io, params, subcktName, label, subcircuits); // Create a copy of the subircuit for this instance Subcircuit subc = subcircuits.at(subcktName); // If not nested if (!subc.containsSubckt) { // Expand the IO nodes of the subcircuit for this instance - expand_io(subc, io, label); + expand_io(subc, params, io, label); // Erase the current line (tokens) subcircuit.lines.erase(subcircuit.lines.begin() + j); // Insert the subcircuit token lines at the erased line position @@ -168,8 +205,6 @@ void Netlist::expand_subcircuits() { } void Netlist::expand_maindesign() { - // Variable to store io - tokens_t io; // std::vector> moddedLines; ProgressBar bar; if (!argMin) { @@ -190,11 +225,15 @@ void Netlist::expand_maindesign() { } // If the line denotes a subcircuit if (maindesign.at(i).front().at(0) == 'X') { - id_io_subc_label(maindesign.at(i), io, subcktName, label, subcircuits); + // Variable to store io and parameters + tokens_t io; + s_map params; + id_io_subc_label(maindesign.at(i), io, params, + subcktName, label, subcircuits); // Copy of subcircuit for this instance Subcircuit subc = subcircuits.at(subcktName); // Expand the appropriate IO nodes of the subcircuit for this instance - expand_io(subc, io, label); + expand_io(subc, params, io, label); // Add the expanded subcircuit lines to the expanded netlist expNetlist.insert(expNetlist.end(), subc.lines.begin(), subc.lines.end()); From 3f5b528aa49fe60845a8d810ef035c5dc061225c Mon Sep 17 00:00:00 2001 From: JoeyDelp Date: Tue, 19 Oct 2021 09:33:34 +0200 Subject: [PATCH 03/15] Added the Phi0 paremeter to the junction model for pi junctions. --- include/JoSIM/Model.hpp | 10 +++++++++- src/Model.cpp | 2 ++ src/Simulation.cpp | 15 ++++++++++----- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/include/JoSIM/Model.hpp b/include/JoSIM/Model.hpp index d07565b6..6e2378f7 100644 --- a/include/JoSIM/Model.hpp +++ b/include/JoSIM/Model.hpp @@ -23,6 +23,7 @@ namespace JoSIM { double transparency_; double criticalToNormalRatio_; double phaseOffset_; + double phiZero_; public: Model() : @@ -37,7 +38,8 @@ namespace JoSIM { deltaV_(0.1E-3), transparency_(0), criticalToNormalRatio_(Constants::PI / 4), - phaseOffset_(0) {}; + phaseOffset_(0), + phiZero_(0) {}; std::string get_modelName() const { return modelName_; @@ -78,6 +80,9 @@ namespace JoSIM { double get_phaseOffset() const { return phaseOffset_; } + double get_phiZero() const { + return phiZero_; + } void set_modelName(const std::string& n) { modelName_ = n; @@ -118,6 +123,9 @@ namespace JoSIM { void set_phaseOffset(const double& o) { phaseOffset_ = o; } + void set_phiZero(const double& o) { + phiZero_ = o; + } static void parse_model( const std::pair& s, diff --git a/src/Model.cpp b/src/Model.cpp index 5869862d..125c680e 100644 --- a/src/Model.cpp +++ b/src/Model.cpp @@ -67,6 +67,8 @@ void Model::parse_model( temp.set_criticalToNormalRatio(value); } else if (tokens.at(i) == "PHI") { temp.set_phaseOffset(value); + } else if (tokens.at(i) == "PHI0") { + temp.set_phiZero(value); } } diff --git a/src/Simulation.cpp b/src/Simulation.cpp index 32335208..c4bc09e1 100644 --- a/src/Simulation.cpp +++ b/src/Simulation.cpp @@ -344,15 +344,20 @@ void Simulation::handle_jj( needsLU_ = true; } } - // -(hR / h + 2RC) * (Ic sin φ0 - 2C / h Vp1 + C/2h Vp2 + It) + // -(hR / h + 2RC) * (Ic sin (φ0 - 2C / h Vp1 + C/2h Vp2 + It) b_.at(temp.indexInfo.currentIndex_.value()) = (temp.matrixInfo.nonZeros_.back()) * ((((Constants::PI * temp.del_) / - (2 * Constants::EV * temp.rncalc_)) * (sin(temp.phi0_) / - sqrt(1 - model.value().get_transparency() * (sin(temp.phi0_ / 2) * - sin(temp.phi0_ / 2)))) * tanh((temp.del_) / + (2 * Constants::EV * temp.rncalc_)) * (sin((temp.phi0_ + + temp.model_.value().get_phiZero())) / + sqrt(1 - model.value().get_transparency() * (sin((temp.phi0_ + + temp.model_.value().get_phiZero()) / 2) * + sin((temp.phi0_ + + temp.model_.value().get_phiZero()) / 2)))) * tanh((temp.del_) / (2 * Constants::BOLTZMANN * model.value().get_temperature()) * sqrt(1 - model.value().get_transparency() * - (sin(temp.phi0_ / 2) * sin(temp.phi0_ / 2))))) - + (sin((temp.phi0_ + + temp.model_.value().get_phiZero()) / 2) * sin((temp.phi0_ + + temp.model_.value().get_phiZero()) / 2))))) - (((2 * model.value().get_capacitance()) / (stepSize_ * factor)) * temp.vn1_) + ((model.value().get_capacitance() / From 3e63ecc0d227a96c406c1a71cba9db2cc4276b0b Mon Sep 17 00:00:00 2001 From: JoeyDelp Date: Mon, 22 Nov 2021 09:52:53 +0200 Subject: [PATCH 04/15] Phi junction update --- include/JoSIM/JJ.hpp | 8 +- include/JoSIM/Misc.hpp | 4 +- include/JoSIM/Model.hpp | 160 +++++++++++++------------- include/JoSIM/Simulation.hpp | 1 + include/JoSIM/Transient.hpp | 12 +- scripts/{josim-plot => josim-plot.py} | 110 +++++++++++++++++- src/Errors.cpp | 6 +- src/Function.cpp | 2 + src/IV.cpp | 5 + src/JJ.cpp | 108 +++++++---------- src/Model.cpp | 35 +++--- src/Parameters.cpp | 4 + src/Simulation.cpp | 81 +++++++++---- src/Transient.cpp | 11 +- 14 files changed, 343 insertions(+), 204 deletions(-) rename scripts/{josim-plot => josim-plot.py} (68%) diff --git a/include/JoSIM/JJ.hpp b/include/JoSIM/JJ.hpp index c5325ac8..c34e0bb4 100644 --- a/include/JoSIM/JJ.hpp +++ b/include/JoSIM/JJ.hpp @@ -55,14 +55,14 @@ namespace JoSIM { int variableIndex_ = 0; double area_ = 1.0; std::optional Ic_; - std::optional model_; + Model model_; double phaseConst_ = 0.0; double lowerB_ = 0.0, upperB_ = 0.0, gLarge_ = 0.0; - double del0_ = 0.0, del_ = 0.0, rncalc_ = 0.0; + double del0_ = 0.0, del_ = 0.0; double pn1_ = 0.0, pn2_ = pn1_, pn3_ = pn2_, pn4_ = pn3_, phi0_ = 0.0; double vn1_ = 0.0, vn2_ = vn1_, vn3_ = vn2_, vn4_ = vn3_, vn5_ = vn4_, vn6_ = vn5_; - double transitionCurrent_ = 0.0; + double it_ = 0.0; JoSIM::AnalysisType at_; JJ( @@ -82,8 +82,6 @@ namespace JoSIM { bool update_value(const double& v); - void update_timestep(const double& factor) override; - void step_back() override { pn2_ = pn4_; vn3_ = vn6_; diff --git a/include/JoSIM/Misc.hpp b/include/JoSIM/Misc.hpp index b37ef7cb..288ca124 100644 --- a/include/JoSIM/Misc.hpp +++ b/include/JoSIM/Misc.hpp @@ -78,7 +78,9 @@ namespace JoSIM { template std::string precise_to_string(const T a_value) { std::ostringstream out; - out << std::uppercase << std::fixed << std::scientific << a_value; + out << std::uppercase << + std::setprecision(std::numeric_limits::digits10 + 1) << + a_value; return out.str(); } diff --git a/include/JoSIM/Model.hpp b/include/JoSIM/Model.hpp index 6e2378f7..5a2fb90d 100644 --- a/include/JoSIM/Model.hpp +++ b/include/JoSIM/Model.hpp @@ -11,122 +11,120 @@ namespace JoSIM { class Model { private: std::string modelName_; - double voltageGap_; - double criticalCurrent_; - int resistanceType_; - double normalResistance_; - double subgapResistance_; - double capacitance_; - double temperature_; - double criticalTemperature_; + double vg_; + double ic_; + int rtype_; + double rn_; + double r0_; + double c_; + double t_; + double tc_; double deltaV_; - double transparency_; - double criticalToNormalRatio_; - double phaseOffset_; - double phiZero_; + double d_; + double icFct_; + double phiOff_; + bool tDep_; public: Model() : - voltageGap_(2.8E-3), - criticalCurrent_(1E-3), - resistanceType_(1), - normalResistance_(5), - subgapResistance_(30), - capacitance_(2.5E-12), - temperature_(4.2), - criticalTemperature_(9.1), + vg_(2.8E-3), + ic_(1E-3), + rtype_(1), + rn_(5), + r0_(30), + c_(2.5E-12), + t_(4.2), + tc_(9.1), deltaV_(0.1E-3), - transparency_(0), - criticalToNormalRatio_(Constants::PI / 4), - phaseOffset_(0), - phiZero_(0) {}; + d_(0), + icFct_(Constants::PI / 4), + phiOff_(0), + tDep_(false) {}; - std::string get_modelName() const { + std::string modelName() const { return modelName_; } - double get_voltageGap() const { - return voltageGap_; + void modelName(const std::string& n) { + modelName_ = n; } - double get_criticalCurrent() const { - return criticalCurrent_; + double vg() const { + return vg_; } - int get_resistanceType() const { - return resistanceType_; + void vg(const double& v) { + vg_ = v; } - double get_normalResistance() const { - return normalResistance_; + double ic() const { + return ic_; } - double get_subgapResistance() const { - return subgapResistance_; + void ic(const double& i) { + ic_ = i; } - double get_capacitance() const { - return capacitance_; + int rtype() const { + return rtype_; } - double get_temperature() const { - return temperature_; + void rtype(const int& r) { + rtype_ = r; } - double get_criticalTemperature() const { - return criticalTemperature_; + double rn() const { + return rn_; } - double get_deltaV() const { - return deltaV_; + void rn(const double& r) { + rn_ = r; } - double get_transparency() const { - return transparency_; + double r0() const { + return r0_; } - double get_criticalToNormalRatio() const { - return criticalToNormalRatio_; + void r0(const double& r) { + r0_ = r; } - double get_phaseOffset() const { - return phaseOffset_; + double c() const { + return c_; } - double get_phiZero() const { - return phiZero_; + void c(const double& c) { + c_ = c; } - - void set_modelName(const std::string& n) { - modelName_ = n; + double t() const { + return t_; } - void set_voltageGap(const double& v) { - voltageGap_ = v; + void t(const double& t) { + t_ = t; } - void set_criticalCurrent(const double& i) { - criticalCurrent_ = i; + double tc() const { + return tc_; } - void set_resistanceType(const int& r) { - resistanceType_ = r; + void tc(const double& t) { + tc_ = t; } - void set_normalResistance(const double& r) { - normalResistance_ = r; + double deltaV() const { + return deltaV_; } - void set_subgapResistance(const double& r) { - subgapResistance_ = r; + void deltaV(const double& d) { + deltaV_ = d; } - void set_capacitance(const double& c) { - capacitance_ = c; + double d() const { + return d_; } - void set_temperature(const double& t) { - temperature_ = t; + void d(const double& t) { + d_ = t; } - void set_criticalTemperature(const double& t) { - criticalTemperature_ = t; + double icFct() const { + return icFct_; } - void set_deltaV(const double& d) { - deltaV_ = d; + void icFct(const double& r) { + icFct_ = r; } - void set_transparency(const double& t) { - transparency_ = t; + double phiOff() const { + return phiOff_; } - void set_criticalToNormalRatio(const double& r) { - criticalToNormalRatio_ = r; + void phiOff(const double& o) { + phiOff_ = o; } - void set_phaseOffset(const double& o) { - phaseOffset_ = o; + bool tDep() { + return tDep_; } - void set_phiZero(const double& o) { - phiZero_ = o; + void tDep(bool b) { + tDep_ = b; } - static void parse_model( const std::pair& s, vector_pair_t& models, const param_map& p); diff --git a/include/JoSIM/Simulation.hpp b/include/JoSIM/Simulation.hpp index 547d0770..dd251d88 100644 --- a/include/JoSIM/Simulation.hpp +++ b/include/JoSIM/Simulation.hpp @@ -36,6 +36,7 @@ namespace JoSIM { bool minOut_; bool needsLU_; bool needsTR_; + bool startup_; double stepSize_, prstep_, prstart_; int simOK_; klu_l_symbolic* Symbolic_; diff --git a/include/JoSIM/Transient.hpp b/include/JoSIM/Transient.hpp index dc43dfbf..bd507cf6 100644 --- a/include/JoSIM/Transient.hpp +++ b/include/JoSIM/Transient.hpp @@ -15,12 +15,14 @@ namespace JoSIM { double tstop_; double prstart_; double prstep_; + bool startup_; public: Transient() : tstep_(0.25E-12), tstop_(0.0), prstart_(0.0), - prstep_(1E-12) {}; + prstep_(1E-12), + startup_(true) {}; double tstep() const { return tstep_; @@ -37,6 +39,9 @@ namespace JoSIM { int simsize() const { return static_cast(tstop_ / tstep_); } + bool startup() const { + return startup_; + } void tstep(double value) { tstep_ = value; @@ -50,9 +55,12 @@ namespace JoSIM { void prstep(double value) { prstep_ = value; } + void startup(bool value) { + startup_ = value; + } static void identify_simulation( - const std::vector& controls, Transient& tObj); + std::vector& controls, Transient& tObj); }; } diff --git a/scripts/josim-plot b/scripts/josim-plot.py similarity index 68% rename from scripts/josim-plot rename to scripts/josim-plot.py index 4b3b0547..bf5c2aa2 100644 --- a/scripts/josim-plot +++ b/scripts/josim-plot.py @@ -18,7 +18,7 @@ def main(): parser.add_argument("input", help="the CSV input file") parser.add_argument("-o", "--output", help="the output file name with supported extensions: png, jpeg, webp, svg, eps, pdf") parser.add_argument("-x", "--html", help="save the output as an html file for later viewing") - parser.add_argument("-t", "--type", help="type of plot: grid, stacked, combined, square. Default: grid", default="grid") + parser.add_argument("-t", "--type", help="type of plot: grid, stacked, combined, square, sep_comb. Default: grid", default="grid") parser.add_argument("-s", "--subset", nargs='+', help="subset of traces to plot. specify list of column names (as shown in csv file header), ie. \"V(1)\" \"V(2)\". Default: None") parser.add_argument("-c", "--color", help="set the output plot color scheme to one of the following: light, dark, presentation. Default: dark", default='dark') parser.add_argument("-w", "--title", help="set plot title to the provided string") @@ -27,17 +27,20 @@ def main(): # Read arguments from the command line args = parser.parse_args() + # List of possible output formats outformats = [".png", ".jpeg", ".webp", ".svg", ".eps", ".pdf"] - if (os.path.splitext(args.input)[1] == ".csv"): + # How to handle column seperation. CSV uses comma, DAT uses space. + if (os.path.splitext(args.input)[1].lower() == ".csv"): df = pd.read_csv(args.input, sep=',') - elif (os.path.splitext(args.input)[1] == ".dat"): + elif (os.path.splitext(args.input)[1].lower() == ".dat"): df = pd.read_csv(args.input, delim_whitespace=True) else: print("Invalid input file specified: " + args.input) print("Please provide either .csv (comma seperated) or .dat (space seperated) file") sys.exit() + # Determine the plot layout. if(args.type == "grid"): fig = grid_layout(df, args.subset) elif(args.type == "stacked"): @@ -46,11 +49,14 @@ def main(): fig = combined_layout(df, args.subset) elif(args.type == "square"): fig = square_layout(df, args.subset) + elif(args.type == "sep_comb"): + fig = seperate_combined_layout(df, args.subset) else: print("Invalid plot type specified: " + args.type) print("Please provide either gird, stacked or combined as type") sys.exit() - + + # Determine the theme to plot with. if(args.color == 'light'): template = 'plotly_white' elif(args.color == 'dark'): @@ -62,21 +68,37 @@ def main(): print("Please provide either light, dark or presentation as color theme") sys.exit() + # Set the title of the plot if(args.title == None): title=os.path.splitext(os.path.basename(args.input))[0] else: title=args.title + # Update the layout based on the settings fig.update_layout( title=title, title_font_size=30, template=template ) + + # Set the mode bar buttons config = dict({ 'scrollZoom': True, - 'displaylogo': False + 'displaylogo': False, + 'toImageButtonOptions': { + 'format': 'svg', + 'filename': title, + 'height': None, + 'width': None + }, + 'modeBarButtonsToAdd': [ + 'toggleSpikelines', + 'hovercompare', + 'v1hovermode' + ] }) + # Determine wether to show the plot or just dump to file if(args.output == None and args.html == None): fig.show(config=config) elif(args.html != None and args.output == None): @@ -191,6 +213,84 @@ def stacked_layout(df, subset): fig['layout']['yaxis' + str(i+1)]['title']=y_axis_title(plots[i]) return fig +# Seperate and Combine like plots +def seperate_combined_layout(df, subset): + plots = df.columns[1:].tolist() if subset == None else subset + V = [] + P = [] + I = [] + U = [] + for i in range(0, len(plots)): + if plots[i][0] == 'V': + V.append(i) + elif plots[i][0] == 'I': + I.append(i) + elif plots[i][0] == 'P': + P.append(i) + else: + U.append(i) + fig_count = 0 + if len(V) != 0: + fig_count = fig_count + 1; + if len(P) != 0: + fig_count = fig_count + 1; + if len(I) != 0: + fig_count = fig_count + 1; + if len(U) != 0: + fig_count = fig_count + 1; + fig = make_subplots( + rows=fig_count, + cols=1, + vertical_spacing=0.2/math.ceil(fig_count/2), + x_title= 'Time (seconds)') + # Add the traces + fig_count = 0 + if len(U) != 0: + fig_count = fig_count + 1; + for i in U: + fig.add_trace(go.Scatter( + x=df.iloc[:,0], y=df.loc[:,plots[i]], + mode='lines', + name=plots[i]), + row=fig_count, + col=1 + ) + fig['layout']['yaxis' + str(fig_count)]['title']=y_axis_title(plots[i]) + if len(V) != 0: + fig_count = fig_count + 1; + for i in V: + fig.add_trace(go.Scatter( + x=df.iloc[:,0], y=df.loc[:,plots[i]], + mode='lines', + name=plots[i]), + row=fig_count, + col=1 + ) + fig['layout']['yaxis' + str(fig_count)]['title']=y_axis_title(plots[i]) + if len(P) != 0: + fig_count = fig_count + 1; + for i in P: + fig.add_trace(go.Scatter( + x=df.iloc[:,0], y=df.loc[:,plots[i]], + mode='lines', + name=plots[i]), + row=fig_count, + col=1 + ) + fig['layout']['yaxis' + str(fig_count)]['title']=y_axis_title(plots[i]) + if len(I) != 0: + fig_count = fig_count + 1; + for i in I: + fig.add_trace(go.Scatter( + x=df.iloc[:,0], y=df.loc[:,plots[i]], + mode='lines', + name=plots[i]), + row=fig_count, + col=1 + ) + fig['layout']['yaxis' + str(fig_count)]['title']=y_axis_title(plots[i]) + return fig + # Combine all the plots def combined_layout(df, subset): plots = df.columns[1:].tolist() if subset == None else subset diff --git a/src/Errors.cpp b/src/Errors.cpp index 512cf5c8..e8444544 100644 --- a/src/Errors.cpp +++ b/src/Errors.cpp @@ -488,8 +488,10 @@ void Errors::control_errors(ControlErrors errorCode, string_o message) { formattedMessage += "Unknown model parameter specified.\n"; formattedMessage += "Model line: " + message.value_or("") + "\n"; formattedMessage += - "Please refer to the model definition in the documentation"; - throw std::runtime_error(formattedMessage); + "Continuing with default model parameters.\n" + "Please consult the syntax guide for more information."; + warning_message(formattedMessage); + break; case ModelErrors::UNKNOWN_MODEL_TYPE: formattedMessage += "Unknown model type specified.\n"; formattedMessage += "Model line: " + message.value_or(""); diff --git a/src/Function.cpp b/src/Function.cpp index 4469307d..d8f9567c 100644 --- a/src/Function.cpp +++ b/src/Function.cpp @@ -65,6 +65,8 @@ void Function::parse_function( Misc::tokenize(str).back(), iObj.parameters, subckt))) { fType_ = FunctionType::DC; parse_dc(t, iObj, subckt); + } else { + // Assume DC } } diff --git a/src/IV.cpp b/src/IV.cpp index 12af4889..21fe9a6b 100644 --- a/src/IV.cpp +++ b/src/IV.cpp @@ -41,6 +41,7 @@ void IV::setup_iv(const tokens_t& i, const Input& iObj) { double maxC = parse_param(i.at(2), iObj.parameters); // Create an input object for this simulation Input ivInp = iObj; + ivInp.controls.clear(); tokens_t jj = { "B01", "1", "0", model, "AREA=1" }; tokens_t ib = { "IB01", "0", "1", "PWL(0", "0", "10P", "0", "50P", "2.5U)" }; ivInp.netlist.expNetlist = { @@ -74,24 +75,28 @@ std::vector> IV::generate_iv(double maxC, currentCurr += currentIncrement; ivMat.sourcegen.back().ampValues({ 0, 0, currentCurr }); iv_data.emplace_back(do_simulate(ivInp, ivMat)); + ivInp.transSim.tstep(0.05E-12); } while (currentCurr >= 0) { // Create a matrix object using the input object currentCurr -= currentIncrement; ivMat.sourcegen.back().ampValues({ 0, maxC, currentCurr }); iv_data.emplace_back(do_simulate(ivInp, ivMat)); + ivInp.transSim.tstep(0.05E-12); } while (currentCurr >= -maxC) { // Create a matrix object using the input object currentCurr -= currentIncrement; ivMat.sourcegen.back().ampValues({ 0, 0, currentCurr }); iv_data.emplace_back(do_simulate(ivInp, ivMat)); + ivInp.transSim.tstep(0.05E-12); } while (currentCurr <= 0) { // Create a matrix object using the input object currentCurr += currentIncrement; ivMat.sourcegen.back().ampValues({ 0, -maxC, currentCurr }); iv_data.emplace_back(do_simulate(ivInp, ivMat)); + ivInp.transSim.tstep(0.05E-12); } return iv_data; } diff --git a/src/JJ.cpp b/src/JJ.cpp index af8882b2..7c5e1426 100644 --- a/src/JJ.cpp +++ b/src/JJ.cpp @@ -80,12 +80,6 @@ JJ::JJ( } // Set the model for this JJ instance set_model(t, iObj.netlist.models_new, s.second); - // Get and set the phase offset from the model - pn1_ = model_.value().get_phaseOffset(); - // Set the transitional conductance value - gLarge_ = model_.value().get_criticalCurrent() / - (model_.value().get_criticalToNormalRatio() * - model_.value().get_deltaV()); // Set the phase constant if (at_ == AnalysisType::Voltage) { // If voltage mode set this to (3 * hbar) / (4 * h * eV) @@ -94,19 +88,6 @@ JJ::JJ( // If phase mode set this to (4 * h * eV) / (3 * hbar) phaseConst_ = (4 * h_ * Constants::EV) / (3 * Constants::HBAR); } - // Set the Del0 parameter - del0_ = 1.76 * Constants::BOLTZMANN * - model_.value().get_criticalTemperature(); - // Set the del parameter - del_ = del0_ * sqrt(cos((Constants::PI / 2) * - (model_.value().get_temperature() / - model_.value().get_criticalTemperature()) * - (model_.value().get_temperature() / - model_.value().get_criticalTemperature()))); - // Set the calculated Rn value - rncalc_ = ((Constants::PI * del_) / - (2 * Constants::EV * model_.value().get_criticalCurrent())) * - tanh(del_ / (2 * Constants::BOLTZMANN * model_.value().get_temperature())); // Set the node configuration type indexInfo.nodeConfig_ = ncon; // Set variable index and increment it @@ -121,20 +102,17 @@ JJ::JJ( double JJ::subgap_impedance() { // Set subgap impedance (1/R0) + (3C/2h) - return ((1 / model_.value().get_subgapResistance()) + - ((3.0 * model_.value().get_capacitance()) / (2.0 * h_))); + return ((1 / model_.r0()) + ((3.0 * model_.c()) / (2.0 * h_))); } double JJ::transient_impedance() { // Set transitional impedance (GL) + (3C/2h) - return (gLarge_ + - ((3.0 * model_.value().get_capacitance()) / (2.0 * h_))); + return (gLarge_ + ((3.0 * model_.c()) / (2.0 * h_))); } double JJ::normal_impedance() { // Set normal impedance (1/RN) + (3C/2h) - return ((1 / model_.value().get_normalResistance()) + - ((3.0 * model_.value().get_capacitance()) / (2.0 * h_))); + return ((1 / model_.rn()) + ((3.0 * model_.c()) / (2.0 * h_))); } void JJ::set_matrix_info() { @@ -185,61 +163,74 @@ void JJ::set_matrix_info() { void JJ::set_model( const tokens_t& t, const vector_pair_t& models, const string_o& subc) { + bool found = false; // Loop through all models for (auto& i : models) { // If the model name matches that of an identified model - if (i.first.get_modelName() == t.back()) { + if (i.first.modelName() == t.back()) { // If both models belong to a subcircuit and the subcircuit names match if ((i.second && subc) && (subc.value() == i.second.value())) { // Set the model to the exact identified model model_ = i.first; + found = true; break; - // JJ might be in a subcircuit but model in global scope + // JJ might be in a subcircuit but model in global scope6 } else if (!i.second) { // Set the model to the globally identified model model_ = i.first; + found = true; break; } } } // If no model was found - if (!model_) { + if (!found) { // Complain about it Errors::invalid_component_errors( ComponentErrors::MODEL_NOT_DEFINED, Misc::vector_to_string(t)); } + // Set the model critical current for this JJ instance + model_.ic(model_.ic() * area_); + if (model_.tDep()) { + // Set the Del0 parameter + del0_ = 1.76 * Constants::BOLTZMANN * model_.tc(); + // Set the del parameter + del_ = del0_ * sqrt(cos((Constants::PI / 2) * + (model_.t() / model_.tc()) * (model_.t() / model_.tc()))); + // Set the temperature dependent normal resistance + model_.rn(((Constants::PI * del_) / (2 * Constants::EV * model_.ic())) * + tanh(del_ / (2 * Constants::BOLTZMANN * model_.t()))); + } else { + // Set the model normal resistance for this JJ instance + model_.rn(model_.rn() / area_); + } // Change the area if ic was defined if (Ic_) { - area_ = Ic_.value() / model_.value().get_criticalCurrent(); + area_ = Ic_.value() / model_.ic(); } // Set the model capacitance for this JJ instance - model_.value().set_capacitance( - model_.value().get_capacitance() * area_); - // Set the model normal resistance for this JJ instance - model_.value().set_normalResistance( - model_.value().get_normalResistance() / area_); + model_.c(model_.c() * area_); // Set the model subgap resistance for this JJ instance - model_.value().set_subgapResistance( - model_.value().get_subgapResistance() / area_); - // Set the model critical current for this JJ instance - model_.value().set_criticalCurrent( - model_.value().get_criticalCurrent() * area_); + model_.r0(model_.r0() / area_); // Set the lower boundary for the transition region - lowerB_ = - model_.value().get_voltageGap() - 0.5 * model_.value().get_deltaV(); + lowerB_ = model_.vg() - 0.5 * model_.deltaV(); // Set the upper boundary for the transition region - upperB_ = - model_.value().get_voltageGap() + 0.5 * model_.value().get_deltaV(); + upperB_ = model_.vg() + 0.5 * model_.deltaV(); + // Set the transitional conductance value + gLarge_ = model_.ic() / (model_.icFct() * model_.deltaV()); + if (model_.rtype() == 0) { + model_.r0(model_.rn()); + } } // Update the value based on the matrix entry based on voltage value bool JJ::update_value(const double& v) { // Shorthand for the model - const Model& m = model_.value(); + const Model& m = model_; // If the absolute value of the voltage is less than lower bounds if (fabs(v) < lowerB_) { // Set the transition current to 0 - transitionCurrent_ = 0.0; + it_ = 0.0; // If the non zero vector does not end with the subgap conductance if (matrixInfo.nonZeros_.back() != -1 / subgap_impedance()) { // Make it end with the subgap conductance @@ -255,9 +246,11 @@ bool JJ::update_value(const double& v) { // If the absolute value of the voltage is less than the upperbounds } else if (fabs(v) < upperB_) { // Set the transition current - transitionCurrent_ = lowerB_ * ((1 / m.get_subgapResistance()) - gLarge_); + it_ = lowerB_ * ((1 / m.r0()) - gLarge_); // If the voltage is negative, current must be negative - if (v < 0) transitionCurrent_ = -transitionCurrent_; + if (v < 0) { + it_ = -it_; + } // If the back of the non zero vector is not the transition conductance if (matrixInfo.nonZeros_.back() != -1 / transient_impedance()) { // Set it to the transition conductance @@ -273,7 +266,7 @@ bool JJ::update_value(const double& v) { // If neither of the above then it must be in normal operating region } else { // Reset the transition current, transition has passed. - transitionCurrent_ = 0.0; + it_ = 0.0; // If the back of the non zero vector is not the normal conductance if (matrixInfo.nonZeros_.back() != -1 / normal_impedance()) { // Set it to the normal conductance @@ -289,23 +282,4 @@ bool JJ::update_value(const double& v) { } // This should never happen, only here to appease the return type return false; -} - -// Update timestep based on a scalar factor i.e 0.5 for half the timestep -void JJ::update_timestep(const double& factor) { - h_ = h_ * factor; - if (state_ == 0) { - matrixInfo.nonZeros_.back() = -1 / subgap_impedance(); - } else if (state_ == 1) { - matrixInfo.nonZeros_.back() = -1 / transient_impedance(); - } else if (state_ == 2) { - matrixInfo.nonZeros_.back() = -1 / normal_impedance(); - } - if (at_ == AnalysisType::Voltage) { - matrixInfo.nonZeros_.at(hDepPos_) = - (1 / factor) * matrixInfo.nonZeros_.at(hDepPos_); - } else if (at_ == AnalysisType::Phase) { - matrixInfo.nonZeros_.at(hDepPos_) = - factor * matrixInfo.nonZeros_.at(hDepPos_); - } } \ No newline at end of file diff --git a/src/Model.cpp b/src/Model.cpp index 125c680e..e96fc711 100644 --- a/src/Model.cpp +++ b/src/Model.cpp @@ -19,7 +19,7 @@ void Model::parse_model( // Create a model that will be stored Model temp; // The second token is the model label - temp.set_modelName(s.first.at(1)); + temp.modelName(s.first.at(1)); // The third token needs to start with "JJ" for this to be valid if (s.first.at(2).compare(0, 2, "JJ") != 0) { Errors::model_errors( @@ -44,31 +44,36 @@ void Model::parse_model( } // Assign the relevant model parameters if (tokens.at(i) == "VG" || tokens.at(i) == "VGAP") { - temp.set_voltageGap(value); + temp.vg(value); } else if (tokens.at(i) == "IC" || tokens.at(i) == "ICRIT") { - temp.set_criticalCurrent(value); + temp.ic(value); } else if (tokens.at(i) == "RTYPE") { - temp.set_resistanceType((int)value); + temp.rtype((int)value); } else if (tokens.at(i) == "RN") { - temp.set_normalResistance(value); + temp.rn(value); } else if (tokens.at(i) == "R0") { - temp.set_subgapResistance(value); + temp.r0(value); } else if (tokens.at(i) == "CAP" || tokens.at(i) == "C") { - temp.set_capacitance(value); + temp.c(value); } else if (tokens.at(i) == "T") { - temp.set_temperature(value); + temp.t(value); + temp.tDep(true); } else if (tokens.at(i) == "TC") { - temp.set_criticalTemperature(value); + temp.tc(value); + temp.tDep(true); } else if (tokens.at(i) == "DELV") { - temp.set_deltaV(value); + temp.deltaV(value); } else if (tokens.at(i) == "D") { - temp.set_transparency(value); + temp.d(value); + temp.tDep(true); } else if (tokens.at(i) == "ICFACT" || tokens.at(i) == "ICFCT") { - temp.set_criticalToNormalRatio(value); + temp.icFct(value); } else if (tokens.at(i) == "PHI") { - temp.set_phaseOffset(value); - } else if (tokens.at(i) == "PHI0") { - temp.set_phiZero(value); + temp.phiOff(value); + } else { + // Incompatible parameter + Errors::model_errors(ModelErrors::PARAM_TYPE_ERROR, + Misc::vector_to_string(s.first)); } } diff --git a/src/Parameters.cpp b/src/Parameters.cpp index dc156a44..133da87e 100644 --- a/src/Parameters.cpp +++ b/src/Parameters.cpp @@ -73,6 +73,10 @@ double JoSIM::parse_param( bool single) { // Initialize the expression to evaluate std::string expToEval = expr; + // Sanity check, prepend 0 to a string where the value is eg. .5 to vorm 0.5 + if (expToEval.front() == '.') { + expToEval = "0" + expToEval; + } // Remove any and all whitespace characters expToEval.erase(std::remove_if(expToEval.begin(), expToEval.end(), isspace), expToEval.end()); diff --git a/src/Simulation.cpp b/src/Simulation.cpp index c4bc09e1..72b14532 100644 --- a/src/Simulation.cpp +++ b/src/Simulation.cpp @@ -64,6 +64,7 @@ void Simulation::setup(Input& iObj, Matrix& mObj) { stepSize_ = iObj.transSim.tstep(); prstep_ = iObj.transSim.prstep(); prstart_ = iObj.transSim.prstart(); + startup_ = iObj.transSim.startup(); x_.clear(); x_.resize(mObj.branchIndex, 0.0); if (!mObj.relevantTraces.empty()) { @@ -90,6 +91,28 @@ void Simulation::trans_sim(Matrix &mObj) { } // Initialize the b matrix b_.resize(mObj.rp.size(), 0.0); + if (startup_) { + // Stabilize the simulation before starting at t=0 + int startup = 2 * pow(10, (abs(log10(stepSize_)) - 12) * 2 + 1); + for (int i = -startup; i < 0; ++i) { + double step = i * stepSize_; + // Setup the b matrix + setup_b(mObj, i, i * stepSize_); + if (needsTR_) return; + // Assign x_prev the new b + x_ = b_; + // Solve Ax=b, storing the results in x_ + if (SLU) { + lu.solve(x_); + } else { + simOK_ = klu_l_tsolve( + Symbolic_, Numeric_, mObj.rp.size() - 1, 1, &x_.front(), &Common_); + // If anything is a amiss, complain about it + if (!simOK_) Errors::simulation_errors( + SimulationErrors::MATRIX_SINGULAR); + } + } + } // Start the simulation loop for(int i = 0; i < simSize_; ++i) { double step = i * stepSize_; @@ -310,7 +333,7 @@ void Simulation::handle_jj( // Phase guess (P0) temp.phi0_ = (4.0/3.0) * temp.pn1_ - (1.0/3.0) * temp.pn2_ + ((1.0 / Constants::SIGMA) * - ((2.0 * (stepSize_ * factor)) / 3.0)) * v0; + ((2.0 * (stepSize_)) / 3.0)) * v0; // Ensure timestep is not too large if ((double)i/(double)simSize_ > 0.01) { if (abs(temp.phi0_ - temp.pn1_) > (0.20 * 2 * Constants::PI)) { @@ -323,8 +346,8 @@ void Simulation::handle_jj( // (hbar / 2 * e) ( -(2 / h) φp1 + (1 / 2h) φp2 ) if(atyp_ == AnalysisType::Voltage) { b_.at(temp.variableIndex_) = - (Constants::SIGMA) * (-(2.0 / (stepSize_ * factor)) * - temp.pn1_ + (1.0 / (2.0 * (stepSize_ * factor))) * temp.pn2_); + (Constants::SIGMA) * (-(2.0 / (stepSize_)) * + temp.pn1_ + (1.0 / (2.0 * (stepSize_))) * temp.pn2_); // (4 / 3) φp1 - (1/3) φp2 } else if (atyp_ == AnalysisType::Phase) { b_.at(temp.variableIndex_) = @@ -338,31 +361,43 @@ void Simulation::handle_jj( temp.vn4_ = temp.vn3_; temp.vn3_ = temp.vn2_; // Update junction transition - if(model.value().get_resistanceType() == 1) { + if(model.rtype() == 1) { auto testLU = temp.update_value(v0); if(testLU && !needsLU_) { needsLU_ = true; } } - // -(hR / h + 2RC) * (Ic sin (φ0 - 2C / h Vp1 + C/2h Vp2 + It) - b_.at(temp.indexInfo.currentIndex_.value()) = - (temp.matrixInfo.nonZeros_.back()) * ((((Constants::PI * temp.del_) / - (2 * Constants::EV * temp.rncalc_)) * (sin((temp.phi0_ + - temp.model_.value().get_phiZero())) / - sqrt(1 - model.value().get_transparency() * (sin((temp.phi0_ + - temp.model_.value().get_phiZero()) / 2) * - sin((temp.phi0_ + - temp.model_.value().get_phiZero()) / 2)))) * tanh((temp.del_) / - (2 * Constants::BOLTZMANN * model.value().get_temperature()) * - sqrt(1 - model.value().get_transparency() * - (sin((temp.phi0_ + - temp.model_.value().get_phiZero()) / 2) * sin((temp.phi0_ + - temp.model_.value().get_phiZero()) / 2))))) - - (((2 * model.value().get_capacitance()) / - (stepSize_ * factor)) * temp.vn1_) + - ((model.value().get_capacitance() / - (2.0 * (stepSize_ * factor))) * temp.vn2_) + - temp.transitionCurrent_); + // sin (φ0 - φ) + double sin_phi = sin(temp.phi0_ - temp.model_.phiOff()); + if (!temp.model_.tDep()) { + // -(hR / h + 2RC) * (Ic sin (φ0) - 2C / h Vp1 + C/2h Vp2 + It) + b_.at(temp.indexInfo.currentIndex_.value()) = + (temp.matrixInfo.nonZeros_.back()) * (temp.model_.ic() * sin_phi - + (((2 * model.c()) / (stepSize_)) * temp.vn1_) + + ((model.c() / (2.0 * (stepSize_))) * temp.vn2_) + + temp.it_); + } else { + double sin2_half_phi = sin((temp.phi0_ - temp.model_.phiOff()) / 2); + sin2_half_phi = sin2_half_phi * sin2_half_phi; + double sqrt_part = sqrt(1 - model.d() * sin2_half_phi); + b_.at(temp.indexInfo.currentIndex_.value()) = + // -(hR / h + 2RC) *( + (temp.matrixInfo.nonZeros_.back()) * (( + // (π * Δ / 2 * e * Rn) + ((Constants::PI * temp.del_) + / (2 * Constants::EV * temp.model_.rn())) + // * (sin(φ0 - φ) / √(1 - D * sin²((φ0 - φ) / 2)) + * (sin_phi / sqrt_part) + // * tanh(Δ / (2 * kB * T) * √(1 - D * sin²((φ0 - φ) / 2))) + * tanh(temp.del_ / (2 * Constants::BOLTZMANN * model.t()) + * sqrt_part)) + // - 2C / h Vp1 + - (((2 * model.c()) / stepSize_) * temp.vn1_) + // + C/2h Vp2 + + ((model.c() / (2.0 * stepSize_)) * temp.vn2_) + // + It) + + temp.it_); + } temp.vn2_ = temp.vn1_; } } diff --git a/src/Transient.cpp b/src/Transient.cpp index 3cb3de7f..fb587c3a 100644 --- a/src/Transient.cpp +++ b/src/Transient.cpp @@ -9,16 +9,21 @@ using namespace JoSIM; -void Transient::identify_simulation( - const std::vector& controls, Transient& tObj) { +void Transient::identify_simulation( + std::vector& controls, Transient& tObj) { // Flag to store that a transient simulation was found bool transFound = false; // Loop through all the controls - for (const auto& i : controls) { + for (auto& i : controls) { // If the first token of the line contains "TRAN" if (i.front().find("TRAN") != std::string::npos) { // Set the flag as true transFound = true; + // Check for disable startup flag + if (i.back() == "DST") { + tObj.startup(false); + i.pop_back(); + } // If there are less than 2 tokens if (i.size() < 2) { // Complain of invalid transient analysis specification From b22d5673d9a4fad82b025fbde4bd249a383e83c6 Mon Sep 17 00:00:00 2001 From: JoeyDelp Date: Mon, 22 Nov 2021 10:01:59 +0200 Subject: [PATCH 05/15] Fix LUSolve for CLang --- include/JoSIM/LUSolve.hpp | 5 ++--- src/LUSolve.cpp | 5 +++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/JoSIM/LUSolve.hpp b/include/JoSIM/LUSolve.hpp index ec8ec555..0ff9b565 100644 --- a/include/JoSIM/LUSolve.hpp +++ b/include/JoSIM/LUSolve.hpp @@ -12,7 +12,6 @@ namespace JoSIM { class LUSolve { private: char equed[1] = { 'N' }; - yes_no_t equil; trans_t trans; SuperMatrix A, L, U, B, X; GlobalLU_t Glu; @@ -21,11 +20,11 @@ namespace JoSIM { long long* etree; void* work = nullptr; long long info, lwork, nrhs, ldx; - long long i, m, n, nnz; + long long m, n, nnz; double* rhsb,* rhsx,* xact; double* R,* C; double* ferr,* berr; - double u, rpg, rcond; + double rpg, rcond; mem_usage_t mem_usage; superlu_options_t options; SuperLUStat_t stat; diff --git a/src/LUSolve.cpp b/src/LUSolve.cpp index 677149be..05c0542e 100644 --- a/src/LUSolve.cpp +++ b/src/LUSolve.cpp @@ -63,8 +63,9 @@ void LUSolve::solve(std::vector& x) { if (!constructed) { ABORT("Preconditioner not constructed."); } - DNformat LHSstore = { x.size(), &x.front() }; - SuperMatrix LHSmat = { SLU_DN, SLU_D, SLU_GE, x.size(), 1, &LHSstore }; + DNformat LHSstore = { static_cast(x.size()), &x.front() }; + SuperMatrix LHSmat = { SLU_DN, SLU_D, SLU_GE, static_cast(x.size()), + 1, &LHSstore }; dgstrs(trans, &L, &U, perm_c, perm_r, &LHSmat, &stat, &info); } From 98bc9243b5b9d237363b91dfa47ef07c55df7ac2 Mon Sep 17 00:00:00 2001 From: JoeyDelp Date: Mon, 6 Dec 2021 10:38:12 +0200 Subject: [PATCH 06/15] Thermal noise update --- docs/img/josim_help.png | Bin 39429 -> 58944 bytes docs/img/josim_jtl_ex.png | Bin 26368 -> 40090 bytes docs/index.md | 4 +- docs/syntax.md | 6 ++- docs/tech_disc.md | 4 ++ include/JoSIM/Function.hpp | 7 ++++ include/JoSIM/Input.hpp | 3 +- include/JoSIM/JJ.hpp | 4 +- include/JoSIM/Noise.hpp | 13 ++---- include/JoSIM/Resistor.hpp | 3 ++ include/JoSIM/Simulation.hpp | 2 +- scripts/josim-plot.py | 6 +-- src/Function.cpp | 27 +++++++++++-- src/Input.cpp | 5 +++ src/JJ.cpp | 63 +++++++++++++++++++---------- src/Matrix.cpp | 2 + src/Noise.cpp | 74 +---------------------------------- src/Resistor.cpp | 28 +++++++++++-- src/Simulation.cpp | 35 ++++++++++++++++- src/Transient.cpp | 8 ++-- src/josim.cpp | 2 +- 21 files changed, 169 insertions(+), 127 deletions(-) diff --git a/docs/img/josim_help.png b/docs/img/josim_help.png index 7daf103cff871ab126bf5fc7c4b44f216966cab2..e24e4df72a9eda625a3e36ba538d455f92f70746 100644 GIT binary patch literal 58944 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 DwEM|t literal 39429 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 JSMEO*{|8l)Vi^Dc diff --git a/docs/img/josim_jtl_ex.png b/docs/img/josim_jtl_ex.png index 4f47bf6affa67da2d3a7d3473f7e303dc33271fd..2875c1a3e857d9011081574ddcf5df4ca75ba135 100644 GIT binary patch literal 40090 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 S90xfi9LD-)dS$v!;lBgt*%O2S literal 26368 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 QJ+6~hl2el{k~Z`GKfEc<*Z=?k diff --git a/docs/index.md b/docs/index.md index d3fe10ff..a5f26296 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,9 +4,9 @@ Developers Manual for v2.5.1 ## Project Status -### Testing: v2.5.1 - Status: [![Build Status](https://joeydelp.visualstudio.com/JoSIM/_apis/build/status/JoSIM-CI-Devel?branchName=testing)](https://joeydelp.visualstudio.com/JoSIM/_build/latest?definitionId=1&branchName=testing) +### Testing: v2.6 - Status: [![Build Status](https://joeydelp.visualstudio.com/JoSIM/_apis/build/status/JoSIM-CI-Devel?branchName=testing)](https://joeydelp.visualstudio.com/JoSIM/_build/latest?definitionId=1&branchName=testing) -### Stable: v2.5.1 - Status: [![Build Status](https://joeydelp.visualstudio.com/JoSIM/_apis/build/status/JoeyDelp.JoSIM?branchName=master)](https://joeydelp.visualstudio.com/JoSIM/_build/latest?definitionId=3&branchName=master) +### Stable: v2.6 - Status: [![Build Status](https://joeydelp.visualstudio.com/JoSIM/_apis/build/status/JoeyDelp.JoSIM?branchName=master)](https://joeydelp.visualstudio.com/JoSIM/_build/latest?definitionId=3&branchName=master) ## Introduction diff --git a/docs/syntax.md b/docs/syntax.md index f53356fe..c56a7081 100644 --- a/docs/syntax.md +++ b/docs/syntax.md @@ -96,12 +96,14 @@ The only junction model currently supported by JoSIM is the RCSJ model and thus | DELV | 0, $\infty$ | 0.1E-3 | Transitional voltage from subgap to normal | | D | 0.0, 1 | 0.0 | Point of contact transparency affecting current phase relationship | | ICFCT or ICFACT | 0, 1 | $\frac{\pi}{4}$ | Ratio of critical current to quasiparticle step height | -| PHI | 0, $\pi$ | 0 | Starting phase of junction | +| PHI | 0, $2\pi$ | 0 | Allows phi-junction capability such as the $\pi$-junction. | The *.model* line is unique to the subcircuit it falls under and can thus allow different models with the same name under separate subcircuits. If the model is not found under the subcircuit it will be searched for globally and if not found default values (default model) will be used instead. The **AREA** and **IC** parameters act as modifiers to the model parameters. **AREA** is a critical current multiplier, where if **IC** is specified it replaces the **AREA** value by $AREA=\frac{IC_{jj}}{IC_{model}}$. +By setting the **PHI** parameter of the model, the phase value is persistantly subtracted from the phase ($\phi$) in the $\sin(\phi)$ part of the JJ current. This allows elements such as the $\pi$-junction to be modeled. + ### Transmission Line **T**Label $N^{+}_{1}$ $N^{-}_{1}$ $N^{+}_{2}$ $N^{-}_{2}$ **TD=VALUE** **Z0=VALUE** @@ -273,6 +275,8 @@ A subcircuit can be used in the main netlist or another subcircuit (nesting) usi **X**Label *IO Nodes* *SubcktName* (WRspice (normal SPICE) mode) +Additionally, keywords in the form of **LABEL=VALUE** can be appended to the end of the subcircuit declaration line which when instantiated will replace the value of the **LABEL** component within the subcircuit with the associated **VALUE**. This allows for unique subcircuit instantiations which would prove useful in testing various parameters without altering the original subcircuit or having multiple instances of the same subcircuit definition. This could open the door for potential future margin and optimization software. + ### Noise As mentioned in the technical discussion, noise can be automatically inserted as current sources in parallel to each resistor. This thermal noise temperature and bandwidth can be specified globally using the following commands: diff --git a/docs/tech_disc.md b/docs/tech_disc.md index 09089deb..1f58cda5 100644 --- a/docs/tech_disc.md +++ b/docs/tech_disc.md @@ -58,6 +58,10 @@ This enables different levels of verbosity by the simulator. Level `1` verbosity Only displays the version string for **josim-cli** and then exits. This string is always displayed by default for any command. This command, however, only displays the version string. +### Solver (-x): + +This option allows switching between LU solvers. Default is KLU solver. Setting this to `1` enables SuperLU solver. + ## Parse Input {#parse-input} The input data received through any of the two means above is parsed in the following steps: diff --git a/include/JoSIM/Function.hpp b/include/JoSIM/Function.hpp index e9c8c84e..5527487f 100644 --- a/include/JoSIM/Function.hpp +++ b/include/JoSIM/Function.hpp @@ -25,6 +25,7 @@ namespace JoSIM { FunctionType fType_ = FunctionType::PWL; std::vector timeValues_; std::vector ampValues_; + std::vector miscValues_; void parse_pwl(const tokens_t& t, const Input& iObj, const string_o& s); void parse_pulse(const tokens_t& t, const Input& iObj, const string_o& s); void parse_sin(const tokens_t& t, const Input& iObj, const string_o& s); @@ -46,6 +47,12 @@ namespace JoSIM { const string_o& subckt); double value(double x); void ampValues(std::vector values); + std::vector ampValues() { + return ampValues_; + } + void clearMisc() { + miscValues_.clear(); + } }; // class Function diff --git a/include/JoSIM/Input.hpp b/include/JoSIM/Input.hpp index 5259845f..de7d2c36 100644 --- a/include/JoSIM/Input.hpp +++ b/include/JoSIM/Input.hpp @@ -24,7 +24,8 @@ namespace JoSIM { public: Netlist netlist; Transient transSim; - std::optional globalTemp, neB; + std::optional globalTemp; + double neB = 1E12; std::vector fileLines, controls; std::vector relevantX; std::unordered_map parameters; diff --git a/include/JoSIM/JJ.hpp b/include/JoSIM/JJ.hpp index c34e0bb4..02a150f8 100644 --- a/include/JoSIM/JJ.hpp +++ b/include/JoSIM/JJ.hpp @@ -10,6 +10,7 @@ #include "JoSIM/AnalysisType.hpp" #include "JoSIM/Input.hpp" #include "JoSIM/Spread.hpp" +#include "JoSIM/Function.hpp" #include #include @@ -54,7 +55,7 @@ namespace JoSIM { public: int variableIndex_ = 0; double area_ = 1.0; - std::optional Ic_; + std::optional Ic_, temp_, neb_, spAmp_; Model model_; double phaseConst_ = 0.0; double lowerB_ = 0.0, upperB_ = 0.0, gLarge_ = 0.0; @@ -64,6 +65,7 @@ namespace JoSIM { vn6_ = vn5_; double it_ = 0.0; JoSIM::AnalysisType at_; + std::optional thermalNoise; JJ( const std::pair& s, const NodeConfig& ncon, diff --git a/include/JoSIM/Noise.hpp b/include/JoSIM/Noise.hpp index b58813c0..f626cef8 100644 --- a/include/JoSIM/Noise.hpp +++ b/include/JoSIM/Noise.hpp @@ -8,19 +8,12 @@ namespace JoSIM { class Noise { - private: - static double determine_spectral_amplitude(const double& R, - const double& T); - static std::pair - create_resistive_current_noise(Input& iObj, const double& R, - const double& T, const double& B, - std::vector>::iterator& i); + public: static void determine_global_temperature(Input& iObj); static void determine_noise_effective_bandwidth(Input& iObj); + static double determine_spectral_amplitude(const double& R, + const double& T); - - public: - static void add_noise_sources(Input& iObj); }; } diff --git a/include/JoSIM/Resistor.hpp b/include/JoSIM/Resistor.hpp index cf52c880..b295a8ac 100644 --- a/include/JoSIM/Resistor.hpp +++ b/include/JoSIM/Resistor.hpp @@ -9,6 +9,7 @@ #include "JoSIM/AnalysisType.hpp" #include "JoSIM/Input.hpp" #include "JoSIM/Spread.hpp" +#include "JoSIM/Function.hpp" #include #include @@ -36,8 +37,10 @@ namespace JoSIM { class Resistor : public BasicComponent { private: JoSIM::AnalysisType at_; + std::optional spAmp_, temp_, neb_; public: double pn1_ = 0.0, pn2_ = 0.0, pn3_ = 0.0, pn4_ = 0.0; + std::optional thermalNoise; Resistor( const std::pair& s, const NodeConfig& ncon, diff --git a/include/JoSIM/Simulation.hpp b/include/JoSIM/Simulation.hpp index dd251d88..f61906fa 100644 --- a/include/JoSIM/Simulation.hpp +++ b/include/JoSIM/Simulation.hpp @@ -50,7 +50,7 @@ namespace JoSIM { void reduce_step(Input& iObj, Matrix& mObj); void handle_cs(Matrix& mObj, double& step, const int& i); - void handle_resistors(Matrix& mObj); + void handle_resistors(Matrix& mObj, double& step); void handle_inductors(Matrix& mObj, double factor = 1); void handle_capacitors(Matrix& mObj); void handle_jj(Matrix& mObj, int& i, double& step, double factor = 1); diff --git a/scripts/josim-plot.py b/scripts/josim-plot.py index bf5c2aa2..b22f5b96 100644 --- a/scripts/josim-plot.py +++ b/scripts/josim-plot.py @@ -112,11 +112,11 @@ def main(): # Function that sets the Y-axis title relevant to the data def y_axis_title(figLabel): if figLabel[0] == 'V': - return "Voltage (volts)" + return "Voltage (V)" elif figLabel[0] == 'I': - return "Current (ampere)" + return "Current (A)" elif figLabel[0] == 'P': - return "Phase (radians)" + return "Phase (rad)" else: return "Unknown" diff --git a/src/Function.cpp b/src/Function.cpp index d8f9567c..0daa3e70 100644 --- a/src/Function.cpp +++ b/src/Function.cpp @@ -236,6 +236,7 @@ void Function::parse_noise( const double& tstep = iObj.transSim.tstep(); // Set amplitudes ampValues_.emplace_back(parse_param(t.at(0), iObj.parameters, s)); + ampValues_.emplace_back(0.0); // Default values for the arguments timeValues_.emplace_back(0.0); timeValues_.emplace_back(tstep); @@ -244,6 +245,11 @@ void Function::parse_noise( timeValues_.at(0) = parse_param(t.at(1), iObj.parameters, s); if (t.size() >= 3) timeValues_.at(1) = parse_param(t.at(2), iObj.parameters, s); + miscValues_.emplace_back(0.0); + miscValues_.emplace_back( + ampValues_.at(0) * Misc::grand() / sqrt(2.0 * timeValues_.back())); + miscValues_.emplace_back(timeValues_.at(0)); + miscValues_.emplace_back(timeValues_.at(0) + timeValues_.at(1)); if (iObj.argVerb) { if (ampValues_.at(0) == 0.0) { Errors::function_errors(FunctionErrors::NOISE_VA_ZERO, t.at(1)); @@ -385,10 +391,23 @@ double Function::return_cus(double& x) { } double Function::return_noise(double& x) { - if (x < timeValues_.front()) - return 0.0; - else - return ampValues_.at(0) * Misc::grand() / sqrt(2.0 * timeValues_.back()); + if (x < timeValues_.front()) { + return ampValues_.at(1); + } else { + if (x >= miscValues_.at(3)) { + miscValues_.at(0) = miscValues_.at(1); + miscValues_.at(1) = ampValues_.at(0) * + Misc::grand() / sqrt(2.0 * timeValues_.back()); + miscValues_.at(2) = miscValues_.at(3); + miscValues_.at(3) = miscValues_.at(2) + timeValues_.back(); + } + double& y2 = miscValues_.at(1); + double& y1 = miscValues_.at(0); + double& x2 = miscValues_.at(3); + double& x1 = miscValues_.at(2); + // Calculate function value and return it + return y1 + ((y2 - y1) / (x2 - x1)) * (x - x1); + } } double Function::return_pws(double& x) { diff --git a/src/Input.cpp b/src/Input.cpp index 455a226b..e2fd38aa 100644 --- a/src/Input.cpp +++ b/src/Input.cpp @@ -10,6 +10,7 @@ #include #include #include +#include using namespace JoSIM; @@ -85,6 +86,9 @@ std::vector Input::read_input( output_files.emplace_back(OutputFile(path.string())); } fileLines.emplace_back(tokens); + // If the line contains a "END" statement + } else if (tokens.at(0) == ".END" || tokens.at(0) == "END") { + break; // If the line does not contain an "INCLUDE" or "FILE" statement } else { // Transform the entire line to upper case @@ -117,6 +121,7 @@ std::vector Input::read_input( } void Input::parse_input(string_o fileName) { + srand(time(NULL)); // Create a seperate thread that will be used for printing creation progress std::thread printingThread; // Variable to store the tokenized input diff --git a/src/JJ.cpp b/src/JJ.cpp index 7c5e1426..ca8ee6a8 100644 --- a/src/JJ.cpp +++ b/src/JJ.cpp @@ -5,6 +5,7 @@ #include "JoSIM/Misc.hpp" #include "JoSIM/Errors.hpp" #include "JoSIM/Constants.hpp" +#include "JoSIM/Noise.hpp" #include @@ -42,12 +43,31 @@ JJ::JJ( const nodemap& nm, std::unordered_set& lm, nodeconnections& nc, Input& iObj, Spread& spread, int& bi) { double spr = 1.0; - for (auto i : s.first) { - if (i.find("SPREAD=") != std::string::npos) { - spr = - parse_param(i.substr(i.find("SPREAD=") + 7), iObj.parameters, s.second); + tokens_t t; + for (int i = 3; i < s.first.size(); ++i) { + auto& ti = s.first.at(i); + if (ti.rfind("SPREAD=", 0) == 0) { + spr = parse_param(ti.substr(7), iObj.parameters, s.second); + } else if (ti.rfind("TEMP=", 0) == 0) { + temp_ = parse_param(ti.substr(5), iObj.parameters, s.second); + } else if (ti.rfind("NEB=", 0) == 0) { + neb_ = parse_param(ti.substr(4), iObj.parameters, s.second); + } else if (ti.rfind("AREA=", 0) == 0) { + area_ = spread.spread_value( + parse_param(ti.substr(5), iObj.parameters, s.second), Spread::JJ, spr); + } else if (ti.rfind("IC=", 0) == 0) { + Ic_ = spread.spread_value( + parse_param(ti.substr(3), iObj.parameters, s.second), Spread::JJ, spr); + } else { + t.emplace_back(ti); } } + if (!temp_ && iObj.globalTemp) { + temp_ = iObj.globalTemp; + } + if (!neb_ && iObj.neB) { + neb_ = iObj.neB; + } // Set component timestep h_ = iObj.transSim.tstep(); at_ = iObj.argAnal; @@ -62,22 +82,6 @@ JJ::JJ( netlistInfo.label_ = s.first.at(0); // Add the label to the known labels list lm.emplace(s.first.at(0)); - tokens_t t; - // Identify the named parameters of the junction, leaving model as last token - for (auto i : s.first) { - if (i.find("AREA=") != std::string::npos) { - area_ = spread.spread_value( - parse_param(i.substr(i.find("AREA=") + 5), iObj.parameters, s.second), - Spread::JJ, spr); - } else if (i.find("IC=") != std::string::npos) { - Ic_ = spread.spread_value( - parse_param(i.substr(i.find("IC=") + 3), iObj.parameters, s.second), - Spread::JJ, spr); - } else if (i.find("SPREAD=") != std::string::npos) { - } else { - t.emplace_back(i); - } - } // Set the model for this JJ instance set_model(t, iObj.netlist.models_new, s.second); // Set the phase constant @@ -98,6 +102,15 @@ JJ::JJ( set_node_indices(tokens_t(s.first.begin() + 1, s.first.begin() + 3), nm, nc); // Set the non zero, column index and row pointer vectors set_matrix_info(); + if (temp_) { + spAmp_ = Noise::determine_spectral_amplitude( + this->model_.r0(), temp_.value()); + Function tnoise; + tnoise.parse_function("NOISE(" + + Misc::precise_to_string(spAmp_.value()) + ", 0.0, " + + Misc::precise_to_string(1.0 / neb_.value()) + ")", iObj, s.second); + thermalNoise = tnoise; + } } double JJ::subgap_impedance() { @@ -229,6 +242,11 @@ bool JJ::update_value(const double& v) { const Model& m = model_; // If the absolute value of the voltage is less than lower bounds if (fabs(v) < lowerB_) { + // Set temperature resistance + if (this->temp_) { + thermalNoise.value().ampValues().at(0) = + Noise::determine_spectral_amplitude(this->model_.r0(), temp_.value()); + } // Set the transition current to 0 it_ = 0.0; // If the non zero vector does not end with the subgap conductance @@ -265,6 +283,11 @@ bool JJ::update_value(const double& v) { } // If neither of the above then it must be in normal operating region } else { + // Set temperature resistance + if (this->temp_) { + thermalNoise.value().ampValues().at(0) = + Noise::determine_spectral_amplitude(this->model_.rn(), temp_.value()); + } // Reset the transition current, transition has passed. it_ = 0.0; // If the back of the non zero vector is not the normal conductance diff --git a/src/Matrix.cpp b/src/Matrix.cpp index 5fa38861..7aea8917 100644 --- a/src/Matrix.cpp +++ b/src/Matrix.cpp @@ -34,6 +34,8 @@ void Matrix::create_matrix(Input& iObj) { void Matrix::setup(Input& iObj) { needsTR_ = false; spread.get_spreads(iObj); + Noise::determine_global_temperature(iObj); + Noise::determine_noise_effective_bandwidth(iObj); // Create a node counter variable int nodeCounter = 0; // Variables to store node configs since they are already identified here diff --git a/src/Noise.cpp b/src/Noise.cpp index d3b8ef2b..7732c595 100644 --- a/src/Noise.cpp +++ b/src/Noise.cpp @@ -27,79 +27,7 @@ void JoSIM::Noise::determine_noise_effective_bandwidth(Input& iObj) { double JoSIM::Noise::determine_spectral_amplitude(const double& R, const double& T) { - // spectral amplitute = sqrt(4 * kB * T * B / R) + // spectral amplitute = sqrt(4 * kB * T / R) double spAmp = sqrt((4 * Constants::BOLTZMANN * T) / R); return spAmp; } - -std::pair -JoSIM::Noise::create_resistive_current_noise(Input& iObj, const double& R, - const double& T, const double& B, - std::vector>::iterator& i) { - std::pair noiseSource; - noiseSource.first.emplace_back("INOISE_" + i->first.front()); - noiseSource.first.emplace_back(i->first.at(1)); - noiseSource.first.emplace_back(i->first.at(2)); - noiseSource.first.emplace_back("NOISE(" + Misc::precise_to_string( - determine_spectral_amplitude(R, T))); - noiseSource.first.emplace_back("0"); - noiseSource.first.emplace_back( - Misc::precise_to_string(1 / B) + ")"); - noiseSource.second = i->second; - return noiseSource; -} - -void JoSIM::Noise::add_noise_sources(Input& iObj) { - determine_global_temperature(iObj); - determine_noise_effective_bandwidth(iObj); - std::vector> noises; - for (auto it = iObj.netlist.expNetlist.begin(); - it != iObj.netlist.expNetlist.end(); ++it) { - if (it->first.front().at(0) == 'R') { - std::optional T; - double B = 0, R = 0; - if (!iObj.neB) { - B = 1E12; - } else { - B = iObj.neB.value(); - } - if (iObj.globalTemp) { - T = iObj.globalTemp.value(); - } - if (it->first.size() > 4) { - tokens_t t(it->first.begin() + 4, it->first.end()); - std::string temp = Misc::vector_to_string(t, " "); - t = Misc::tokenize(temp, " ="); - for (auto i = t.begin(); i < t.end(); ++i) { - if (*i == "TEMP") { - if (i + 1 == t.end() || *(i + 1) == "NEB") { - Errors::invalid_component_errors(ComponentErrors::RES_ERROR, - Misc::vector_to_string(it->first)); - } else { - T = parse_param(*(i + 1), iObj.parameters, it->second); - } - } - if (*i == "NEB") { - if (i + 1 == t.end() || *(i + 1) == "TEMP") { - Errors::invalid_component_errors(ComponentErrors::RES_ERROR, - Misc::vector_to_string(it->first)); - } else { - B = parse_param(*(i + 1), iObj.parameters, it->second); - } - } - } - R = parse_param(*(it->first.begin() + 3), iObj.parameters, it->second); - } else { - R = parse_param(it->first.back(), iObj.parameters, it->second); - } - if (T) { - noises.emplace_back( - create_resistive_current_noise(iObj, R, T.value(), B, it)); - } - } - } - if (noises.size() != 0) { - iObj.netlist.expNetlist.insert(iObj.netlist.expNetlist.end(), - noises.begin(), noises.end()); - } -} diff --git a/src/Resistor.cpp b/src/Resistor.cpp index 1e5d214b..017a9c47 100644 --- a/src/Resistor.cpp +++ b/src/Resistor.cpp @@ -5,6 +5,7 @@ #include "JoSIM/Misc.hpp" #include "JoSIM/Errors.hpp" #include "JoSIM/Constants.hpp" +#include "JoSIM/Noise.hpp" #include @@ -31,12 +32,22 @@ Resistor::Resistor( const nodemap& nm, std::unordered_set& lm, nodeconnections& nc, Input& iObj, Spread& spread, int& bi) { double spr = 1.0; - for (auto i : s.first) { - if (i.find("SPREAD=") != std::string::npos) { - spr = - parse_param(i.substr(i.find("SPREAD=") + 7), iObj.parameters, s.second); + for (int i = 4; i < s.first.size(); ++i) { + auto& t = s.first.at(i); + if (t.rfind("SPREAD=", 0) == 0) { + spr = parse_param(t.substr(7), iObj.parameters, s.second); + } else if (t.rfind("TEMP=", 0) == 0) { + temp_ = parse_param(t.substr(5), iObj.parameters, s.second); + } else if (t.rfind("NEB=", 0) == 0) { + neb_ = parse_param(t.substr(4), iObj.parameters, s.second); } } + if (!temp_ && iObj.globalTemp) { + temp_ = iObj.globalTemp; + } + if (!neb_ && iObj.neB) { + neb_ = iObj.neB; + } at_ = iObj.argAnal; // Check if the label has already been defined if (lm.count(s.first.at(0)) != 0) { @@ -70,6 +81,15 @@ Resistor::Resistor( -((2.0 * iObj.transSim.tstep()) / 3.0) * (netlistInfo.value_ / Constants::SIGMA)); } + if (temp_) { + spAmp_ = Noise::determine_spectral_amplitude( + netlistInfo.value_, temp_.value()); + Function tnoise; + tnoise.parse_function("NOISE(" + + Misc::precise_to_string(spAmp_.value()) + ", 0.0, " + + Misc::precise_to_string(1.0 / neb_.value()) + ")", iObj, s.second); + thermalNoise = tnoise; + } } // Update timestep based on a scalar factor i.e 0.5 for half the timestep diff --git a/src/Simulation.cpp b/src/Simulation.cpp index 72b14532..a9f12766 100644 --- a/src/Simulation.cpp +++ b/src/Simulation.cpp @@ -165,6 +165,9 @@ void Simulation::reduce_step(Input& iObj, Matrix& mObj) { if (!tempMinOut) iObj.argMin = tempMinOut; results.xVector.clear(); results.timeAxis.clear(); + for (auto& i : mObj.sourcegen) { + i.clearMisc(); + } } void Simulation::setup_b( @@ -191,7 +194,7 @@ void Simulation::setup_b( // Handle current sources handle_cs(mObj, step, i); // Handle resistors - handle_resistors(mObj); + handle_resistors(mObj, step); // Handle inductors handle_inductors(mObj, factor); // Handle capacitors @@ -226,15 +229,29 @@ void Simulation::handle_cs(Matrix &mObj, double &step, const int &i) { } } -void Simulation::handle_resistors(Matrix &mObj) { +void Simulation::handle_resistors(Matrix &mObj, double &step) { for (const auto &j : mObj.components.resistorIndices) { auto &temp = std::get(mObj.components.devices.at(j)); NodeConfig &nc = temp.indexInfo.nodeConfig_; if(nc == NodeConfig::POSGND) { + if (temp.thermalNoise) { + b_.at(temp.indexInfo.posIndex_.value()) -= + temp.thermalNoise.value().value(step); + } temp.pn1_ = (x_.at(temp.indexInfo.posIndex_.value())); } else if(nc == NodeConfig::GNDNEG) { + if (temp.thermalNoise) { + b_.at(temp.indexInfo.negIndex_.value()) += + temp.thermalNoise.value().value(step); + } temp.pn1_ = (-x_.at(temp.indexInfo.negIndex_.value())); } else { + if (temp.thermalNoise) { + b_.at(temp.indexInfo.posIndex_.value()) -= + temp.thermalNoise.value().value(step); + b_.at(temp.indexInfo.negIndex_.value()) += + temp.thermalNoise.value().value(step); + } temp.pn1_ = (x_.at(temp.indexInfo.posIndex_.value()) - x_.at(temp.indexInfo.negIndex_.value())); } @@ -311,10 +328,24 @@ void Simulation::handle_jj( auto &temp = std::get(mObj.components.devices.at(j)); const auto &model = temp.model_; if(temp.indexInfo.posIndex_ && !temp.indexInfo.negIndex_) { + if (temp.thermalNoise) { + b_.at(temp.indexInfo.posIndex_.value()) -= + temp.thermalNoise.value().value(step); + } temp.pn1_ = (x_.at(temp.indexInfo.posIndex_.value())); } else if(!temp.indexInfo.posIndex_ && temp.indexInfo.negIndex_) { + if (temp.thermalNoise) { + b_.at(temp.indexInfo.negIndex_.value()) += + temp.thermalNoise.value().value(step); + } temp.pn1_ = (-x_.at(temp.indexInfo.negIndex_.value())); } else { + if (temp.thermalNoise) { + b_.at(temp.indexInfo.posIndex_.value()) -= + temp.thermalNoise.value().value(step); + b_.at(temp.indexInfo.negIndex_.value()) += + temp.thermalNoise.value().value(step); + } temp.pn1_ = (x_.at(temp.indexInfo.posIndex_.value()) - x_.at(temp.indexInfo.negIndex_.value())); } diff --git a/src/Transient.cpp b/src/Transient.cpp index fb587c3a..073a3c23 100644 --- a/src/Transient.cpp +++ b/src/Transient.cpp @@ -74,10 +74,10 @@ void Transient::identify_simulation( tObj.tstop(1E-9); tObj.prstart(0); } - // If user provided time step is larger than 0.25ps junction will fail - if (tObj.tstep() > 0.25E-12) { - tObj.tstep(0.25E-12); - } + //// If user provided time step is larger than 0.25ps junction will fail + //if (tObj.tstep() > 0.25E-12) { + // tObj.tstep(0.25E-12); + //} // Also if PSTEP is smaller than TSTEP if (tObj.tstep() > tObj.prstep()) { // Reduce TSTEP to match PRSTEP diff --git a/src/josim.cpp b/src/josim.cpp index b04a7779..86242f5b 100644 --- a/src/josim.cpp +++ b/src/josim.cpp @@ -47,7 +47,7 @@ int main(int argc, // Identify the simulation parameters Transient::identify_simulation(iObj.controls, iObj.transSim); // Add noise (if any) - Noise::add_noise_sources(iObj); + //Noise::add_noise_sources(iObj); // Create matrix object Matrix mObj; // Create the matrix in csr format From 2522abf6128d440f4c1aadf7a595994853164b7a Mon Sep 17 00:00:00 2001 From: JoeyDelp Date: Mon, 6 Dec 2021 12:48:22 +0200 Subject: [PATCH 07/15] uninitialized needsTR_ to wrong value --- include/JoSIM/BasicComponent.hpp | 2 +- include/JoSIM/Matrix.hpp | 4 ++-- include/JoSIM/TransmissionLine.hpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/JoSIM/BasicComponent.hpp b/include/JoSIM/BasicComponent.hpp index 08f0647f..37ac01db 100644 --- a/include/JoSIM/BasicComponent.hpp +++ b/include/JoSIM/BasicComponent.hpp @@ -27,7 +27,7 @@ namespace JoSIM { class IndexInfo { public: int_o posIndex_, negIndex_, currentIndex_; - NodeConfig nodeConfig_; + NodeConfig nodeConfig_ = NodeConfig::GND; }; class MatrixInfo { diff --git a/include/JoSIM/Matrix.hpp b/include/JoSIM/Matrix.hpp index 9676d579..9e40c1d1 100644 --- a/include/JoSIM/Matrix.hpp +++ b/include/JoSIM/Matrix.hpp @@ -18,7 +18,7 @@ namespace JoSIM { class Matrix { private: std::vector nodeConfig, nodeConfig2; - bool needsTR_; + bool needsTR_ = true; public: AnalysisType analysisType = AnalysisType::Phase; std::vector sourcegen; @@ -28,7 +28,7 @@ namespace JoSIM { std::unordered_map nm; nodeconnections nc; std::unordered_set lm; - int branchIndex; + int branchIndex = 0; std::vector nz; std::vector ci, rp; std::vector relevantTraces; diff --git a/include/JoSIM/TransmissionLine.hpp b/include/JoSIM/TransmissionLine.hpp index 42b1f125..e5c67e0a 100644 --- a/include/JoSIM/TransmissionLine.hpp +++ b/include/JoSIM/TransmissionLine.hpp @@ -60,7 +60,7 @@ namespace JoSIM { double n1_1_ = 0.0, n1_2_ = 0.0, n2_1_ = 0.0, n2_2_ = 0.0; double nk_1_ = 0.0, nk_2_ = 0.0, nk1_1_ = 0.0, nk1_2_ = 0.0, nk2_1_ = 0.0, nk2_2_ = 0.0; - int timestepDelay_ = 0.0; + int timestepDelay_ = 0; TransmissionLine( const std::pair& s, const NodeConfig& ncon, From 66b734af7b58bb801d4a68269335efbbc985256f Mon Sep 17 00:00:00 2001 From: JoeyDelp Date: Wed, 8 Dec 2021 13:38:41 +0200 Subject: [PATCH 08/15] Less agressive time step reduction --- src/Matrix.cpp | 2 +- src/Simulation.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Matrix.cpp b/src/Matrix.cpp index 7aea8917..d6d6fa02 100644 --- a/src/Matrix.cpp +++ b/src/Matrix.cpp @@ -363,7 +363,7 @@ void Matrix::handle_mutual_inductance(Input& iObj) { } void Matrix::reduce_step(Input& iObj) { - iObj.transSim.tstep(iObj.transSim.tstep() / 5); + iObj.transSim.tstep(iObj.transSim.tstep() / 2); nodeConfig.clear(); nodeConfig2.clear(); Components newComponents; diff --git a/src/Simulation.cpp b/src/Simulation.cpp index a9f12766..bfe51dd1 100644 --- a/src/Simulation.cpp +++ b/src/Simulation.cpp @@ -151,7 +151,7 @@ void Simulation::trans_sim(Matrix &mObj) { } void Simulation::reduce_step(Input& iObj, Matrix& mObj) { - iObj.transSim.tstep(iObj.transSim.tstep() / 5); + iObj.transSim.tstep(iObj.transSim.tstep() / 2); bool tempMinOut = iObj.argMin; if (!iObj.argMin) iObj.argMin = true; Matrix newmObj; From 1e18c28468d7094e038e9071173f5d45e081a78f Mon Sep 17 00:00:00 2001 From: JoeyDelp Date: Wed, 8 Dec 2021 15:32:48 +0200 Subject: [PATCH 09/15] Fix need TR initialization --- include/JoSIM/Simulation.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/JoSIM/Simulation.hpp b/include/JoSIM/Simulation.hpp index f61906fa..e6ccb75e 100644 --- a/include/JoSIM/Simulation.hpp +++ b/include/JoSIM/Simulation.hpp @@ -35,7 +35,7 @@ namespace JoSIM { JoSIM::AnalysisType atyp_; bool minOut_; bool needsLU_; - bool needsTR_; + bool needsTR_ = true; bool startup_; double stepSize_, prstep_, prstart_; int simOK_; From 77c52939e53eb7fe1b8a2295848767b883b5df23 Mon Sep 17 00:00:00 2001 From: JoeyDelp Date: Thu, 9 Dec 2021 11:11:11 +0200 Subject: [PATCH 10/15] Cleared noise source misc vector at the incorrect place. --- src/Simulation.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Simulation.cpp b/src/Simulation.cpp index bfe51dd1..f715bae1 100644 --- a/src/Simulation.cpp +++ b/src/Simulation.cpp @@ -157,6 +157,9 @@ void Simulation::reduce_step(Input& iObj, Matrix& mObj) { Matrix newmObj; mObj = newmObj; // Create the matrix in csr format + for (auto& i : mObj.sourcegen) { + i.clearMisc(); + } mObj.create_matrix(iObj); find_relevant_traces(iObj, mObj); //// Dump expanded Netlist since it is no longer needed @@ -165,9 +168,6 @@ void Simulation::reduce_step(Input& iObj, Matrix& mObj) { if (!tempMinOut) iObj.argMin = tempMinOut; results.xVector.clear(); results.timeAxis.clear(); - for (auto& i : mObj.sourcegen) { - i.clearMisc(); - } } void Simulation::setup_b( From c4d5a9c074caddb9a5dff1c596f91c2587a211b7 Mon Sep 17 00:00:00 2001 From: JoeyDelp Date: Thu, 9 Dec 2021 12:19:41 +0200 Subject: [PATCH 11/15] Fixed in line parameter expansions. --- src/Misc.cpp | 8 +++++--- src/Parameters.cpp | 46 +++++++++++++++++++--------------------------- 2 files changed, 24 insertions(+), 30 deletions(-) diff --git a/src/Misc.cpp b/src/Misc.cpp index 5a44f6bb..34165690 100644 --- a/src/Misc.cpp +++ b/src/Misc.cpp @@ -96,9 +96,11 @@ tokens_t Misc::tokenize( } // If trim spaces is enabled if (trimSpaces) { - // Remove trailing, leading and duplicate spaces between tokens - tokens.back() = - std::regex_replace(tokens.back(), std::regex("^ +| +$|( ) +"), "$1"); + if (!tokens.empty()) { + // Remove trailing, leading and duplicate spaces between tokens + tokens.back() = + std::regex_replace(tokens.back(), std::regex("^ +| +$|( ) +"), "$1"); + } } lastPos = pos + 1; ++counter; diff --git a/src/Parameters.cpp b/src/Parameters.cpp index 133da87e..775e602b 100644 --- a/src/Parameters.cpp +++ b/src/Parameters.cpp @@ -480,41 +480,33 @@ void JoSIM::expand_inline_parameters( Errors::parsing_errors( ParsingErrors::INVALID_DECLARATION, Misc::vector_to_string(s.first)); } - // Create a temporary vector to split the token on '{' - tokens_t temp = - Misc::tokenize(s.first.at(oPos.value()), "{", true, true, 1); - // Erase the original token containing the '{' - s.first.erase(s.first.begin() + oPos.value()); - // Insert at the previous token position the temporary vector - s.first.insert(s.first.begin() + oPos.value(), temp.begin(), temp.end()); - // If the emporary token is of size 2. e.g. "td={4" becomes [td=][4] - if (temp.size() == 2) { - // Increment the position to the begining of the expression - oPos = oPos.value() + 1; + if (cPos.value() != oPos.value()) { + s.first.at(oPos.value()) = Misc::vector_to_string( + tokens_t{ s.first.begin() + oPos.value(), + s.first.begin() + cPos.value() + 1 }, ""); + s.first.erase(s.first.begin() + oPos.value() + 1, + s.first.begin() + cPos.value() + 1); } - // Split the closing parenthesis into tokens on '}' - temp = - Misc::tokenize(s.first.at(cPos.value()), "}", true, true, 1); - // Erase the original closing token - s.first.erase(s.first.begin() + cPos.value()); - // Insert the temporary vector at the original position - s.first.insert(s.first.begin() + cPos.value(), temp.begin(), temp.end()); - // Parse the identified expression - double value = parse_param( - Misc::vector_to_string(tokens_t(s.first.begin() + oPos.value(), - s.first.begin() + cPos.value()), ""), parameters, s.second, false); + tokens_t temp = Misc::tokenize(s.first.at(oPos.value()), "{}", true, true, 2); + double value = parse_param(temp.back(), parameters, s.second, false); // If the returned value is not NaN - if (!std::isnan(value)) { + if (std::isnan(value)) { // Complain of invalid parameter expression Errors::parsing_errors( ParsingErrors::UNIDENTIFIED_PART, Misc::vector_to_string(s.first)); } // Erase the expression part of the tokens s.first.erase( - s.first.begin() + oPos.value(), s.first.begin() + cPos.value()); - // Insert the double value in the place of the expression - s.first.insert( - s.first.begin() + oPos.value(), Misc::precise_to_string(value)); + s.first.begin() + oPos.value(), s.first.begin() + oPos.value() + 1); + if (temp.size() > 1) { + // Insert the double value in the place of the expression + s.first.insert(s.first.begin() + oPos.value(), + Misc::vector_to_string( + tokens_t{ temp.front(), Misc::precise_to_string(value) }, "")); + } else { + s.first.insert(s.first.begin() + oPos.value(), + Misc::precise_to_string(value)); + } } // If an expression closing was found if (cPos) { From cb50508e460d693ea7da6ba0556d6bc3d116cbb7 Mon Sep 17 00:00:00 2001 From: JoeyDelp Date: Thu, 9 Dec 2021 13:54:21 +0200 Subject: [PATCH 12/15] Fix noreturn issue with model parameters not recognised --- include/JoSIM/Errors.hpp | 6 +++--- src/Errors.cpp | 6 +++--- src/Model.cpp | 9 ++++++--- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/include/JoSIM/Errors.hpp b/include/JoSIM/Errors.hpp index 0686b306..cf6bf0c5 100644 --- a/include/JoSIM/Errors.hpp +++ b/include/JoSIM/Errors.hpp @@ -189,10 +189,10 @@ namespace JoSIM { static void control_errors( ControlErrors errorCode, string_o message = std::nullopt); - [[noreturn]] static void model_errors( + static void model_errors( ModelErrors errorCode, string_o message = std::nullopt); - static void matrix_errors( + [[noreturn]] static void matrix_errors( MatrixErrors errorCode, string_o message = std::nullopt); [[noreturn]] static void misc_errors( @@ -210,7 +210,7 @@ namespace JoSIM { static void output_errors( OutputErrors errorCode, string_o message = std::nullopt); - static void netlist_errors( + [[noreturn]] static void netlist_errors( NetlistErrors errorCode, string_o message = std::nullopt); static void verbosity_errors( diff --git a/src/Errors.cpp b/src/Errors.cpp index e8444544..e8d48556 100644 --- a/src/Errors.cpp +++ b/src/Errors.cpp @@ -480,7 +480,7 @@ void Errors::control_errors(ControlErrors errorCode, string_o message) { } } -[[noreturn]] void Errors::model_errors(ModelErrors errorCode, +void Errors::model_errors(ModelErrors errorCode, string_o message) { std::string formattedMessage = "Model\n"; switch (errorCode) { @@ -507,7 +507,7 @@ void Errors::control_errors(ControlErrors errorCode, string_o message) { } } -void Errors::matrix_errors(MatrixErrors errorCode, string_o message) { +[[noreturn]] void Errors::matrix_errors(MatrixErrors errorCode, string_o message) { std::string formattedMessage = "Matrix\n"; switch (errorCode) { case MatrixErrors::NON_SQUARE: @@ -790,7 +790,7 @@ void Errors::parsing_errors(ParsingErrors errorCode, string_o message) { } } -void Errors::netlist_errors(NetlistErrors errorCode, string_o message) { +[[noreturn]] void Errors::netlist_errors(NetlistErrors errorCode, string_o message) { std::string formattedMessage = "Netlist\n"; switch (errorCode) { case NetlistErrors::NO_SUCH_NODE: diff --git a/src/Model.cpp b/src/Model.cpp index e96fc711..a0c8c409 100644 --- a/src/Model.cpp +++ b/src/Model.cpp @@ -2,8 +2,8 @@ // This code is licensed under MIT license (see LICENSE for details) #include "JoSIM/Model.hpp" -#include "JoSIM/Misc.hpp" #include "JoSIM/Errors.hpp" +#include "JoSIM/Misc.hpp" #include "JoSIM/TypeDefines.hpp" using namespace JoSIM; @@ -34,10 +34,11 @@ void Model::parse_model( Errors::model_errors( ModelErrors::BAD_MODEL_DEFINITION, Misc::vector_to_string(s.first)); } + double value = 0.0; // Loop through the parameter tokens for (int i = 0; i < tokens.size(); i += 2) { // Every even odd token should be a value (otherwise complain) - double value = parse_param(tokens.at(i + 1), p, s.second); + value = parse_param(tokens.at(i + 1), p, s.second); if (std::isnan(value)) { Errors::model_errors( ModelErrors::BAD_MODEL_DEFINITION, Misc::vector_to_string(s.first)); @@ -73,7 +74,9 @@ void Model::parse_model( } else { // Incompatible parameter Errors::model_errors(ModelErrors::PARAM_TYPE_ERROR, - Misc::vector_to_string(s.first)); + Misc::vector_to_string( + tokens_t{ Misc::vector_to_string(s.first), + "\nThe parameter: ", tokens.at(i) })); } } From ca38c66c0caaa33ba946b71a0b4bdf734507dd36 Mon Sep 17 00:00:00 2001 From: JoeyDelp Date: Thu, 9 Dec 2021 13:56:35 +0200 Subject: [PATCH 13/15] Fixed netlist errors noreturn clause --- src/Errors.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Errors.cpp b/src/Errors.cpp index e8d48556..ff99530b 100644 --- a/src/Errors.cpp +++ b/src/Errors.cpp @@ -803,6 +803,11 @@ void Errors::parsing_errors(ParsingErrors errorCode, string_o message) { formattedMessage += message.value_or("") + "\n"; formattedMessage += "Please check for any disconnections in the netlist"; throw std::runtime_error(formattedMessage); + default: + formattedMessage += + "Unknown netlist error: " + message.value_or("") + "\n"; + formattedMessage += "Please contact the developer."; + throw std::runtime_error(formattedMessage); } } From b81331987e3e4895a226b55d07a838bc84fa13a2 Mon Sep 17 00:00:00 2001 From: JoeyDelp Date: Wed, 15 Dec 2021 13:49:43 +0200 Subject: [PATCH 14/15] Documents update --- docs/syntax.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/syntax.md b/docs/syntax.md index c56a7081..ed4cbb4f 100644 --- a/docs/syntax.md +++ b/docs/syntax.md @@ -67,7 +67,7 @@ The value of a capacitor is in Farad. ### Josephson Junction (JJ) -**B**Label $N^{+}$ $N^{-}$ ** **MODEL** [area=<**AREA**\>] [ic=<**IC**>] +**B**Label $N^{+}$ $N^{-}$ ** **MODEL** [area=<**AREA**\>] [ic=<**IC**>] [temp=<**TEMP**>] [neb=<**FREQ**>] A Josephson junction is a two terminal device but could also be defined with a third non-connected node to allow compatibility with WRspice. This node is not used in any way in JoSIM. @@ -75,6 +75,8 @@ The Josephson junction requires specification of a model name which can be defin When **AREA** or **IC** is not specified then an area=1 is used as default. +The temp and neb commands have the same descriptions as for the resistor. + #### Model This model control has the following syntax @@ -249,12 +251,14 @@ The most important of these control commands is the transient simulation command ### Transient Analysis -**.tran** $T_{STEP}$ $T_{STOP}$ [$P_{START}$ [$P_{STEP}$]] +**.tran** $T_{STEP}$ $T_{STOP}$ [$P_{START}$ [$P_{STEP}$]] DST This generates a simulation that runs from 0 until $T_{STOP}$. The amount simulation steps that will be performed is $n=\frac{T_{STOP}}{T_{STEP}}$. $P_{START}$ indicates at what point output will start printing. $P_{STEP}$ sets the size of the print steps. This has to be larger or equal to $T_{STEP}$. +DST disables the start-up time. The start-up time is a period calculated internally by the simulator in which components settle. This is equivalent to the few picoseconds from when a circuit initially receives power (power switch flipped). + ### Subcircuits Subcircuits allow subdivision and reuse of smaller circuits within a larger design. When wrapped in a subcircuit control devices are allowed to have the same label names as specified elsewhere in the netlist as the subcircuit completely isolates them. From 8870a25534c689a357096cdc2e01d38e8abd8855 Mon Sep 17 00:00:00 2001 From: JoeyDelp Date: Wed, 15 Dec 2021 15:11:48 +0200 Subject: [PATCH 15/15] README update --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0b5c09df..3453844e 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,9 @@ Referencing: ## Changelog ### v2.6 -- WIP +- Full Johnson-Nyquist temperature noise for Resistors and Resistive branch of RCSJ model +- Phi-junction model with verified Pi junction results +- Various bug fixes and code clean up ### v2.5.8 - Updated KLU to a 64-bit version capable of handling non-zero count larger than the maximum value of a 32-bit integer.