ocs/000755 000765 000000 00000000000 12564412616 012107 5ustar00carlowheel000000 000000 ocs/COPYING000644 000765 000000 00000043141 11601145313 013131 0ustar00carlowheel000000 000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ocs/DESCRIPTION000644 000765 000000 00000000501 12564411021 013576 0ustar00carlowheel000000 000000 Name: OCS Version: 0.1.5 Date: 2015-08-7 Author: Carlo de Falco, Culpo Massimiliano, Marco Merlin Maintainer: Carlo de Falco, Culpo Massimiliano Title: Octave Circuit Simulator Description: Package for solving DC and transient electrical circuit equations Depends: octave (>= 3.0.0), odepkg Autoload: no License: GPLv2+ ocs/doc/000755 000765 000000 00000000000 12564412616 012654 5ustar00carlowheel000000 000000 ocs/INDEX000644 000765 000000 00000001012 12564412603 012667 0ustar00carlowheel000000 000000 OCS >> Octave Circuit Simulator Matrix Assembly Functions asm_initialize_system asm_build_system Netlist Parsing Functions prs_iff prs_spice Time Stepping Functions tst_backward_euler tst_daspk tst_theta_method tst_odepkg Non Linear Solvers nls_stationary nls_newton_raphson UTiLity Functions utl_plot_by_name utl_sbn_server SuBNet Function Library Mcapacitors Mcurrentsources Mdiode Minductors Mnmosfet Mpmosfet Mresistors Mshichmanhodgesmosfet Mvoltagesources Mpdesympnjunct ocs/inst/000755 000765 000000 00000000000 12564412616 013064 5ustar00carlowheel000000 000000 ocs/NEWS000644 000765 000000 00000000722 12564410772 012610 0ustar00carlowheel000000 000000 Summary of important user-visible changes for ocs 0.1.5: ------------------------------------------------------------------- ** Fixed use of obsolete LaTeX commands in some documents (bug #45638). ** Added missing functions to INDEX. Summary of important user-visible changes for ocs 0.1.4: ------------------------------------------------------------------- ** Fixed a few incompatibilities with Octave 4.0 and warnings about use of deprecated syntax. ocs/PKG_ADD000644 000765 000000 00000001115 12546656656 013137 0ustar00carlowheel000000 000000 dirlist = {"utl", "asm", "tst", "nls", "prs", "sbn"}; dirname = fileparts (canonicalize_file_name (mfilename ("fullpath"))); if (! exist (fullfile (dirname, "inst"), "dir")) ## Run this if the package is installed for ii=1:length (dirlist) addpath (fullfile (dirname, "..", dirlist{ii}), "-end") endfor else ## Run this if we are testing the package without installation for ii=1:length(dirlist) addpath (fullfile (dirname, "inst", dirlist{ii})) addpath (fullfile (dirname, "src")) endfor endif warning ("off", "Octave:fopen-file-in-path"); clear dirlist dirname ocs/PKG_DEL000644 000765 000000 00000001023 12025300074 013115 0ustar00carlowheel000000 000000 dirlist = {"utl", "asm", "tst", "nls", "prs", "sbn"}; dirname = fileparts (canonicalize_file_name (mfilename ("fullpath"))); if (! exist (fullfile (dirname, "inst"), "dir")) ## Run this if the package is installed for ii=1:length (dirlist) rmpath (fullfile (dirname, "..", dirlist{ii})) endfor else ## Run this if we are testing the package without installation for ii=1:length (dirlist) rmpath (fullfile (dirname, "inst", dirlist{ii})) endfor rmpath (fullfile (dirname, "src")) endif clear dirlist dirname ocs/README000644 000765 000000 00000001754 11601145313 012762 0ustar00carlowheel000000 000000 OCS - A Circuit Simulator for Octave ------------------------------------------------------------------- Copyright (C) 2006 Carlo de Falco This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see the file LICENSE); if not, write to the Free Software Foundation, Inc. 51 Franklin Street - Fifth Floor Boston MA 02110-1301 USA For more information, you may also contact me by email at carlo.defalco@gmail.com I would also appreciate it if you drop me a line just to say that you are you using the program ocs/src/000755 000765 000000 00000000000 12564412616 012676 5ustar00carlowheel000000 000000 ocs/src/Makefile000644 000765 000000 00000000200 11334212227 014314 0ustar00carlowheel000000 000000 OCTFILES:=Mshichmanhodgesmosfet.oct all: $(OCTFILES) %.oct: %.cc mkoctfile $< clean: -rm -f *.o core octave-core *.oct *~ ocs/src/Mshichmanhodgesmosfet.cc000644 000765 000000 00000035330 12564411634 017527 0ustar00carlowheel000000 000000 /* Copyright (C) 2009 Massimiliano Culpo This file is part of: OCS - A Circuit Simulator for Octave OCS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see the file LICENSE); if not, see . author: Massimiliano Culpo */ #include #include #include #include #include using namespace std; /* Print parameters */ void print_parameters(double rd, double W, double L, double mu0, double Vth, double Cox, double Cgs, double Cgd, double Cgb, double Csb, double Cdb, double Tshift) { octave_stdout << "PARAMETER TABLE: Simplified Shichman-Hodges MOS-FET\n\n"; octave_stdout << "Name\t\tValue\n"; octave_stdout << "rd\t\t" << rd << "\n" ; octave_stdout << "W\t\t" << W << "\n" ; octave_stdout << "L\t\t" << L << "\n" ; octave_stdout << "mu0\t\t" << mu0 << "\n" ; octave_stdout << "Vth\t\t" << Vth << "\n" ; octave_stdout << "Cox\t\t" << Cox << "\n" ; octave_stdout << "Cgs\t\t" << Cgs << "\n" ; octave_stdout << "Cgd\t\t" << Cgd << "\n" ; octave_stdout << "Cgb\t\t" << Cgb << "\n" ; octave_stdout << "Csb\t\t" << Csb << "\n" ; octave_stdout << "Cdb\t\t" << Cdb << "\n" ; octave_stdout << "Tshift\t\t" << Tshift << "\n" ; octave_stdout << "\n\n"; } /* Print computed values */ void print_values(double gm, double gd, double ids, double didT, double P, double dPdT, double dPdvgs, double dPdvds) { octave_stdout << "COMPUTED VALUES TABLE: Simplified Shichman-Hodges MOS-FET\n\n"; octave_stdout << "Name\t\tValue\n"; octave_stdout << "gm\t\t" << gm << "\n" ; octave_stdout << "gd\t\t" << gd << "\n" ; octave_stdout << "ids\t\t" << ids << "\n" ; octave_stdout << "didT\t\t" << didT << "\n" ; octave_stdout << "P\t\t" << P << "\n" ; octave_stdout << "dPdT\t\t" << dPdT << "\n" ; octave_stdout << "dPdvgs\t\t" << dPdvgs << "\n" ; octave_stdout << "dPdvds\t\t" << dPdvds << "\n" ; octave_stdout << "\n\n"; } /* Set the parameters of the simplified Shichman-Hodges MOS-FET */ void set_parameters(ColumnVector parameters, string_vector parameternames, double *rd, double* W, double* L, double* mu0, double* Vth, double* Cox, double* Cgs, double* Cgd, double* Cgb, double* Csb, double* Cdb, double* Tshift) { octave_idx_type nnames = parameternames.numel (); octave_idx_type niter = 0; //FIXME: it should be better to use Octave_map for parameters while (niter < nnames) { if (parameternames[niter] == "rd") *rd = parameters(niter); else if (parameternames[niter] == "W") *W = parameters(niter); else if (parameternames[niter] == "L") *L = parameters(niter); else if (parameternames[niter] == "mu0") *mu0 = parameters(niter); else if (parameternames[niter] == "Vth") *Vth = parameters(niter); else if (parameternames[niter] == "Cox") *Cox = parameters(niter); else if (parameternames[niter] == "Cgs") *Cgs = parameters(niter); else if (parameternames[niter] == "Cgd") *Cgd = parameters(niter); else if (parameternames[niter] == "Cgb") *Cgb = parameters(niter); else if (parameternames[niter] == "Csb") *Csb = parameters(niter); else if (parameternames[niter] == "Cdb") *Cdb = parameters(niter); else if (parameternames[niter] == "Tshift") *Tshift = parameters(niter); else warning ((string("Mshichmanhodgesmosfet: unknown parameter").append (parameternames[niter])).c_str ()); niter++; } } /* Compute values for n-mos model*/ void nmos(ColumnVector extvar, double mu0, double Cox, double W, double L, double Vth, double rd, double Tshift, double *gm, double *gd, double *ids, double *didT, double *P, double *dPdT, double *dPdvgs, double *dPdvds) { double vg = extvar(0); // V-gate double vs = extvar(1); // V-source double vd = extvar(2); // V-drain double vb = extvar(3); // V-bulk double T = extvar(4); // Temperature double k = mu0*Cox*pow((T + Tshift)/300.0,-3.0/2.0)*W/L; double dkdT = mu0*Cox*W*(-3.0/2)*std::pow((T + Tshift)/300.0,-5.0/2.0 )*(1.0/300.0)/L; double vgs = vg - vs; double vds = vd - vs; if (vgs < Vth) { *gm = 0; *gd = 1/rd; *ids = vds*(*gd); *didT = 0; } else if ( ( (vgs-Vth)>= vds ) && (vds>=0)) { *ids = k*((vgs-Vth)*vds - std::pow(vds,2)/2 ) + vds/rd; *gm = k*vds; *gd = k*(vgs-Vth-vds) + (1/rd); *didT = dkdT*((vgs-Vth)*vds-(std::pow(vds,2))/2); } else if (((vgs-Vth)>=(vds))&&(vds<0)) { *gm = 0; *gd = 1/rd; *ids = vds*(*gd); *didT= 0; } else // (i.e. if 0 <= vgs-vth <= vds) { *ids = (k/2)*std::pow((vgs-Vth),2) + vds/rd; *gm = k*(vgs-Vth); *gd = 1/rd; *didT= (dkdT/(2))*std::pow((vgs-Vth),2); } *P = -(*ids)*vds; *dPdT = -(*didT)*vds; *dPdvgs = -(*gm)*vds; *dPdvds = -((*gd)*vds + (*ids)); } /* Compute values for p-mos model*/ void pmos(ColumnVector extvar, double mu0, double Cox, double W, double L, double Vth, double rd, double Tshift, double *gm, double *gd, double *ids, double *didT, double *P, double *dPdT, double *dPdvgs, double *dPdvds) { double vg = extvar(0); // V-gate double vs = extvar(1); // V-source double vd = extvar(2); // V-drain double vb = extvar(3); // V-bulk double T = extvar(4); // Temperature double k = - mu0*Cox*std::pow((T + Tshift)/300.0,-3.0/2.0)*W/L; double dkdT = - mu0*Cox*W*(-3.0/2.0)*std::pow((T + Tshift)/300.0,-5.0/2.0 )*(1.0/300.0)/L; double vgs = vg - vs; double vds = vd - vs; if (vgs > Vth) { *gm = 0; *gd = 1/rd; *ids = vds*(*gd); *didT = 0; } else if ( ( (vgs-Vth)<= vds ) && (vds<=0)) { *ids = k*((vgs-Vth)*vds - std::pow(vds,2)/2 ) + vds/rd; *gm = k*vds; *gd = k*(vgs-Vth-vds) + (1/rd); *didT = dkdT*((vgs-Vth)*vds-(std::pow(vds,2))/2); } else if (((vgs-Vth)<=(vds))&&(vds>0)) { *gm = 0; *gd = 1/rd; *ids = vds*(*gd); *didT= 0; } else // (i.e. if 0 <= vgs-vth <= vds) { *ids = (k/2)*std::pow((vgs-Vth),2) + vds/rd; *gm = k*(vgs-Vth); *gd = 1/rd; *didT= (dkdT/(2))*std::pow((vgs-Vth),2); } *P = -(*ids)*vds; *dPdT = -(*didT)*vds; *dPdvgs = -(*gm)*vds; *dPdvds = -((*gd)*vds + (*ids)); } DEFUN_DLD(Mshichmanhodgesmosfet,args,nargout, "-*- texinfo -*-\n\ \n\ @deftypefn{Loadable Function} @\n\ {[@var{a},@var{b},@var{c}]=} Mshichmanhodgesmosfet@\n\ (@var{string}, @var{parameters}, @var{parameternames}, @\n\ @var{extvar},@var{intvar},@var{t})\n\ \n\ SBN file implementing Schichman-Hodges MOSFETs model.\n\ \n\ @var{string} is used to select among models. Possible models are:\n\ \n\ @enumerate\n\ @item @var{string} = NMOS (Simplified Shichman-Hodges n-MOSFET)\n\ @item @var{string} = PMOS (Simplified Shichman-Hodges p-MOSFET)\n\ @end enumerate\n\ \n\ Parameters for all the above models are:\n\ @itemize\n\ @item rd -> parasitic resistance between drain and source\n\ @item W -> MOSFET width\n\ @item L -> channel length\n\ @item mu0 -> reference value for mobility\n\ @item Vth -> threshold voltage\n\ @item Cox -> oxide capacitance\n\ @item Cgs -> gate-source capacitance\n\ @item Cgd -> gate-drain capacitance\n\ @item Cgb -> gate-bulk capacitance\n\ @item Csb -> source-bulk capacitance\n\ @item Cdb -> drain-bulk capacitance\n\ @item Tshift -> shift for reference temperature on MOSFETs\n\ @end itemize\n\ See the @cite{IFF file format specifications} for details about\n\ the output structures.\n\ \n\ @seealso{prs_iff,asm_initialize_system,asm_build_system}\n\ \n\ @end deftypefn\n \ ") { octave_value_list retval; // Contain returned values octave_idx_type nargin = args.length(); /* Input parameters */ string eltype; ColumnVector parameters; string_vector parameternames; ColumnVector extvar; ColumnVector intvar(5,0.0); double t; /* Model parameters */ double rd; double W,L; double mu0,Vth,Cox; double Cgs,Cgd,Cgb,Csb,Cdb; double Tshift; /* Model variables */ double vg; // V-gate double vs; // V-source double vd; // V-drain double vb; // V-bulk double T ; // Temperature double Qgb;// Charges double Qgs; double Qgd; double Qsb; double Qdb; double gm; // Conductances et similia double gd; double ids; double didT; double P; double dPdT; double dPdvgs; double dPdvds; /* Output values */ Matrix a(10,10,0.0), b(10,10,0.0); ColumnVector c(10,0.0); /* Check and retrieve input */ if (nargin != 6) error("Mshichmanhodgesmosfet: wrong number of input parameters.\n"); else { /* Retrieve input parameters */ // Type of MOS-FET if (args(0).is_string()) eltype = args(0).string_value(); else error("Mshichmanhodgesmosfet: argument #1 is expected to be a string.\n"); // Parameters and parameter names if (args(1).length() == args(2).length()) { parameters = args(1).column_vector_value(); parameternames = args(2).all_strings(); } else error("Mshichmanhodgesmosfet: parameters and parameternames are expected to have the same length.\n"); // External pins if (args(3).length() == 5) extvar = args(3).column_vector_value(); else error("Mshichmanhodgesmosfet: five external values expected.\n"); // Internal variables if (args(4).is_empty()) {} else if (args(4).length() == 5) intvar = args(4).column_vector_value(); else error("Mshichmanhodgesmosfet: five internal values expected.\n"); // Time point if (args(5).is_real_scalar()) t = args(5).double_value(); else error("Mshichmanhodgesmosfet: double type value expected as time instant.\n"); } if (!error_state) { //FIXME: create enum of cases and use switch? if (eltype == "NMOS") { //FIXME: change parameters to a single map or Octave_map /* Default n-MOS parameters*/ rd = 1e6; W = 1; L = 1; mu0 = 1e-5; Vth = .5; Cox = 1e-9; Cgb = Cox; Cgs = .1*Cox; Cgd = .1*Cox; Csb = .1*Cox; Cdb = .1*Cox; Tshift = 0; /* Overwrite parameters */ set_parameters(parameters, parameternames, &rd, &W, &L, &mu0, &Vth, &Cox, &Cgs, &Cgd, &Cgb, &Csb, &Cdb, &Tshift); //FIXME: debug //print_parameters(rd, W, L, mu0, Vth, Cox, Cgs, Cgd, Cgb, Csb, Cdb, Tshift); /* Compute model conductance and capacitance */ nmos(extvar,mu0,Cox,W,L,Vth,rd,Tshift,&gm,&gd,&ids,&didT,&P,&dPdT,&dPdvgs,&dPdvds); //FIXME: debug //print_values(gm, gd, ids, didT, P, dPdT, dPdvgs, dPdvds); /* Assemble output values*/ vg = extvar(0); // V-gate vs = extvar(1); // V-source vd = extvar(2); // V-drain vb = extvar(3); // V-bulk T = extvar(4); // Temperature Qgb = intvar(0); Qgs = intvar(1); Qgd = intvar(2); Qsb = intvar(3); Qdb = intvar(4); //FIXME: probably a better way to initialize Matrix exist! /* Dynamic matrix (constant) */ a(0,5) = 1; a(0,6) = 1; a(0,7) = 1; a(1,6) = -1; a(1,8) = 1; a(2,7) = -1; a(2,9) = 1; a(3,5) = -1; a(3,8) = -1; a(3,9) = -1; /* Algebraic part (non-linear) */ b(1,0) = -gm; b(1,1) = (gm+gd); b(1,2) = -gd; b(1,4) = -didT; b(2,0) = gm; b(2,1) = -(gm+gd); b(2,2) = gd; b(2,4) = didT; b(4,0) = dPdvgs; b(4,1) = -(dPdvgs+dPdvds); b(4,2) = dPdvds; b(4,4) = dPdT; b(5,0) = Cgb; b(5,3) = -Cgb; b(6,0) = Cgs; b(6,1) = -Cgs; b(7,0) = Cgd; b(7,2) = -Cgd; b(8,1) = Csb; b(8,3) = -Csb; b(9,2) = Cdb; b(9,3) = -Cdb; b(5,5) = -1; b(6,6) = -1; b(7,7) = -1; b(8,8) = -1; b(9,9) = -1; /* Residual */ c(0) = 0; c(1) = -ids; c(2) = ids; c(4) = P; c(5) = Cgb*(vg - vb) - Qgb; c(6) = Cgs*(vg - vs) - Qgs; c(7) = Cgd*(vg - vd) - Qgd; c(8) = Csb*(vs - vb) - Qsb; c(9) = Cdb*(vd - vb) - Qdb; /* Return values */ retval(0) = octave_value(a); retval(1) = octave_value(b); retval(2) = octave_value(c); } else if (eltype == "PMOS") { /* Default p-MOS parameters*/ rd = 1e6; W = 1; L = 1; mu0 = 1e-5; Vth = -.5; Cox = 1e-9; Cgb = Cox; Cgs = .1*Cox; Cgd = .1*Cox; Csb = .1*Cox; Cdb = .1*Cox; Tshift = 0; /* Overwrite parameters */ set_parameters(parameters, parameternames, &rd, &W, &L, &mu0, &Vth, &Cox, &Cgs, &Cgd, &Cgb, &Csb, &Cdb, &Tshift); /* Compute model conductance and capacitance */ pmos(extvar,mu0,Cox,W,L,Vth,rd,Tshift,&gm,&gd,&ids,&didT,&P,&dPdT,&dPdvgs,&dPdvds); /* Assemble output values*/ vg = extvar(0); // V-gate vs = extvar(1); // V-source vd = extvar(2); // V-drain vb = extvar(3); // V-bulk T = extvar(4); // Temperature Qgb = intvar(0); Qgs = intvar(1); Qgd = intvar(2); Qsb = intvar(3); Qdb = intvar(4); /* Dynamic matrix (constant) */ a(0,5) = 1; a(0,6) = 1; a(0,7) = 1; a(1,6) = -1; a(1,8) = 1; a(2,7) = -1; a(2,9) = 1; a(3,5) = -1; a(3,8) = -1; a(3,9) = -1; /* Algebraic part (non-linear) */ b(1,0) = -gm; b(1,1) = (gm+gd); b(1,2) = -gd; b(1,4) = -didT; b(2,0) = gm; b(2,1) = -(gm+gd); b(2,2) = gd; b(2,4) = didT; b(4,0) = dPdvgs; b(4,1) = -(dPdvgs+dPdvds); b(4,2) = dPdvds; b(4,4) = dPdT; b(5,0) = Cgb; b(5,3) = -Cgb; b(6,0) = Cgs; b(6,1) = -Cgs; b(7,0) = Cgd; b(7,2) = -Cgd; b(8,1) = Csb; b(8,3) = -Csb; b(9,2) = Cdb; b(9,3) = -Cdb; b(5,5) = -1; b(6,6) = -1; b(7,7) = -1; b(8,8) = -1; b(9,9) = -1; /* Residual */ c(0) = 0; c(1) = -ids; c(2) = ids; c(4) = P; c(5) = Cgb*(vg - vb) - Qgb; c(6) = Cgs*(vg - vs) - Qgs; c(7) = Cgd*(vg - vd) - Qgd; c(8) = Csb*(vs - vb) - Qsb; c(9) = Cdb*(vd - vb) - Qdb; /* Return values */ retval(0) = octave_value(a); retval(1) = octave_value(b); retval(2) = octave_value(c); } else error("Mshichmanhodgesmosfet: unknown element type.\n"); } return (retval); } ocs/inst/asm/000755 000765 000000 00000000000 12564412616 013644 5ustar00carlowheel000000 000000 ocs/inst/nls/000755 000765 000000 00000000000 12564412616 013660 5ustar00carlowheel000000 000000 ocs/inst/prs/000755 000765 000000 00000000000 12564412616 013670 5ustar00carlowheel000000 000000 ocs/inst/sbn/000755 000765 000000 00000000000 12564412616 013646 5ustar00carlowheel000000 000000 ocs/inst/tst/000755 000765 000000 00000000000 12564412616 013676 5ustar00carlowheel000000 000000 ocs/inst/utl/000755 000765 000000 00000000000 12564412616 013670 5ustar00carlowheel000000 000000 ocs/inst/utl/utl_plot_by_name.m000644 000765 000000 00000003510 11533543616 017401 0ustar00carlowheel000000 000000 ## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## @deftypefn{Function File} {} utl_plot_by_name(@var{t},@var{out}, @ ## @var{outstruct},@var{namelist}) ## ## Select by name some elements of the state vector of the system described ## by @var{outstruct} and plot their dynamics over the time interval ## @var{t}. ## ## @var{namelist} should contain the list of names of the variables ## to plot. ## @var{out} should be the output of a transient simulation over the ## time interval @var{t} ## ## @seealso{tst_backward_euler,tst_daspk,tst_theta_method,tst_odepkg,prs_iff} ## ## @end deftypefn function utl_plot_by_name (t, out, outstruct, namelist) if (nargin != 4) error ("utl_plot_by_name: wrong number of input parameters.") endif nn = length (outstruct.namesn); leg = {}; ileg = 0; for ip = 1:nn for in = 1:length (namelist) if (strcmp (namelist{in},outstruct.namess{ip})) plot (t, out(outstruct.namesn(ip), :), sprintf("%d", mod (in+1, 6) + 1)); leg{++ileg} = outstruct.namess{ip}; hold on endif endfor endfor legend (leg{:}); hold off endfunctionocs/inst/utl/utl_sbn_server.m000644 000765 000000 00000004375 11334211056 017100 0ustar00carlowheel000000 000000 ## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## @deftypefn{Function File} {} utl_sbn_server(@var{port}) ## Listen for socket connections on port @var{port}, read a command @ ## and return the corresponding output to the socket. ## @end deftypefn function utl_sbn_server (portnum) QUITMESSAGE = "quit UTLsbnserver"; CONFIRMMESSAGE = "confirmed"; ## CREATE THE SOCKET AND WAIT FOR CONNECTIONS s = socket(AF_INET, SOCK_STREAM, 0); if s < 0 error("cannot create socket\n"); end if bind(s, portnum) < 0 error("bind failed\n"); end if listen(s, 1) < 0 error("listen failed\n"); end ##MAIN LOOP while 1 ##ACCEPT CONNECTIONS c = accept(s); if c < 0 error("connection error") end ## READ COMMANDS FROM THE SOCKET msg = readstring (c) ##IF CLIENT SENT SHUTDOWN MESSAGE EXIT if strcmp (msg,QUITMESSAGE) printf("client requested server shutdown, goodbye!\n"); disconnect(c); disconnect(s); break end ##EXECUTE COMMANDS FROM THE CLIENT [A,B,C] = eval(msg); ##SEND OUTPUT TO THE CLIENT str = [ sprintf("%17g ",A) "\n" sprintf("%17g ",B)... "\n" sprintf("%17g ",C) "\n"] send(c,str); ##END CONNECTION disconnect(c); end disconnect(s); endfunction function msg = readstring (c) BUFFER_SIZE = 255; msg = ''; read = BUFFER_SIZE; while read >= BUFFER_SIZE newmsg = char(recv(c, BUFFER_SIZE)); read = length(newmsg) msg = [ msg newmsg]; end endfunction ocs/inst/tst/tst_backward_euler.m000644 000765 000000 00000012067 11523470260 017717 0ustar00carlowheel000000 000000 ## Copyright (C) 2006,2007,2008,2011 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} {[@var{out},@var{niter}] =} @ ## tst_backward_euler(@var{cirstruct},@var{x},@var{t},@var{tol},@ ## @var{maxit},@var{pltvars},@var{verbosity},@var{dae_fun}) ## ## Perform a transient simulation of the system described by ## @var{cirstruct} over the time interval @var{t} using the backward ## Euler algorithm. ## ## The initial value for the state vector is computed by solving a ## steady state problem at @var{t}(1), with starting guess @var{x}. ## ## @var{tol} and @var{maxit} are parameters passed to ## @code{nls_newton_raphson}. ## ## The output @var{out} will contain the value of the state vector at ## each point of @var{t}. ## ## The optional parameter @var{verbosity} controls the amount of ## output produced: ## ## @itemize @minus ## @item if verbosity(1) != 0, information on the progress ## of the algorithm are output at runtime ## @item if verbosity(2) != 0, the plot of the variables whose names ## are listed in @var{pltvars} is ## produced after the computation ## @end itemize ## ## For special purposes one may need to pass modified jacobian and ## residual functions. This can be done via the cell array of function ## handles @var{dae_fun}. ## ## Such functions should have the same input and output ## parameter list as the default sub-functions ## TSTBWEFUNJAC0,TSTBWEFUNRES0, TSTBWEFUNJAC,TSTBWEFUNRES. ## ## The optional output @var{niter} returns the number of Newton iterations ## needed to reach convergence. ## ## @seealso{tst_daspk,tst_theta_method,tst_odepkg,nls_newton_raphson} ## ## @end deftypefn function [out, varargout] = tst_backward_euler (outstruct, x, t, tol, maxit, pltvars, verbosity, dae_fun) ## Check input ## FIXME: add input check! if ((nargin < 6) || (nargin > 8)) error ("tst_backward_euler: wrong number of input parameters."); endif if ~exist ("verbosity") verbosity = [0,0]; elseif (length (verbosity) < 2) verbosity(2) = 0; endif out = zeros (rows (x), columns (t)); out(:,1) = x; if nargout > 1 niter = zeros (length(t),1); endif if (verbosity(1)) fprintf (1, "Initial value.\n"); endif [A0, B, C] = asm_initialize_system (outstruct, x); if (nargin > 8) JAC = @(x) dae_fun{1} (outstruct,x,t(1),B); RES = @(x) dae_fun{2} (outstruct,x,t(1),B,C); [out(:,1), ii, resnrm] = nls_newton_raphson (x, RES, JAC, tol, maxit, verbosity(1)); else [out(:,1),ii] = nls_stationary (outstruct, x, tol, maxit); endif if (nargout > 1) niter(1) = ii; endif for it = 2:length (t) if (verbosity(1)) fprintf (1,"Timestep #%d.\n",it); endif if nargin > 8 JAC = @(x) dae_fun{3} (outstruct, x, t(it-1), t(it), A0, B); RES = @(x) dae_fun{4} (outstruct, x, out(:,it-1), t(it-1), t(it), A0, B, C); else JAC = @(x,A1,Jac,res) TSTBWEFUNJAC1(outstruct, x, t(it-1), t(it), A0, B, A1, Jac, res); RES = @(x,A1,Jac,res) TSTBWEFUNRES1(outstruct, x, out(:,it-1), t(it-1), t(it), A0, B, C, A1, Jac, res); UPDT = @(x) TSTBWEFUNUP1 (outstruct, x, t(it)); endif [out(:,it),ii,resnrm] = nls_newton_raphson (out(:,it-1), RES, JAC, tol, maxit, verbosity(1), UPDT); if nargout > 1 niter(it) = ii; endif if (verbosity(2)) utl_plot_by_name (t(1:it), out(:,1:it), outstruct, pltvars); drawnow (); endif ## Stop at runtime ## FIXME: maintain this part? if exist("~/.stop_ocs","file") printf("stopping at timestep %d\n",it); unix("rm ~/.stop_ocs"); break end endfor if nargout > 1 varargout{1} = niter; endif endfunction ## Jacobian for transient problem function lhs = TSTBWEFUNJAC1 (outstruct, x, t0, t1, A0, B, A1, Jac, res) DT = t1-t0; if (nargin < 9) [A1, Jac, res] = asm_build_system (outstruct, x, t1); endif lhs = ((A0+A1)/DT + B + Jac); endfunction ## Residual for transient problem function rhs = TSTBWEFUNRES1 (outstruct, x, xold, t0, t1, A0, B, C, A1, Jac, res) DT = t1-t0; if ( nargin < 11 ) [A1, Jac, res] = asm_build_system (outstruct, x, t1); endif rhs = (res + C + B*x + (A0+A1)*(x-xold)/DT); endfunction ## Update for transient problem function update = TSTBWEFUNUP1 (outstruct, x, t1) [A1, Jac, res] = asm_build_system (outstruct, x, t1); update = {A1, Jac, res}; endfunctionocs/inst/tst/tst_daspk.m000644 000765 000000 00000010341 11523470456 016047 0ustar00carlowheel000000 000000 ## Copyright (C) 2006,2007,2008,2011 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} {[@var{out}] =} tst_daspk @ ## (@var{cirstruct},@var{x},@var{t},@var{tol},@var{maxit},@ ## @var{pltvars},@var{verbosity},@var{daskopts},@var{dae_fun}); ## ## Perform a transient simulation of the system described by ## @var{cirstruct} over the time interval @var{t} using @code{daspk}. ## ## The initial value for the state vector is computed by solving a ## steady state problem at @var{t}(1), with starting guess @var{x}. ## ## @var{tol} and @var{maxit} are parameters passed to ## @code{nls_newton_raphson}. ## ## The output @var{out} will contain the value of the state vector ## at each point of @var{t}. ## ## Extra options for @code{daspk} can be passed as name/value pairs in ## the cellarray @var{daskopts}. ## ## The optional parameter @var{verbosity} controls the amount of ## output produced: ## ## @itemize @minus ## @item if verbosity(1) != 0, information on the progress ## of the algorithm are output at runtime ## @item if verbosity(2) != 0, the plot of the variables whose names ## are listed in @var{pltvars} is ## produced after the computation ## @end itemize ## ## For special purposes one may need to pass modified jacobian and ## residual functions. This can be done via the cell array of function ## handles @var{dae_fun}. ## ## Such functions should have the same input and output ## parameter list as the default sub-functions ## TSTBWEFUNJAC0,TSTBWEFUNRES0, TSTBWEFUNJAC,TSTBWEFUNRES. ## ## @seealso{tst_backward_euler,tst_odepkg,tst_theta_method,nls_newton_raphson,daspk} ## ## @end deftypefn function [out] = tst_daspk (outstruct, x, t, tol, maxit, pltvars, verbosity, daspkopts, dae_fun) ## FIXME: add input check! if ((nargin < 6) || (nargin > 9)) error ("tst_daspk: wrong number of input parameters."); endif if (! exist ("verbosity")) verbosity = [0, 0]; elseif (length (verbosity) < 2) verbosity(2) = 0; endif if (verbosity(1)) fprintf (1, "initial value:\n"); endif daspk_options ("print initial condition info",1); daspk_options ("maximum order",2); daspk_options ("initial step size",t(2)-t(1)); daspk_options ("relative tolerance",1e-3); if (nargin > 8) for ii = 1:2:length (daspkopts) daspk_options (daspkopts{ii}, daspkopts{ii+1}); endfor endif [A0, B, C] = asm_initialize_system (outstruct, x); if (nargin > 9) JAC = @(x) dae_fun{1} (outstruct, x, t(1), B); RES = @(x) dae_fun{2} (outstruct, x, t(1), B, C); [x, ii, resnrm] = nls_newton_raphson (x, RES, JAC, tol, maxit, verbosity); else [out(:,1), ii] = nls_stationary (outstruct, x, tol, maxit); endif if (nargin > 9) JAC = @(x) dae_fun{3} (outstruct, x, t(1), B); RES = @(x) dae_fun{4} (outstruct, x, t(1), B, C); else JAC = @(x,xdot,t,c) TSTDASPKFUNJAC (outstruct, x, xdot, A0, B, t, c); RES = @(x,xdot,t) TSTDASPKFUNRES (outstruct, x, xdot, A0, B, C, t); endif [out, xdot, istate, msg] = daspk ({RES,JAC}, out(:,1), zeros (size (x)), t); out = out.'; if (verbosity(2)) utl_plot_by_name (t, out, outstruct, pltvars) endif endfunction ## Jacobian for transient problem function lhs = TSTDASPKFUNJAC (outstruct, x, xdot, A0, B, t, c) [A1, Jac, res] = asm_build_system (outstruct, x, t); lhs = (c*(A0+A1) + B + Jac); endfunction ## Residual for transient problem function rhs = TSTDASPKFUNRES (outstruct, x, xdot, A0, B, C, t) [A1, Jac, res] = asm_build_system (outstruct, x, t); rhs = (A0+A1)*xdot + B*x + C + res; endfunctionocs/inst/tst/tst_odepkg.m000644 000765 000000 00000012223 12207456226 016216 0ustar00carlowheel000000 000000 ## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} {[@var{out}, [@var{tout}]] =} tst_odepkg @ ## (@var{cirstruct},@var{x},@var{t},@var{tol},@var{maxit},@ ## @var{pltvars},@var{solver},@var{odestruct},@var{verbosity}); ## ## Perform a transient simulation of the system described by ## @var{cirstruct} over the time interval @var{t} using the @code{odepkg} DAE ## solver specified in @var{solver}. ## ## Pssible values for @var{solver} are @code{ode2r}, @code{ode5r}, ## @code{oders} or @code{odesx}. ## ## The initial value for the state vector is computed by solving a ## steady state problem at @var{t}(1), with starting guess @var{x}. ## ## @var{tol} and @var{maxit} are parameters passed to @code{nls_newton_raphson}. ## ## If one output is requested @var{out} will contain the value of the state vector ## at each point of @var{t}. ## ## If two outputs are requested @var{out} will contain the value of the state vector ## at each point of @var{tout}. ## ## Extra options for options for the solver can be passed to the solver ## via @var{odestruct}. ## ## The optional parameter @var{verbosity} controls the amount of ## output produced: ## ## @itemize @minus ## @item if verbosity(1) != 0, information on the progress ## of the algorithm are output at runtime ## @item if verbosity(2) != 0, the plot of the variables whose names ## are listed in @var{pltvars} is ## produced after the computation ## @end itemize ## ## @seealso{tst_backward_euler,tst_theta_method,tst_daspk,nls_newton_raphson,odepkg,odeset,@ ## ode2r,ode5r,oders,odesx} ## ## @end deftypefn function [out, tout] = tst_odepkg (outstruct,x,t,tol,maxit,... pltvars,solver,verbosity,odestruct) ## Check input ## FIXME: add input check! if ((nargin < 7) || (nargin > 9)) error("tst_odepkg:wrong number of input parameters"); endif if ~exist("verbosity") verbosity = [0,0]; elseif length(verbosity)<2 verbosity(2) =0; endif if(verbosity(1)) fprintf(1,"initial value:\n"); endif if ~exist("odestruct") odestruct = odeset(); endif [A0,B,C] = asm_initialize_system(outstruct,x); [out(:,1),ii] = nls_stationary(outstruct,x,tol,maxit); JAC = @(t, x) TSTODEPKGFUNJAC(outstruct, x, A0, B, t); RES = @(t, x) TSTODEPKGFUNRES(outstruct, x, A0, B, C, t); MASS= @(t, x) TSTODEPKGFUNMASS(outstruct, x, A0, t); odestruct = odeset(odestruct,"Jacobian", JAC); odestruct = odeset(odestruct,"Mass",MASS(0,x)); odestruct = odeset(odestruct,"RelTol", 1e-6,"AbsTol",1e6*eps, "MaxStep", max(diff(t)),"InitialStep",(diff(t))(1)); if verbosity(2) odestruct = odeset(odestruct, "OutputFcn", @(t, y, flag) plotfun(t, y, flag, outstruct, pltvars) ); endif [tout, out] = feval( solver, RES, t([1 end]), x, odestruct); if (nargout < 2) out = interp1(tout, out, t).'; endif endfunction function [varargout] = plotfun (vt, vy, vflag, outstruct, pltvars) ## this function is a modified version of odeplot distributed ## with odepkg (c) Thomas Treichl %# No input argument check is done for a higher processing speed persistent vfigure; persistent vtold; persistent vyold; persistent vcounter; if (strcmp (vflag, "init")) %# Nothing to return, vt is either the time slot [tstart tstop] %# or [t0, t1, ..., tn], vy is the inital value vector 'vinit' vfigure = figure; vtold = vt(1,1); vyold = vy(:,1); vcounter = 1; elseif (isempty (vflag)) %# Return something in varargout{1}, either false for 'not stopping %# the integration' or true for 'stopping the integration' vcounter = vcounter + 1; figure (vfigure); vtold(vcounter,1) = vt(1,1); vyold(:,vcounter) = vy(:,1); utl_plot_by_name(vtold, vyold, outstruct, pltvars); drawnow; varargout{1} = false; elseif (strcmp (vflag, "done")) %# Cleanup has to be done, clear the persistent variables because %# we don't need them anymore clear ("vfigure","vtold","vyold","vcounter"); endif endfunction ## Jacobian for transient problems function lhs = TSTODEPKGFUNJAC(outstruct,x,A0,B,t) [A1,Jac,res] = asm_build_system(outstruct,x,t); lhs = ( B + Jac); endfunction function lhs = TSTODEPKGFUNMASS(outstruct,x,A0,t) [A1,Jac,res] = asm_build_system(outstruct,x,t); lhs = -(A0+A1); endfunction ## Residual for transient problems function rhs = TSTODEPKGFUNRES(outstruct,x,A0,B,C,t) [A1,Jac,res] = asm_build_system(outstruct,x,t); rhs = B*x + C + res; endfunctionocs/inst/tst/tst_theta_method.m000644 000765 000000 00000010627 12207456226 017420 0ustar00carlowheel000000 000000 ## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} {[@var{out},@var{niter}] =} tst_theta_method @ ## (@var{cirstruct},@var{x},@var{t},@var{tol},@ ## @var{maxit},@var{theta},@var{pltvars},@ ## @var{verbosity}); ## ## Perform a transient simulation of the system described by ## @var{cirstruct} over the time interval @var{t} using the ## theta-method with parameter @var{theta}. ## ## The initial value for the state vector is computed by solving a ## steady state problem at @var{t}(1), with starting guess @var{x}. ## ## @var{tol} and @var{maxit} are parameters passed to ## @code{nls_newton_raphson}. ## ## The output @var{out} will contain the value of the state vector at ## each point of @var{t}. ## ## The optional parameter @var{verbosity} controls the amount of ## output produced: ## ## @itemize @minus ## @item if verbosity(1) != 0, information on the progress ## of the algorithm are output at runtime ## @item if verbosity(2) != 0, the plot of the variables whose names ## are listed in @var{pltvars} is ## produced after the computation ## @end itemize ## ## The optional output @var{niter} returns the number of Newton iterations ## needed to reach convergence. ## ## @seealso{tst_backward_euler,tst_daspk,tst_odepkg,nls_newton_raphson} ## ## @end deftypefn function [out, varargout] = tst_theta_method(outstruct,x,t,tol,maxit,... theta,pltvars,verbosity) ## Check input ## FIXME: add input check! if ((nargin < 7) || (nargin > 8)) error("tst_theta_method: wrong number of input parameters."); endif if ~exist("verbosity") verbosity = [0,0]; elseif length(verbosity)<2 verbosity(2) = 0; endif out = zeros(rows(x),columns(t)); out(:,1) = x; if nargout > 1 niter = zeros(length(t),1); endif if (verbosity(1)) fprintf(1,"Initial value.\n"); endif [A0,B,C] = asm_initialize_system(outstruct,x); [out(:,1),ii] = nls_stationary(outstruct,x,tol,maxit); if nargout > 1 niter(1) = ii; endif for it=2:length(t) if(verbosity) fprintf(1,"Timestep #%d.\n",it); endif [A1old,Jacold,resold] = asm_build_system(outstruct, out(:,it-1), t(it-1)); JAC = @(x,A1,Jac,res) TSTTHETAFUNJAC1(outstruct, x, t(it-1), t(it), A0, B, theta, A1, Jac, res); RES = @(x,A1,Jac,res) TSTTHETAFUNRES1(outstruct, x, out(:,it-1), t(it-1), t(it), A0, B, C, resold, theta, A1, Jac, res); UPDT = @(x) TSTTHETAFUNUP1 (outstruct, x, t(it)); [out(:,it),ii,resnrm] = nls_newton_raphson(out(:,it-1),RES,JAC,... tol, maxit,verbosity(1),... UPDT); if nargout > 1 niter(it) = ii; endif if (verbosity(2)) utl_plot_by_name(t(1:it),out(:,1:it),outstruct,pltvars); pause(.1); endif if exist("~/.stop_ocs","file") break end endfor if nargout > 1 varargout{1} = niter; endif endfunction ## Jacobian for transient problem function lhs = TSTTHETAFUNJAC1(outstruct, x, t0, t1, A0, B, theta, A1, Jac, res) DT = t1-t0; if ( nargin < 10 ) [A1,Jac,res] = asm_build_system(outstruct,x,t1); endif lhs = ( (A0+A1)/DT + theta*(B + Jac) ); endfunction ## Residual for transient problem function rhs = TSTTHETAFUNRES1(outstruct, x, xold, t0, t1, A0, B, C, resold, theta, A1, Jac, res) DT = t1-t0; if ( nargin < 13 ) [A1,Jac,res] = asm_build_system(outstruct,x,t1); endif rhs = ( (A1+A0)*(x-xold)/DT + theta * (res + C + B*x) + (1-theta) * (resold + C + B*xold) ); endfunction ## Update for transient problem function update = TSTTHETAFUNUP1(outstruct,x,t1) [A1,Jac,res] = asm_build_system(outstruct,x,t1); update = {A1,Jac,res}; endfunction ocs/inst/sbn/Mcapacitors.m000644 000765 000000 00000011126 11334211056 016257 0ustar00carlowheel000000 000000 ## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} @ ## {[@var{a},@var{b},@var{c}]=} Mcapacitors(@var{string},@var{parameters},@ ## @var{parameternames},@var{extvar},@var{intvar},@var{t}) ## ## SBN file implementing models for capacitors. ## ## @var{string} is used to select among models. Parameters are listed ## as inner items. Possible models are: ## ## @enumerate ## @item @var{string} = "LIN" (Linear Capacitor) ## @itemize @minus ## @item C -> capacitance value ## @end itemize ## @item @var{string} = "MULTICAP" (Multipole Capacitor) ## @itemize @minus ## @item C -> capacitance values ## @end itemize ## @item @var{string} = "PDE_NMOS" (Drift-Diffusion PDE NMOS capacitor) ## @itemize @minus ## @item tbulk -> bulk thickness ## @item tox -> oxide thickness ## @item Nnodes -> number of nodes of 1D grid ## @item Na -> bulk doping ## @item toll -> absolute tolerance ## @item maxit -> max iterations number ## @item Area -> device area ## @end itemize ## @end enumerate ## ## See the @cite{IFF file format specifications} for details about ## the output structures. ## ## @seealso{prs_iff,asm_initialize_system,asm_build_system} ## @end deftypefn function [a,b,c] = Mcapacitors(string,parameters,parameternames,extvar,intvar,t) if isempty(intvar) intvar = 0; endif switch string ##LCR part case "LIN" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor a = [0 0 1; 0 0 -1; 0 0 0]; b = [0 0 0;0 0 0;-C C 1]; c = [0 0 0]'; break case "MULTICAP" n = length(extvar); C = reshape(parameters,n,n); a = [zeros(n) eye(n); zeros(n) zeros(n)]; b = [zeros(n) zeros(n); -C eye(n)]; c = [zeros(2*n,1)]'; break ##NLC part case "PDE_NMOS" constants tbulk = 1.5e-6; tox = 90e-9; len = tbulk + tox; Nnodes = 300; Na=1e21; toll = 1e-10; maxit = 1000; Area = 1e-12; for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor Vg = extvar(1) - extvar(2); q = intvar(1); [Q,C]=Mnmoscap(tbulk,tox,Area,Vg,Na,Nnodes,toll,maxit); a = [0 0 1; 0 0 -1; 0 0 0]; b = [0 0 0;0 0 0;C -C -1]; c = [0 0 Q-q]'; break otherwise error (["unknown section:" string]) endswitch endfunction ## Non-linear 1D MOS structure. ## FIXME: requires SECS1D!!! function [Q,C]=Mnmoscap(tbulk,tox,Area,Vg,Na,Nnodes,toll,maxit); constants Nelements = Nnodes - 1; len = tox+tbulk; x = linspace(0,len,Nnodes)'; sinodes = find(x<=tbulk); Nsinodes = length(sinodes); NelementsSi = Nsinodes-1; D = - Na* ones(Nsinodes,1); pp = Na ; p = pp* ones(Nsinodes,1); n = (ni^2)./p; Fn = 0*n; Fp = 0*n; V = -Phims + Vg * ones(Nnodes,1); V(sinodes) = Fn + Vth*log(n/ni); ## Scaling xs = len; ns = norm(D,inf); Din = D/ns; Vs = Vth; xin = x/xs; nin = n/ns; pin = p/ns; Vin = V/Vs; Fnin = (Fn - Vs * log(ni/ns))/Vs; Fpin = (Fp + Vs * log(ni/ns))/Vs; l2 = (Vs*esio2)/(q*ns*xs^2)* ones(Nelements,1); l2(1:NelementsSi) = (Vs*esi)/(q*ns*xs^2); ## Solution of Nonlinear Poisson equation [V,nout,pout,res,niter] = DDGnlpoisson (xin,sinodes,Vin,nin,... pin,Fnin,Fpin,Din,l2,... toll,maxit,0); L = Ucomplap(xin,Nnodes,[],Nelements,l2); C22 = L(end,end); C12 = L(2:end-1,end); C11 = L(2:end-1,2:end-1); drdv = zeros(Nnodes,1); drdv(sinodes) = nout + pout; coeff = zeros(Nelements,1); coeff(1:NelementsSi) = 1; M = Ucompmass(xin,Nnodes,[],[],drdv,coeff); C = C22 - C12'*((C11+M(2:end-1,2:end-1))\C12); Q =(C12'*V(2:end-1)+C22*V(end)); ## Descaling C = Area*C*(q*ns*xs/Vs); Q = Area*Q*(q*ns*xs); endfunctionocs/inst/sbn/Mcurrentsources.m000644 000765 000000 00000006661 12207456226 017237 0ustar00carlowheel000000 000000 ## Copyright (C) 2006,2007,2008 Carlo de Falco, Culpo Massimiliano ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## author culpo@math.uni-wuppertal.de ## -*- texinfo -*- ## ## @deftypefn{Function File} @ ## {[@var{a},@var{b},@var{c}]=}Mcurrentsources(@var{string},@var{parameters},@ ## @var{parameternames},@var{extvar},@var{intvar},@var{t}) ## ## SBN file implementing models for current sources. ## ## @var{string} is used to select among models. Parameters are listed ## as inner items. Possible models are: ## ## @enumerate ## @item @var{string} = "DC" (Static indipendent current source) ## @itemize @minus ## @item I -> Current source value ## @end itemize ## @item @var{string} = "VCCS" (Voltage controlled current source) ## @itemize @minus ## @item K -> Control parameter ## @end itemize ## @item @var{string} = "sinwave" (Sinusoidal indipendent current ## source) ## @itemize @minus ## @item shift -> mean value of sinusoidal input ## @item Ampl -> amplitude of sinusoidal wave ## @item f -> frequency of sinusoidal wave ## @item delay -> delay of sinusoidal wave ## @end itemize ## @item @var{string} = "VCPS" (Voltage controlled power source) ## @itemize @minus ## @item K -> Control parameter ## @end itemize ## @end enumerate ## ## See the @cite{IFF file format specifications} for details about ## the output structures. ## ## @seealso{prs_iff,asm_initialize_system,asm_build_system} ## @end deftypefn function [a,b,c] = Mcurrentsources (string,parameters,parameternames,extvar,intvar,t) switch string ## LCR part case "DC" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor a = zeros(2); b = a; c = [I -I]'; break case "VCCS" ## Voltage controlled current source K = 1; for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor a = zeros(4); b = [0 0 K -K;... 0 0 -K K;... 0 0 0 0;... 0 0 0 0]; c = zeros(4,1); ## NLC part case "sinwave" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor I = shift+Ampl * sin(2*pi*(t+delay)*f ); a = zeros(2); b = a; c = [I -I]'; break case "VCPS" ## Voltage controlled power source K = 1; for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor dv = extvar(3) - extvar(4); I = K*(dv^2); dIdv = 2*K*dv; a = zeros(4); b = [0 0 dIdv -dIdv;... 0 0 -dIdv dIdv;... 0 0 0 0;... 0 0 0 0]; c = [I -I 0 0]; otherwise error (["unknown section:" string]) endswitch endfunction ocs/inst/sbn/Mdiode.m000644 000765 000000 00000006004 11334211056 015212 0ustar00carlowheel000000 000000 ## Copyright (C) 2006,2007,2008 Massimiliano Culpo, Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: culpo@math.uni-wuppertal.de, Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} @ ## {[@var{a},@var{b},@var{c}]=}Mdiode(@var{string},@var{parameters},@ ## @var{parameternames},@var{extvar},@var{intvar},@var{t}) ## ## SBN file implementing models for diodes. ## ## @var{string} is used to select among models. Parameters are listed ## as inner items. Possible models are: ## ## @itemize @minus ## @item @var{string} = "simple" (Usual exponential diode model) ## @itemize @minus ## @item Is -> reverse current ## @item Vth -> thermal voltage ## @item Rpar -> parasitic resistance ## @end itemize ## @item @var{string} = "PDEsymmetric" (Drift-Diffusion PDE model) ## @itemize @minus ## @item len -> diode length ## @item Nnodes -> number of nodes of 1D grid ## @item Dope -> doping (abrupt and symmetric) ## @item toll -> absolute tolerance ## @item maxit -> max iterations number ## @item Area -> device area ## @end itemize ## @end itemize ## ## See the @cite{IFF file format specifications} for details about ## the output structures. ## ## @seealso{prs_iff,asm_initialize_system,asm_build_system} ## @end deftypefn function [a,b,c] = Mdiode (string,parameters,parameternames,extvar,intvar,t) switch string case "simple" Is = 1e-14; Vth = 2.5e-2; Rpar = 1e12; for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor vp = extvar(1); vm = extvar(2); I = Is*(exp((vp - vm)/Vth) -1 ) + (vp - vm)/Rpar; geq = Is*exp((vp - vm)/Vth)/Vth + 1/Rpar; a = zeros(2); b = [geq -geq; -geq geq]; c = [I ; -I] ; break case "PDEsymmetric" len = 1e-6; Nnodes = 100; Dope=1e23; toll = 1e-5; maxit = 100; ptoll = 1e-10; pmaxit = 100; Area = 1e-10; for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor vp = extvar(1); vm = extvar(2); [I,g] = Mpdesympnjunct (len,Dope,vp-vm,Area,Nnodes,toll,maxit,ptoll,pmaxit); a = zeros(2); b = [g -g; -g g]; c = [I ; -I] ; break otherwise error(["unknown section:" string]) endswitch endfunction ocs/inst/sbn/Minductors.m000644 000765 000000 00000003766 11334211056 016154 0ustar00carlowheel000000 000000 ## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} @ ## {[@var{a},@var{b},@var{c}]=}Minductors(@var{string},@var{parameters},@ ## @var{parameternames},@var{extvar},@var{intvar},@var{t}) ## ## SBN file implementing models for inductors. ## ## @var{string} is used to select among models. Parameters are listed ## as inner items. Possible models are: ## ## @enumerate ## @item @var{string} = "LIN" (Linear inductor model) ## @itemize @minus ## @item L -> inductance value ## @end itemize ## @end enumerate ## ## See the @cite{IFF file format specifications} for details about ## the output structures. ## ## @seealso{prs_iff,asm_initialize_system,asm_build_system} ## @end deftypefn function [a,b,c] = Minductors (string,parameters,parameternames,extvar,intvar,t) if isempty(intvar) intvar = [0 0]; endif switch string case "LIN" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor phi = intvar(1); jl = intvar(2); a = [0 0 0 0; 0 0 0 0; 0 0 1 0; 0 0 0 0]; b = [0 0 0 1; 0 0 0 -1; -1 1 0 0; 0 0 1 -L]; c = [0 0 0 0]'; otherwise error (["unknown section:" string]) endswitch endfunction ocs/inst/sbn/Mnmosfet.m000644 000765 000000 00000010010 11617232116 015575 0ustar00carlowheel000000 000000 ## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} @ ## {[@var{a},@var{b},@var{c}]=}Mnmosfet(@var{string},@var{parameters},@ ## @var{parameternames},@var{extvar},@var{intvar},@var{t}) ## ## SBN file implementing standard models for n-mosfets. ## ## @var{string} is used to select among models. Parameters are listed ## as inner items. Possible models are: ## ## @enumerate ## @item @var{string} = "simple" (Standard model for MOSFET) ## @itemize @minus ## @item rd -> parasitic resistance between drain and source ## @item k -> k parameter for usual mosfet model ## @item Vth -> threshold voltage ## @end itemize ## @item @var{string} = "lincap" (Adds RC parasitics) ## @itemize @minus ## @item rd -> parasitic resistance between drain and source ## @item k -> k parameter for usual mosfet model ## @item Vth -> threshold voltage ## @item Rs -> parasitic source resistance ## @item Rd -> parasitic drain resistance ## @item Cs -> gate-source capacitance ## @item Cd -> gate-drain capacitance ## @item Cb -> gate-bulk capacitance ## @end itemize ## @end enumerate ## ## See the @cite{IFF file format specifications} for details about ## the output structures. ## ## @seealso{prs_iff,asm_initialize_system,asm_build_system} ## @end deftypefn function [a,b,c]=Mnmosfet(string,parameters,parameternames,extvar,intvar,t) switch string case "simple" rd = 1e6; k = 1e-5; Vth = .5; for ii=1:length(parameternames) eval([parameternames{ii} "=",... num2str(parameters(ii)) " ;"]) endfor vg = extvar(1); vs = extvar(2); vd = extvar(3); vb = extvar(4); vgs = vg-vs; vds = vd-vs; if (vgs < Vth) gm = 0; gd = 1/rd; id = vds*gd; elseif (((vgs-Vth) >= (vds)) && (vds>=0)) id = k*((vgs-Vth)*vds-(vds^2)/2)+vds/rd; gm = k*vds; gd = k*(vgs-Vth-vds)+1/rd; elseif (((vgs-Vth) >= (vds)) && (vds<0)) gm = 0; gd = 1/rd; id = vds*gd; else # (i.e. if 0 <= vgs-vth <= vds) id = (k/(2))*(vgs-Vth)^2+vds/rd; gm = (2*k/(2))*(vgs-Vth); gd = 1/rd; endif a = zeros(4); b = [0 0 0 0; -gm (gm+gd) -gd 0; gm -(gm+gd) gd 0; 0 0 0 0]; c = [0 -id id 0]'; break; case "lincap" ## Default parameter values if isempty(intvar) intvar = zeros(5,1); endif Rs = 1e2; Rd = 1e2; Cs = 1e-15; Cd = 1e-15; Cb = 1e-14; rd = inf; k = 1e-3; Vth = .1; ## parameters given in input for ii=1:length(parameternames) eval([parameternames{ii} "=",... num2str(parameters(ii)) " ;"]) endfor persistent tmpstruct if isempty(tmpstruct) mtdnmos = file_in_path(path,"Mtdnmos.cir"); mtdnmos(end-3:end)=[]; tmpstruct = prs_iff(mtdnmos); endif tmpstruct.NLC.pvmatrix = [k Vth rd]; tmpstruct.LCR(1).pvmatrix = [Rs; Rd]; tmpstruct.LCR(2).pvmatrix = [Cs; Cd; Cb]; [A0,B,C] = asm_initialize_system(tmpstruct,[extvar;intvar]); [A1,Jac,res] = asm_build_system(tmpstruct,[extvar;intvar],t); a = A0+A1; b = B+Jac; c = res + B*[extvar;intvar] + C; break; otherwise error(["unknown option:" string]); endswitch endfunction ocs/inst/sbn/Mpdesympnjunct.m000644 000765 000000 00000006230 11334211056 017032 0ustar00carlowheel000000 000000 ## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} @ ## {[@var{j},@var{g}]=}Mpdesympnjunct@ ## (@var{len}, @var{Dope}, @var{va}, @ ## @var{Area}, @var{Nnodes}, @var{toll}, @var{maxit}, @var{ptoll}, @var{pmaxit}) ## ## INTERNAL FUNCTION: ## ## NOT SUPPOSED TO BE CALLED DIRECTLY BY USERS ## @end deftypefn function [j,g] = Mpdesympnjunct (len,Dope,va,Area,Nnodes,toll,maxit,ptoll,pmaxit) constants x = linspace(0,len,Nnodes)'; xm = mean(x); Nd=Dope; Na=Dope; nn = (Nd + sqrt(Nd^2+4*ni^2))/2; pp = (Na + sqrt(Na^2+4*ni^2))/2; xn = xm+len/10; xp = xm-len/10; D = Nd * (x>xm) - Na * (x<=xm); ## Scaling coefficients xs = len; ns = norm(D,inf); Vs = Vth; us = un; Js = (Area*us*Vs*q*ns/xs); xin = x/xs; gs = Js/Vs; n = nn * (x>=xn) + (ni^2)/pp * (xxp) + pp * (x<=xp); Fn = va*(x<=xm); Fp = Fn; V = (Fn - Vth * log(p/ni)); ## Scaling idata.D = D/ns; idata.un = un/us; idata.up = up/us; idata.tn = inf; idata.tp = inf; idata.l2 = (Vs*esi)/(q*ns*xs^2); idata.nis = ni/ns; idata.n = n/ns; idata.p = p/ns; idata.V = V/Vs; idata.Fn = (Fn - Vs * log(ni/ns))/Vs; idata.Fp = (Fp + Vs * log(ni/ns))/Vs; ## Solution of DD system ## Algorithm parameters sinodes = [1:length(x)]; [idata,it,res] = DDGgummelmap (xin,idata,toll,maxit/2,ptoll,pmaxit,0); [odata,it,res] = DDNnewtonmap (xin,idata,toll,maxit/2,0); DV = diff(odata.V); h = xin(2)-xin(1); Bp = Ubernoulli(DV,1); Bm = Ubernoulli(DV,0); Jn = -odata.un * (odata.n(2:end).*Bp-odata.n(1:end-1).*Bm)/h; Jp = odata.up * (odata.p(2:end).*Bm-odata.p(1:end-1).*Bp)/h; coeff = idata.un.*Umediaarmonica(odata.n); L =- Ucomplap (xin,Nnodes,[],[],coeff); Jn1 = L*odata.Fn; fprintf(1,"jn1=%g\n",Jn1(1)) fprintf(1,"jn=%g\n",Jn(1)) C11 = L(1,1); C1I = L(1,2:end-1); CII = L(2:end-1,2:end-1); Gn = C11 - C1I*(CII\C1I'); Gn = Gn - coeff(1)*(odata.Fn(2)-odata.Fn(1))/h coeff = idata.up.*Umediaarmonica(odata.p); L =- Ucomplap (xin,Nnodes,[],[],coeff); Jp1 = L*odata.Fp; fprintf(1,"jp1=%g\n",Jp1(1)) fprintf(1,"jp=%g\n",Jp(1)) C11 = L(1,1); C1I = L(1,2:end-1); CII = L(2:end-1,2:end-1); Gp = C11 - C1I*(CII\C1I'); Gp = Gp - coeff(1)*(odata.Fp(2)-odata.Fp(1))/h ## Descaling j= -(Jp(1)+Jn(1))*Js g= gs*(Gn+Gp) endfunctionocs/inst/sbn/Mpmosfet.m000644 000765 000000 00000007633 11617232116 015620 0ustar00carlowheel000000 000000 ## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} @ ## {[@var{a},@var{b},@var{c}]=} Mpmosfet(@var{string},@var{parameters},@ ## @var{parameternames},@var{extvar},@var{intvar},@var{t}) ## ## SBN file implementing standard models for p-mosfets. ## ## @var{string} is used to select among models. Parameters are listed ## as inner items. Possible models are: ## ## @enumerate ## @item @var{string} = "simple" (Standard model for MOSFET) ## @itemize @minus ## @item rd -> parasitic resistance between drain and source ## @item k -> k parameter for usual mosfet model ## @item Vth -> threshold voltage ## @end itemize ## @item @var{string} = "lincap" (Adds RC parasitics) ## @itemize @minus ## @item rd -> parasitic resistance between drain and source ## @item k -> k parameter for usual mosfet model ## @item Vth -> threshold voltage ## @item Rs -> parasitic source resistance ## @item Rd -> parasitic drain resistance ## @item Cs -> gate-source capacitance ## @item Cd -> gate-drain capacitance ## @item Cb -> gate-bulk capacitance ## @end itemize ## @end enumerate ## ## See the @cite{IFF file format specifications} for details about ## the output structures. ## ## @seealso{prs_iff,asm_initialize_system,asm_build_system} ## @end deftypefn function [a,b,c]= Mpmosfet (string,parameters,parameternames,extvar,intvar,t) switch string case "simple" rd = 1e6; for ii=1:length(parameternames) eval([parameternames{ii} "=",... num2str(parameters(ii)) " ;"]); endfor vg = extvar(1); vs = extvar(2); vd = extvar(3); vb = extvar(4); vgs = vg-vs; vds = vd-vs; if (vgs > Vth) gm = 0; gd = 1/rd; id = vds*gd; elseif (((vgs-Vth) <= (vds)) && (vds<=0)) id = k*((vgs-Vth)*vds-(vds^2)/2)+vds/rd; gm = k*vds; gd = k*(vgs-Vth-vds)+1/rd; elseif (((vgs-Vth) <= (vds)) && (vds>0)) gm = 0; gd = 1/rd; id = vds*gd; else id = k*(vgs-Vth)^2/2+vds/rd; gm = k*(vgs-Vth); gd = 1/rd; endif a = zeros(4); b = [0 0 0 0; -gm (gm+gd) -gd 0; gm -(gm+gd) gd 0; 0 0 0 0 ]; c =[0 -id id 0]'; break; case "lincap" ## Default parameter values if isempty(intvar) intvar = zeros(5,1); endif Rs = 1e2; Rd = 1e2; Cs = 1e-15; Cd = 1e-15; Cb = 1e-12; rd = inf; k = -1e-3; Vth = -.1; ## parameters given in input for ii=1:length(parameternames) eval([parameternames{ii} "=",... num2str(parameters(ii)) " ;"]) endfor mtdpmos = file_in_path(path,"Mtdpmos.cir"); mtdpmos(end-3:end)=[]; tmpstruct = prs_iff(mtdpmos); tmpstruct.NLC.pvmatrix = [k Vth rd]; tmpstruct.LCR(1).pvmatrix = [Rs; Rd]; tmpstruct.LCR(2).pvmatrix = [Cs; Cd; Cb]; [A0,B,C] = asm_initialize_system(tmpstruct,[extvar;intvar]); [A1,Jac,res] = asm_build_system(tmpstruct,[extvar;intvar],t); a = A0+A1; b = B+Jac; c = res + B*[extvar;intvar] + C; break; otherwise error(["unknown option:" string]); endswitch endfunction ocs/inst/sbn/Mresistors.m000644 000765 000000 00000007246 12546656656 016225 0ustar00carlowheel000000 000000 ## Copyright (C) 2006,2007,2008 Carlo de Falco, Culpo Massimiliano ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## author: culpo@math.uni-wuppertal.de ## -*- texinfo -*- ## ## @deftypefn{Function File} @ ## {[@var{a},@var{b},@var{c}]=}Mresistors(@var{string},@var{parameters},@ ## @var{parameternames},@var{extvar},@var{intvar},@var{t}) ## ## SBN file implementing models for resistors. ## ## @var{string} is used to select among models. Parameters are listed ## as inner items. Possible models are: ## ## @enumerate ## @item @var{string} = "LIN" (Linear resistor) ## @itemize @minus ## @item R -> resistance value ## @end itemize ## @item @var{string} = "THERMAL" (Linear resistor with termal pin) ## @itemize @minus ## @item R0 -> reference resistance value at temperature @code{TNOM} ## @item TC1 -> coefficient for first order Taylor expansion ## @item TC2 -> coefficient for second order Taylor expansion ## @item TNOM -> reference temperature ## @end itemize ## @item @var{string} = "THERMAL1D" (1D Thermal resistor) ## @itemize @minus ## @item L -> length of 1D domain ## @item N -> number of discretized elements ## @item cv -> PDE coefficient for dynamic part ## @item k -> PDE coefficient for diffusion part ## @end itemize ## @end enumerate ## ## See the @cite{IFF file format specifications} for details about ## the output structures. ## ## @seealso{prs_iff,asm_initialize_system,asm_build_system} ## @end deftypefn function [a,b,c] = Mresistors (string, parameters, parameternames, extvar, intvar, t) switch string ## LCR part case "LIN" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor vp = extvar(1); vm = extvar(2); a = zeros(2); b = [1 -1 ;-1 1]/R; c = -[0; 0]; break ##NLCpart case "THERMAL" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor v1 = extvar(1); v2 = extvar(2); T = extvar(3); RT = R0*(1 + TC1*(T-TNOM) + TC2*(T - TNOM)^2); dRdT = R0*(TC1 + 2*TC2*(T-TNOM)); i1 = (v1-v2)/RT; i2 = (v2-v1)/RT; P = -(v1-v2)^2/RT; a = zeros(3); b = [ 1/RT -1/RT (v2-v1)*dRdT/RT^2;... -1/RT 1/RT (v1-v2)*dRdT/RT^2;... -2*(v1-v2)/RT -2*(v2-v1)/RT (v1-v2)^2*dRdT/RT^2]; c = [i1 i2 P]'; break; case "THERMAL1D" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor h = L/N; A = (cv*S*h)*speye(N+1); B = spdiags([ -ones(N+1,1) 2*ones(N+1,1) -ones(N+1,1)],-1:1,N+1,N+1); B(1 ,1) = 1; B(N+1 ,N+1) = 1; ext=[1 N+1]; int=[2:N]; a = [A(ext,ext), A(ext,int); A(int,ext), A(int,int)]; b = k*(S/h)*[B(ext,ext), B(ext,int); B(int,ext), B(int,int)]; c = zeros(N+1,1); break; otherwise error (["unknown section:" string]) endswitch endfunction ocs/inst/sbn/Mshichmanhodgesmosfet.m000644 000765 000000 00000017013 12207456226 020344 0ustar00carlowheel000000 000000 ## Copyright (C) 2006-2009 Carlo de Falco, Massimiliano Culpo ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco , culpo@math.uni-wuppertal.de ## -*- texinfo -*- ## ## @deftypefn{Function File} @ ## {[@var{a},@var{b},@var{c}]=} Mshichmanhodgesmosfet(@var{string},@var{parameters},@ ## @var{parameternames},@var{extvar},@var{intvar},@var{t}) ## ## SBN file implementing Schichman-Hodges MOSFETs model. ## ## @var{string} is used to select among models. Possible models are: ## ## @enumerate ## @item @var{string} = "NMOS" (Schichman-Hodges n-MOSFET) ## @item @var{string} = "PMOS" (Schichman-Hodges p-MOSFET) ## @end enumerate ## ## Parameters for all the above models are: ## @itemize ## @item rd -> parasitic resistance between drain and source ## @item W -> MOSFET width ## @item L -> channel length ## @item mu0 -> reference value for mobility ## @item Vth -> threshold voltage ## @item Cox -> oxide capacitance ## @item Cgs -> gate-source capacitance ## @item Cgd -> gate-drain capacitance ## @item Cgb -> gate-bulk capacitance ## @item Csb -> source-bulk capacitance ## @item Cdb -> drain-bulk capacitance ## @item Tshift -> shift for reference temperature on MOSFETs (default 0) ## @end itemize ## ## See the @cite{IFF file format specifications} for details about ## the output structures. ## ## @seealso{prs_iff,asm_initialize_system,asm_build_system} ## @end deftypefn function [a,b,c]= Mshichmanhodgesmosfet (string,parameters,parameternames,extvar,intvar,t) if isempty(intvar) ## If intvar is empty, then we are initializing the system ## and there is no need of a matrix evaluation a = sparse(10,10); b = []; c = []; else ## If intvar is NOT empty, then we are evaluating the ## element stamp switch string case "NMOS" rd = 1e6; W = 1; L = 1; mu0 = 1e-5; Vth = .5; Cox = 1e-9; Cgb = Cox; Cgs=Cgd=Csb=Cdb=.1*Cox; Tshift = 0; for ii=1:length(parameternames) eval([parameternames{ii} "=",... num2str(parameters(ii)) " ;"]) endfor [gm,gd,ids,didT,P,dPdT,dPdvgs,dPdvds] = ... nmos(extvar,mu0,Cox,W,L,Vth,rd,Tshift); vg = extvar(1); vs = extvar(2); vd = extvar(3); vb = extvar(4); T = max(extvar(5),0); if isempty(intvar) intvar = zeros(5,1); endif Qgb = intvar(1); Qgs = intvar(2); Qgd = intvar(3); Qsb = intvar(4); Qdb = intvar(5); a11 = a21 = a22 = zeros(5,5); a12 = [ 1 1 1 0 0; ... 0 -1 0 1 0; ... 0 0 -1 0 1; ... -1 0 0 -1 -1; ... 0 0 0 0 0]; a = [a11 a12; a21 a22]; b11 = [0 0 0 0 0; ... -gm (gm+gd) -gd 0 -didT; ... gm -(gm+gd) gd 0 didT; ... 0 0 0 0 0; ... dPdvgs -(dPdvgs+dPdvds) dPdvds 0 dPdT]; b12 = zeros(5,5); b21 = [Cgb 0 0 -Cgb 0; ... Cgs -Cgs 0 0 0; ... Cgd 0 -Cgd 0 0; ... 0 Csb 0 -Csb 0; ... 0 0 Cdb -Cdb 0]; b22 = -eye(5); b = [b11 b12; b21 b22]; c1 = [0; -ids; ids; 0; P]; c2 = [Cgb*(vg - vb) - Qgb;... Cgs*(vg - vs) - Qgs;... Cgd*(vg - vd) - Qgd;... Csb*(vs - vb) - Qsb;... Cdb*(vd - vb) - Qdb]; c = [c1;c2]; break; case "PMOS" rd = 1e6; W = 1; L = 1; mu0 = 1e-5; Vth = -.5; Cox = 1e-9; Cgb=Cox; Cgs=Cgd=Csb=Cdb=.1*Cox; Tshift = 0; for ii=1:length(parameternames) eval([parameternames{ii} "=",... num2str(parameters(ii)) " ;"]) endfor [gm,gd,ids,didT,P,dPdT,dPdvgs,dPdvds] = ... pmos(extvar,mu0,Cox,W,L,Vth,rd,Tshift); vg = extvar(1); vs = extvar(2); vd = extvar(3); vb = extvar(4); T = extvar(5); if isempty(intvar) intvar = zeros(5,1); endif Qgb = intvar(1); Qgs = intvar(2); Qgd = intvar(3); Qsb = intvar(4); Qdb = intvar(5); a11 = a21 = a22 = zeros(5,5); a12 = [ 1 1 1 0 0; ... 0 -1 0 1 0; ... 0 0 -1 0 1; ... -1 0 0 -1 -1; ... 0 0 0 0 0]; a = [a11 a12; a21 a22]; b11 = [0 0 0 0 0; ... -gm (gm+gd) -gd 0 -didT; ... gm -(gm+gd) gd 0 didT; ... 0 0 0 0 0; ... dPdvgs -(dPdvgs+dPdvds) dPdvds 0 dPdT]; b12 = zeros(5,5); b21 = [Cgb 0 0 -Cgb 0; ... Cgs -Cgs 0 0 0; ... Cgd 0 -Cgd 0 0; ... 0 Csb 0 -Csb 0; ... 0 0 Cdb -Cdb 0]; b22 = -eye(5); b = [b11 b12; b21 b22]; c1 = [0; -ids; ids; 0; P]; c2 = [Cgb*(vg - vb) - Qgb;... Cgs*(vg - vs) - Qgs;... Cgd*(vg - vd) - Qgd;... Csb*(vs - vb) - Qsb;... Cdb*(vd - vb) - Qdb]; c = [c1;c2]; break; otherwise error(["unknown option:" string]); endswitch endif endfunction function [gm,gd,ids,didT,P,dPdT,dPdvgs,dPdvds] = nmos(extvar,mu0,Cox,W,L,Vth,rd,Tshift) ##Computes values for nmos case vg = extvar(1); vs = extvar(2); vd = extvar(3); vb = extvar(4); T = max(extvar(5),0); k = mu0*Cox*((T + Tshift)/300)^(-3/2)*W/L; dkdT = mu0*Cox*W*(-3/2)*((T + Tshift)/300)^(-5/2)*(1/300)/L; vgs = vg-vs; vds = vd-vs; if (vgs < Vth) gm = 0; gd = 1/rd; ids = vds*gd; didT= 0; elseif (((vgs-Vth) >= (vds)) && (vds >= 0)) ids = k*((vgs-Vth)*vds-(vds^2)/2)+vds/rd; gm = k*vds; gd = k*(vgs-Vth-vds) + 1/rd; didT= dkdT*((vgs-Vth)*vds-(vds^2)/2); elseif (((vgs-Vth) >= (vds)) && (vds < 0)) gm = 0; gd = 1/rd; ids = vds*gd; didT= 0; else # (i.e. if 0 <= vgs-vth <= vds) ids = (k/2)*(vgs-Vth)^2+vds/rd; gm = k*(vgs-Vth); gd = 1/rd; didT= (dkdT/(2))*(vgs-Vth)^2; endif P = -ids * vds; dPdT = -didT* vds; dPdvgs = -(gm*vds); dPdvds = -(gd*vds + ids); endfunction function [gm,gd,ids,didT,P,dPdT,dPdvgs,dPdvds] = pmos(extvar,mu0,Cox,W,L,Vth,rd,Tshift) ##Computes values for pmos case vg = extvar(1); vs = extvar(2); vd = extvar(3); vb = extvar(4); T = extvar(5); k = - mu0 * Cox * ((T + Tshift)/300)^(-3/2) *W/L; dkdT = - mu0 * Cox * W *(-3/2)*((T + Tshift)/300)^(-5/2)*(1/300)/L; vgs = vg-vs; vds = vd-vs; if (vgs > Vth) gm = 0; gd = 1/rd; ids = vds*gd; didT= 0; elseif (((vgs-Vth) <= (vds)) && (vds <= 0)) ids = k*((vgs-Vth)*vds-(vds^2)/2)+vds/rd; gm = k*vds; gd = k*(vgs-Vth-vds)+1/rd; didT= dkdT*((vgs-Vth)*vds-(vds^2)/2); elseif (((vgs-Vth) <= (vds)) && (vds > 0)) gm = 0; gd = 1/rd; ids = vds*gd; didT= 0; else ids = (k/2)*(vgs-Vth)^2+vds/rd; gm = k*(vgs-Vth); gd = 1/rd; didT= (dkdT/(2))*(vgs-Vth)^2; endif P = -ids * vds; dPdT = -didT* vds; dPdvgs = -(gm*vds); dPdvds = -(gd*vds + ids); endfunctionocs/inst/sbn/Mtdnmos.cir000644 000765 000000 00000000411 11334211056 015747 0ustar00carlowheel000000 000000 % 0.1b1 % A Simple MOSFET model % including charge stores % N-Mosfet Mnmosfet simple 4 3 1 3 k Vth rd 1 1 1e30 1 5 6 4 END % Resistors Mresistors LIN 2 1 2 1 R 1 1 2 5 3 6 % Capacitors Mcapacitors LIN 2 1 3 1 C 1 1 1 1 5 1 6 1 4 END ocs/inst/sbn/Mtdnmos.nms000644 000765 000000 00000000066 11334211056 015775 0ustar00carlowheel000000 000000 % 0.1b1 1 Vg 2 Vs 3 Vd 4 Vb 5 Vsi 6 Vdi 7 Qs 8 Qd 9 Qbocs/inst/sbn/Mtdpmos.cir000644 000765 000000 00000000411 11334211056 015751 0ustar00carlowheel000000 000000 % 0.1b1 % A Simple MOSFET model % including charge stores % N-Mosfet Mpmosfet simple 4 3 1 3 k Vth rd 1 1 1e30 1 5 6 4 END % Resistors Mresistors LIN 2 1 2 1 R 1 1 2 5 3 6 % Capacitors Mcapacitors LIN 2 1 3 1 C 1 1 1 1 5 1 6 1 4 END ocs/inst/sbn/Mtdpmos.nms000644 000765 000000 00000000066 11334211056 015777 0ustar00carlowheel000000 000000 % 0.1b1 1 Vg 2 Vs 3 Vd 4 Vb 5 Vsi 6 Vdi 7 Qs 8 Qd 9 Qbocs/inst/sbn/Mvoltagesources.m000644 000765 000000 00000011452 11334211056 017176 0ustar00carlowheel000000 000000 ## Copyright (C) 2006,2007,2008 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## -*- texinfo -*- ## ## @deftypefn{Function File} @ ## {[@var{a},@var{b},@var{c}]=} Mvoltagesources(@var{string},@var{parameters},@ ## @var{parameternames},@var{extvar},@var{intvar},@var{t}) ## ## SBN file implementing models for voltage sources. ## ## @var{string} is used to select among models. Parameters are listed ## as inner items. Possible models are: ## ## @enumerate ## @item @var{string} = "DC" (Static indipendent voltage source) ## @itemize @minus ## @item V -> Current source value ## @end itemize ## @item @var{string} = "sinwave" (Sinusoidal indipendent voltage ## source) ## @itemize @minus ## @item shift -> mean value of sinusoidal input ## @item Ampl -> amplitude of sinusoidal wave ## @item f -> frequency of sinusoidal wave ## @item delay -> delay of sinusoidal wave ## @end itemize ## @item @var{string} = "pwl" (Piecewise linear voltage source) ## @itemize @minus ## @item takes as parameter times and values. For example @code{0 1 4 6} ## means at time instant 0 value 1, at time instant 4 value 6, etc. ## @end itemize ## @item @var{string} = "squarewave" (Square wave) ## @itemize @minus ## @item low -> low-state value ## @item high -> high-state value ## @item tlow -> duration of low-state ## @item thigh -> duration of high-state ## @item delay -> delay of square wave ## @item start -> starting voltage value ## @end itemize ## @item @var{string} = "step" (Voltage step) ## @itemize @minus ## @item low -> low-state value ## @item high -> high-state value ## @item tstep -> time instant of step transition ## @end itemize ## @item @var{string} = "VCVS" (Voltage controlled voltage source) ## @itemize @minus ## @item K -> Control parameter ## @end itemize ## @end enumerate ## ## See the @cite{IFF file format specifications} for details about ## the output structures. ## ## @seealso{prs_iff,asm_initialize_system,asm_build_system} ## @end deftypefn function [a,b,c] = Mvoltagesources (string,parameters,parameternames,extvar,intvar,t) if isempty(intvar) intvar = 0; endif switch string ##LCR part case "DC" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor j = intvar(1); a = zeros(3); b = [0 0 1;0 0 -1;1 -1 0]; c = [0 0 -V]; break ## NLC part case "sinwave" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor DV = shift+Ampl * sin(2*pi*(t+delay)*f ); j = intvar(1); a = zeros(3); b = [0 0 1;0 0 -1;1 -1 0]; c = [0 0 -DV]' + b * [extvar;intvar]; break case "pwl" times = parameters(1:2:end-1); values= parameters(2:2:end); DV = interp1(times,values,t,"linear","extrap"); j = intvar(1); a = zeros(3); b = [0 0 1;0 0 -1;1 -1 0]; c = [0 0 -DV]' + b * [extvar;intvar]; break case "squarewave" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) endfor if t. ## ## author: Carlo de Falco ## author: Massimiliano Culpo ## -*- texinfo -*- ## @deftypefn{Function File} @var{outstruct} = prs_iff(@var{name}) ## Parse a netlist in IFF format and produce the system description ## structure @var{outstruct}. ## ## @var{name} is the basename of the CIR and NMS files to ## be parsed. ## ## See the @cite{IFF file format specifications} (distributed together ## with the OCS package) for more details on the file format. ## ## @var{outstruct} has the following fields: ## ## @example ## outstruct = ## @{ ## LCR: struct % the fields of LCR are shown below ## NLC: struct % NLC has the same fields as LCR ## namesn: matrix % numbers of vars named in .nms file ## namess: cell % the names corresponding to the vars above ## totextvar: scalar % the total number of external variables ## totintvar: scalar % the total number of internal variables ## @} ## ## outstruct.LCR = ## outstruct.NLC = ## @{ ## struct array containing the fields: % array has one element per block ## ## func % name of the sbn file corresponding to each block ## section % string parameter to be passed to the sbn files ## nextvar % number of external variables for each element of the block ## vnmatrix % numbers of the external variables of each element ## nintvar % number of internal variables for each element of the block ## osintvar % number of the first internal variable ## npar % number of parameters ## nparnames% number of parameter names ## nrows % number of rows in the block ## parnames % list of parameter names ## pvmatrix % list of parameter values for each element ## ## @} ## @end example ## ## See the @cite{IFF file format specifications} for details about ## the output structures. ## @seealso{prs_spice} ## @end deftypefn function outstruct = prs_iff(name) ## Check input if (nargin != 1 || !ischar(name)) error("prs_iff: wrong input.") endif ## Initialization version ="0.1b1"; outstruct = struct("NLC",[],... "LCR",[],... "totextvar",0); ## Open cir file filename = [name ".cir"]; if isempty(file_in_path(".",filename)) error(["prs_iff: .cir file not found:" filename]); endif fid = fopen(filename,"r"); ## Check version ## FIXME: this part can be improved a lot!! line = fgetl(fid); if line(1)!="%" error(["prs_iff: missing version number in file " filename]); endif if ~strcmp(version,sscanf(line(2:end),"%s")); error(["prs_iff: conflicting version number in file " filename]); endif ndsvec = []; # Vector of circuit nodes intvar = 0; # Number of internal variables ## NLC section NLCcount = 0; while !strcmp(line,"END") ## Skip comments while line(1)=="%" line = fgetl(fid); endwhile if strcmp(line,"END") break else NLCcount++; endif ## parse NLC block [outstruct,intvar] = parseNLCblock(fid,line,outstruct,NLCcount,intvar); ndsvec = [ndsvec ; ... outstruct.NLC(NLCcount).vnmatrix(:)]; ## skip the newline char after the matrix line = fgetl(fid); ## proceed to next line line = fgetl(fid); endwhile ## LCR section LCRcount = 0; line = fgetl(fid); while (!strcmp(line,"END")) ## Skip comments while line(1)=="%" line = fgetl(fid); endwhile if strcmp(line,"END") break else LCRcount++; endif ## parse block header [outstruct,intvar] = parseLCRblock(fid,line,outstruct,LCRcount,intvar); ndsvec = [ndsvec ; ... outstruct.LCR(LCRcount).vnmatrix(:)]; ## skip the newline char after the matrix line = fgetl(fid); ## proceed to next line line = fgetl(fid); endwhile ## Set the number of internal and external variables outstruct.totintvar = intvar; nnodes = length(unique(ndsvec)); maxidx = max(ndsvec); if nnodes <= (maxidx+1) ## If the valid file is a subcircuit it may happen ## that nnodes == maxidx, otherwise nnodes == (maxidx+1) outstruct.totextvar = max(ndsvec); else error("prs_iff: hanging nodes in circuit %s",name); endif ## fclose cir file fclose(fid); ## Open nms file filename = [name ".nms"]; if isempty(file_in_path(".",filename)) error(["prs_iff: .nms file not found:" filename]); endif fid = fopen(filename,"r"); ## Check version line = fgetl(fid); if line(1)~="%" error(["prs_iff: missing version number in file " filename]); endif if ~strcmp(version,sscanf(line(2:end),"%s")); error(["prs_iff: conflicting version number in file " filename]); endif ## Initialization cnt = 1; outstruct.namesn = []; outstruct.namess = {}; nnames = 0; while cnt [nn,cnt] = fscanf(fid,"%d","C"); [ns,cnt] = fscanf(fid,"%s","C"); if cnt outstruct.namesn(++nnames)=nn; outstruct.namess{nnames}=ns; endif endwhile ## fclose nms file fclose(fid); endfunction ############################################## function [outstruct,intvar] = parseNLCblock(fid,line,outstruct,NLCcount,intvar); ## Parse first line of the header and retrieve: ## 1 - SBN function name ## 2 - Section ## 3 - Number of external variables ## 4 - Number of parameters [func,section,nextvar,npar] = sscanf(line,"%s %s %g %g","C"); outstruct.NLC(NLCcount).func = func; outstruct.NLC(NLCcount).section = section; outstruct.NLC(NLCcount).nextvar = nextvar; outstruct.NLC(NLCcount).npar = npar; ## Parse second line of the header and retrieve: ## 1 - Number of elements of this type ## 2 - Number of parameter names to be parsed [nrows,nparnames] = fscanf(fid,"%g %g","C"); outstruct.NLC(NLCcount).nrows = nrows; outstruct.NLC(NLCcount).nparnames = nparnames; outstruct.NLC(NLCcount).parnames = {}; for ii=1:nparnames outstruct.NLC(NLCcount).parnames{ii} = fscanf(fid,"%s","C"); endfor ## Parse the matrix containing the values of parameters [outstruct.NLC(NLCcount).pvmatrix] = fscanf(fid,"%g",[npar,nrows])'; ## Parse the connectivity matrix [outstruct.NLC(NLCcount).vnmatrix] = fscanf(fid,"%g",[nextvar,nrows])'; ## Compute internal variables cycling over each ## element in the section for iel = 1:nrows [a,b,c] = feval(func,section,outstruct.NLC(NLCcount).pvmatrix(iel,:),... outstruct.NLC(NLCcount).parnames,zeros(nextvar,1),[],0); ## FIXME: if all the element in the same section share the ## same number of internal variables, the for cycle can be ## substituted by only one call outstruct.NLC(NLCcount).nintvar(iel) = columns(a) - outstruct.NLC(NLCcount).nextvar; outstruct.NLC(NLCcount).osintvar(iel) = intvar; intvar += outstruct.NLC(NLCcount).nintvar(iel); endfor endfunction ############################################## function [outstruct,intvar] = parseLCRblock(fid,line,outstruct,LCRcount,intvar); ## Parse first line of the header and retrieve: ## 1 - SBN function name ## 2 - Section ## 3 - Number of external variables ## 4 - Number of parameters [func,section,nextvar,npar] = sscanf(line,"%s %s %g %g","C"); outstruct.LCR(LCRcount).func = func; outstruct.LCR(LCRcount).section = section; outstruct.LCR(LCRcount).nextvar = nextvar; outstruct.LCR(LCRcount).npar = npar; ## Parse second line of the header and retrieve: ## 1 - Number of elements of this type ## 2 - Number of parameter names to be parsed [nrows,nparnames] = fscanf(fid,"%g %g","C"); outstruct.LCR(LCRcount).nrows = nrows; outstruct.LCR(LCRcount).nparnames = nparnames; outstruct.LCR(LCRcount).parnames = {}; for ii=1:nparnames outstruct.LCR(LCRcount).parnames{ii} = fscanf(fid,"%s","C"); endfor ## Parse the matrix containing the values of parameters [outstruct.LCR(LCRcount).pvmatrix] = fscanf(fid,"%g",[npar,nrows])'; ## Parse the connectivity matrix [outstruct.LCR(LCRcount).vnmatrix] = fscanf(fid,"%g",[nextvar,nrows])'; ## Compute internal variables cycling over each ## element in the section for iel = 1:nrows [a,b,c] = feval(func,section,outstruct.LCR(LCRcount).pvmatrix(iel,:),... outstruct.LCR(LCRcount).parnames,zeros(nextvar,1),[],0); ## FIXME: if all the element in the same section share the ## same number of internal variables, the for cycle can be ## substituted by only one call outstruct.LCR(LCRcount).nintvar(iel) = columns(a) - outstruct.LCR(LCRcount).nextvar; outstruct.LCR(LCRcount).osintvar(iel) = intvar; intvar += outstruct.LCR(LCRcount).nintvar(iel); endfor endfunctionocs/inst/prs/prs_spice.m000644 000765 000000 00000111011 11731174024 016021 0ustar00carlowheel000000 000000 ## Copyright (C) 2012 Marco Merlin ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## OCS is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with OCS; If not, see . ## ## author: Marco Merlin ## based on prs_iff which is (C) Carlo de Falco and Massimiliano Culpo ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{stuct}]} = prs_spice (@var{filename}) ## ## Circuit file parser that can interpret a subset of the spice file format. ## ## @code{prs_spice} currently supports the following set of "Element Cards" ## @itemize @minus ## @item Capacitors: ## @example ## Cname n+ n- cvalue ## @end example ## ## @item Diodes: ## @example ## Cname anode knode modelname ## @end example ## ## @item MOS: ## @example ## Mname gnode dnode snode bnode modelname ## @end example ## ## N.B.: one instance of a MOS element MUST be preceeded (everywhere in the file) by the declaration of the related model. ## For instance: ## @example ## .MODEL mynmos NMOS( k=1e-4 Vth=0.1 rd=1e6) ## M2 Vgate 0 Vdrain 0 mynmos ## @end example ## ## @item Resistors: ## @example ## Rname n+ n- rvalue ## @end example ## ## @item Voltage sources: ## @example ## Vname n+ n- ## @end example ## ## Transvalue specifies a transient voltage source ## @example ## SIN(VO VA FREQ TD THETA) ## @end example ## where: ## @itemize @bullet ## @item VO (offset) ## @item VA (amplitude) ## @item FREQ (frequency) ## @item TD (delay) ## @item THETA (damping factor) ## @end itemize ## ## @itemize @bullet ## @item 0 to TD: V0 ## @item TD to TSTOP: ## VO + VA*exp(-(time-TD)*THETA)*sine(twopi*FREQ*(time+TD)) ## @end itemize ## ## Currently the damping factor has no effect. ## ## Pulse ## @example ## PULSE(V1 V2 TD TR TF PW PER) ## @end example ## ## parameters meaning ## @itemize @bullet ## @item V1 (initial value) ## @item V2 (pulsed value) ## @item TD (delay time) ## @item TR (rise time) ## @item TF (fall time) ## @item PW (pulse width) ## @item PER (period) ## @end itemize ## ## Currently rise and fall time are not implemented yet. ## ## @item .MODEL cards ## Defines a model for semiconductor devices ## ## @example ## .MODEL MNAME TYPE(PNAME1=PVAL1 PNAME2=PVAL2 ... ) ## @end example ## ## TYPE can be: ## @itemize @bullet ## @item NMOS N-channel MOSFET model ## @item PMOS P-channel MOSFET model ## @item D diode model ## @end itemize ## ## The parameter "LEVEL" is currently assigned to the field "section" in the call ## of the element functions by the solver. ## Currently supported values for the parameter LEVEL for NMOS and PMOS are: ## @itemize @bullet ## @item simple ## @item lincap ## @end itemize ## (see documentation of function Mdiode). ## ## Currently supported values for the parameter LEVEL for D are: ## @itemize @bullet ## @item simple ## @end itemize ## (see documentation of functions Mnmosfet and Mpmosfet). ## ## @end itemize ## @seealso{prs_iff,Mdiode,Mnmosfet,Mpmosfet} ## @end deftypefn function outstruct = prs_spice (name) ## Check input if (nargin != 1 || !ischar (name)) error ("prs_spice: wrong input.") endif ## Initialization outstruct = struct ("LCR", [], "NLC", [], "totextvar", 0); global ndsvec; # Vector of circuit nodes global nodes_list; global intvar_list; global models_list; ndsvec = []; outstruct.totintvar = 0; # Number of internal variables count = struct ("NLC", struct ("n", 0, "list", {""}), "LCR", struct ("n", 0, "list", {""})); nodes_list = {"0"}; intvar_list = {}; models_list = struct ("mname", {""}, "melement", {""}, "msection", {""}); ## File parsing ## Open circuit file filename = [name ".spc"]; if (exist (filename) != 2) ## isempty (file_in_path (".", filename)) error (["prs_spice: .spc file not found:" filename]); endif fid = fopen (filename, "r"); if (fid>-1) line = ''; fullline = ''; lineCounter = 0; while (! feof (fid)) line = strtrim (line); %% exclude empty lines if length (line) %% exclude comments if (! strncmpi (line, '*', 1)) %% lines here aren't comments if (strncmpi (line, '+', 1)) %% this line has to be concatenated to previous one line (1) = ' '; fullline = [fullline line]; else %% these lines are not a concatenation %% line echo for debug %# disp (fullline); %% compute fullline here! %#[outstruct, intvar, count] = lineParse (upper (fullline), outstruct, count, intvar); %# NB: case-sensitive because of parameter names %#[outstruct, intvar, count] = lineParse (fullline, outstruct, intvar, count); [outstruct, count] = lineParse (fullline, outstruct, count); fullline = line; end %if (strncmpi (line, '+', 1)) end %if (~strncmpi (line, '*', 1)) end % if length (line) line = fgets (fid); lineCounter = lineCounter+1; end % while ~feof (fid) %% parse last line if length (fullline) ## NB: case-sensitive because of parameter names %#[outstruct, intvar, count] = lineParse (upper (fullline), outstruct, count, intvar); %#[outstruct, intvar, count] = lineParse (fullline, outstruct, intvar, count); [outstruct, count] = lineParse (fullline, outstruct, count); end fclose (fid); else error ('Input file not found!'); end ## Set the number of internal and external variables nnodes = length (unique (ndsvec)); maxidx = max (ndsvec); if (nnodes <= (maxidx+1)) ## If the valid file is a subcircuit it may happen ## that nnodes == maxidx, otherwise nnodes == (maxidx+1) outstruct.totextvar = max (ndsvec); else error ("prs_spice: hanging nodes in circuit %s", name); endif ## set node names as variable names for ii = 1:length (nodes_list) outstruct.namesn (ii) = ii-1; endfor outstruct.namess = horzcat (nodes_list, intvar_list); ##outstruct.namess ##outstruct.totintvar endfunction ## NLC block intvar count update function outstruct = NLCintvar (outstruct, NLCcount, name) global ndsvec; global intvar_list; ## set node names for NLC subcircuit ##for NLCcount = 1:count.NLC.n; ##NLCcount = count.NLC.n; ## set vnmatrix for NLC subcircuit ndsvec = [ndsvec ; outstruct.NLC(NLCcount).vnmatrix(:)]; ## Compute internal variables cycling over each ## element in the section ##for iel = 1:outstruct.NLC(NLCcount).nrows iel = outstruct.NLC(NLCcount).nrows; [a, b, c] = feval (outstruct.NLC(NLCcount).func, outstruct.NLC(NLCcount).section, outstruct.NLC(NLCcount).pvmatrix(iel, :), outstruct.NLC(NLCcount).parnames, zeros (outstruct.NLC(NLCcount).nextvar, 1), [], 0); ## FIXME: if all the element in the same section share the ## same number of internal variables, the for cycle can be ## substituted by only one call outstruct.NLC(NLCcount).nintvar(iel) = columns (a) - outstruct.NLC(NLCcount).nextvar; outstruct.NLC(NLCcount).osintvar(iel) = outstruct.totintvar; outstruct.totintvar += outstruct.NLC(NLCcount).nintvar(iel); if outstruct.NLC(NLCcount).nintvar(iel)>0 intvar_list{outstruct.totintvar} = ["I(" name ")"]; endif ##endfor ##endfor # NLCcount = 1:count.NLC.n; endfunction ## LCR block intvar count update function outstruct = LCRintvar (outstruct, LCRcount, name) global ndsvec; global intvar_list; ## set node names for LCR subcircuit ## for LCRcount = 1:count.LCR.n; ## LCRcount = count.LCR.n; ## set vnmatrix for LCR subcircuit ndsvec = [ndsvec ; outstruct.LCR(LCRcount).vnmatrix(:)]; ## Compute internal variables cycling over each ## element in the section ##for iel = 1:outstruct.LCR(LCRcount).nrows iel = outstruct.LCR(LCRcount).nrows; [a, b, c] = feval (outstruct.LCR(LCRcount).func, outstruct.LCR(LCRcount).section, outstruct.LCR(LCRcount).pvmatrix(iel, :), outstruct.LCR(LCRcount).parnames, zeros(outstruct.LCR(LCRcount).nextvar, 1), [], 0); ## FIXME: if all the element in the same section share the ## same number of internal variables, the for cycle can be ## substituted by only one call outstruct.LCR(LCRcount).nintvar(iel) = columns (a) - outstruct.LCR(LCRcount).nextvar; ##outstruct.LCR(LCRcount).osintvar(iel) = intvar; outstruct.LCR(LCRcount).osintvar(iel) = outstruct.totintvar; ##intvar += outstruct.LCR(LCRcount).nintvar(iel); outstruct.totintvar += outstruct.LCR(LCRcount).nintvar(iel); if outstruct.LCR(LCRcount).nintvar(iel)>0 intvar_list{outstruct.totintvar} = ["I(" name ")"]; endif ##endfor ## endfor # LCRcount = 1:count.LCR.n; endfunction ## Parses a single line function [outstruct, count] = lineParse (line, outstruct, count) if length (line) switch (line (1)) case 'B' case 'C' [outstruct, count] = prs_spice_C (line, outstruct, count); case 'D' [outstruct, count] = prs_spice_D (line, outstruct, count); case 'E' ##mspINP2E (line, lineCounter); case 'F' ##mspINP2F (line, lineCounter); case 'G' ##mspINP2G (line, lineCounter); case 'H' ##mspINP2H (line, lineCounter); case 'I' ##mspINP2I (line, lineCounter); case 'J' case 'K' ##mspINP2K (line, lineCounter); case 'L' ##mspINP2L (line, lineCounter); case 'M' ## FIXME: just for nMOS devices! [outstruct, count] = prs_spice_M (line, outstruct, count); ## case 'P' ## temporarily assigned to pMOS devices. ##[outstruct, count] = prs_spice_P (line, outstruct, count); case 'Q' case 'R' [outstruct, count] = prs_spice_R (line, outstruct, count); case 'S' case 'T' case 'U' case 'V' [outstruct, count] = prs_spice_V (line, outstruct, count); case 'W' case 'X' case 'Z' case '.' [outstruct, count] = prs_spice_dot (line, outstruct, count); otherwise warn = sprintf (['prs_spice: Unsupported circuit element in line: ' line ]); warning (warn); end % switch (line (1)) end %if length (line) endfunction ## adds an NLC element to outstruct function [outstruct, count] = addNLCelement (outstruct, count, element, section, nextvar, npar, nparnames, parnames, vnmatrix, pvmatrix) ## check whether the element type already exists in output structure ## the search key is (func, section) ##[tf, idx] = ismember ({element}, count.NLC.list); ##if !tf ## the element still does not exist ## update counters count.NLC.n++; count.NLC.list{count.NLC.n} = element; ## if the element doesn't exists, add it to the output structure outstruct.NLC(count.NLC.n).func = element; outstruct.NLC(count.NLC.n).section = section; outstruct.NLC(count.NLC.n).nextvar = nextvar; outstruct.NLC(count.NLC.n).npar = npar; outstruct.NLC(count.NLC.n).nrows = 1; outstruct.NLC(count.NLC.n).nparnames = nparnames; outstruct.NLC(count.NLC.n).parnames = parnames; outstruct.NLC(count.NLC.n).vnmatrix = vnmatrix; outstruct.NLC(count.NLC.n).pvmatrix = pvmatrix; ##else ## found = 0; ## for ii = 1:length (idx) ## if strcmp (outstruct.NLC(idx(ii)).section, section) ## found = 1; ## break; ## endif #!strcmp (outstruct.NLC(idx(ii)).section, section) ## endfor #ii = 1:length (idx) ## if !found ## the section does not exist ## the element still does not exist ## update counters ## count.NLC.n++; ## count.NLC.list{count.NLC.n} = element; ## if the element doesn't exists, add it to the output structure ## outstruct.NLC(count.NLC.n).func = element; ## outstruct.NLC(count.NLC.n).section = section; ## outstruct.NLC(count.NLC.n).nextvar = nextvar; ## outstruct.NLC(count.NLC.n).npar = npar; ## outstruct.NLC(count.NLC.n).nrows = 1; ## outstruct.NLC(count.NLC.n).nparnames = nparnames; ## outstruct.NLC(count.NLC.n).parnames = parnames; ## outstruct.NLC(count.NLC.n).vnmatrix = vnmatrix; ## outstruct.NLC(count.NLC.n).pvmatrix = pvmatrix; ## else ## the couple (element, section) already exists, so add a row in the structure ## add an element to the structure ## outstruct.NLC(idx(ii)).nrows++; ## update parameter value and connectivity matrix ## [outstruct.NLC(idx(ii)).vnmatrix] = [outstruct.NLC(idx(ii)).vnmatrix; vnmatrix]; ## [outstruct.NLC(idx(ii)).pvmatrix] = [outstruct.NLC(idx(ii)).pvmatrix; pvmatrix]; ## endif ##endif endfunction ## adds an LCR element to outstruct function [outstruct, count] = addLCRelement (outstruct, count, element, section, nextvar, npar, nparnames, parnames, vnmatrix, pvmatrix) ## check whether the element type already exists in output structure ## the search key is (func, section) [tf, idx] = ismember ({element}, count.LCR.list); if !tf ## the element still does not exist ## update counters count.LCR.n++; count.LCR.list{count.LCR.n} = element; ## if the element doesn't exists, add it to the output structure outstruct.LCR(count.LCR.n).func = element; outstruct.LCR(count.LCR.n).section = section; outstruct.LCR(count.LCR.n).nextvar = nextvar; outstruct.LCR(count.LCR.n).npar = npar; outstruct.LCR(count.LCR.n).nrows = 1; outstruct.LCR(count.LCR.n).nparnames = nparnames; outstruct.LCR(count.LCR.n).parnames = parnames; outstruct.LCR(count.LCR.n).vnmatrix = vnmatrix; outstruct.LCR(count.LCR.n).pvmatrix = pvmatrix; else found = 0; for ii = 1:length (idx) if strcmp (outstruct.LCR(idx(ii)).section, section) found = 1; break; endif #!strcmp (outstruct.LCR(idx(ii)).section, section) endfor #ii = 1:length (idx) if (! found) ## the section does not exist ## the element still does not exist ## update counters count.LCR.n++; count.LCR.list{count.LCR.n} = element; ## if the element doesn't exists, add it to the output structure outstruct.LCR(count.LCR.n).func = element; outstruct.LCR(count.LCR.n).section = section; outstruct.LCR(count.LCR.n).nextvar = nextvar; outstruct.LCR(count.LCR.n).npar = npar; outstruct.LCR(count.LCR.n).nrows = 1; outstruct.LCR(count.LCR.n).nparnames = nparnames; outstruct.LCR(count.LCR.n).parnames = parnames; outstruct.LCR(count.LCR.n).vnmatrix = vnmatrix; outstruct.LCR(count.LCR.n).pvmatrix = pvmatrix; else ## the couple (element, section) already exists, so add a row in the structure ## add an element to the structure outstruct.LCR(idx(ii)).nrows++; ## update parameter value and connectivity matrix [outstruct.LCR(idx(ii)).vnmatrix] = [outstruct.LCR(idx(ii)).vnmatrix; vnmatrix]; [outstruct.LCR(idx(ii)).pvmatrix] = [outstruct.LCR(idx(ii)).pvmatrix; pvmatrix]; endif endif endfunction ## converts a blank separated values string into a cell array function ca = str2ca (str) ca = regexpi (str, '[^ \s=]+', 'match'); endfunction ## replaces the tokens c_old with c_new in string inString function outString = strReplace (inString, c_old, c_new) outString = inString; l = length (c_new); for idx = 1:length (c_old) if (idx<=l) outString = strrep (outString, c_old{idx}, c_new{idx}); end end endfunction ## returns the numeric value of a string function num = literal2num (string) literals = {'MEG' 'MIL' 'A' 'F' 'P' 'N' 'U' 'M' 'K' 'G' 'T'}; numerics = {'e6' '*25.4e-6' 'e-18' 'e-15' 'e-12' 'e-9' 'e-6' 'e-3' 'e3' 'e9' 'e12'}; newstr = strReplace (upper (string), literals, numerics); num = str2num (newstr); end function syntaxError (line) warnstr = sprintf ("Syntax error in line: %s", line); error (warnstr); endfunction function [outstruct, count] = prs_spice_C (line, outstruct, count) element = "Mcapacitors"; ## check wheter the element type already exists in output structure [tf, idx] = ismember ({element}, count.NLC.list); if !tf ## update counters count.NLC.n++; count.NLC.list{count.NLC.n} = element; #idx=count.NLC.n; ## if the element doesn't exists, add it to the output structure outstruct.NLC(count.NLC.n).func = element; outstruct.NLC(count.NLC.n).section = "LIN"; outstruct.NLC(count.NLC.n).nextvar = 2; outstruct.NLC(count.NLC.n).npar = 1; outstruct.NLC(count.NLC.n).nrows = 0; outstruct.NLC(count.NLC.n).nparnames = 1; outstruct.NLC(count.NLC.n).parnames = {"C"}; outstruct.NLC(count.NLC.n).vnmatrix = []; outstruct.NLC(count.NLC.n).pvmatrix = []; endif ## add an element to the structure ##outstruct.NLC(idx).nrows++; outstruct.NLC(count.NLC.n).nrows++; ## convert input line string into cell array ca = str2ca (line); if length (ca)>3 ## update parameter value and connectivity matrix ##[outstruct.NLC(idx).vnmatrix] = [outstruct.NLC(idx).vnmatrix; add_nodes(ca(2:3))]; ##[outstruct.NLC(idx).pvmatrix] = [outstruct.NLC(idx).pvmatrix; literal2num(ca{4})]; [outstruct.NLC(count.NLC.n).vnmatrix] = [outstruct.NLC(count.NLC.n).vnmatrix; add_nodes(ca(2:3))]; [outstruct.NLC(count.NLC.n).pvmatrix] = [outstruct.NLC(count.NLC.n).pvmatrix; literal2num(ca{4})]; else syntaxError (line); endif ##outstruct = NLCintvar (outstruct, idx, ca{1}); outstruct = NLCintvar(outstruct, count.NLC.n, ca{1}); endfunction function [outstruct, count] = prs_spice_D (line, outstruct, count) element = "Mdiode"; ## check wheter the element type already exists in output structure ##[tf, idx] = ismember ({element}, count.NLC.list); ##if !tf ## update counters count.NLC.n++; count.NLC.list{count.NLC.n} = element; ##idx = count.NLC.n; ## if the element doesn't exists, add it to the output structure outstruct.NLC(count.NLC.n).func = element; outstruct.NLC(count.NLC.n).section = "simple"; outstruct.NLC(count.NLC.n).nextvar = 2; outstruct.NLC(count.NLC.n).npar = 0; outstruct.NLC(count.NLC.n).nrows = 1; outstruct.NLC(count.NLC.n).nparnames = 0; outstruct.NLC(count.NLC.n).parnames = {}; outstruct.NLC(count.NLC.n).vnmatrix = []; outstruct.NLC(count.NLC.n).pvmatrix = []; ##endif ## convert input line string into cell array ca = str2ca (line); ## update parameter value and connectivity matrix ##[outstruct.NLC(idx).vnmatrix] = [outstruct.NLC(idx).vnmatrix; add_nodes(ca(2:3))]; [outstruct.NLC(count.NLC.n).vnmatrix] = [outstruct.NLC(count.NLC.n).vnmatrix; add_nodes(ca(2:3))]; ## check if parameters are specified for prm_idx = 1:(length (ca)-3)/2 ## [tf, str_idx] = ismember (outstruct.NLC(count.NLC.n).parnames{prm_idx}, ca); ## TODO: can the loop be executed in a single operation? ## [tf, str_idx] = ismember (outstruct.NLC(count.NLC.n).parnames, ca); if length (ca) >= 1+prm_idx*2 ## find specified parameter name ##if tf outstruct.NLC(count.NLC.n).npar++; outstruct.NLC(count.NLC.n).nparnames++; outstruct.NLC(count.NLC.n).parnames{1, prm_idx} = ca{2*prm_idx+2}; outstruct.NLC(count.NLC.n).pvmatrix(1, prm_idx) = literal2num (ca{2*prm_idx+3}); ##else ## TODO: set to a default value undefined parameters, instead of rising an error? ## errstr = sprintf ("Undefined parameter %s in line: %s", outstruct.NLC(count.NLC.n).parnames{prm_idx}, line); ## error (errstr); ##endif else syntaxError (line); endif endfor outstruct = NLCintvar(outstruct, count.NLC.n, ca{1}); endfunction function [outstruct, count] = prs_spice_M (line, outstruct, count) global models_list; ##element = "Mnmosfet"; ## check wheter the element type already exists in output structure ##[tf, idx] = ismember ({element}, count.NLC.list); ##if !tf ## update counters count.NLC.n++; ##count.NLC.list{count.NLC.n} = element; ##idx = count.NLC.n; ## if the element doesn't exists, add it to the output structure ##outstruct.NLC(count.NLC.n).func = element; ##outstruct.NLC(count.NLC.n).section = "simple"; ## outstruct.NLC(count.NLC.n).section = "lincap"; outstruct.NLC(count.NLC.n).nextvar = 4; outstruct.NLC(count.NLC.n).npar = 0; outstruct.NLC(count.NLC.n).nrows = 1; outstruct.NLC(count.NLC.n).nparnames = 0; outstruct.NLC(count.NLC.n).parnames = {}; ##outstruct.NLC(count.NLC.n).vnmatrix = []; outstruct.NLC(count.NLC.n).pvmatrix = []; ##endif ## convert input line string into cell array ca = str2ca (line); ## update parameter value and connectivity matrix ##[outstruct.NLC(idx).vnmatrix] = [add_nodes(ca(2:5))]; [outstruct.NLC(count.NLC.n).vnmatrix] = [add_nodes(ca(2:5))]; [tf, idx] = ismember (ca{6}, models_list.mname); if (tf) outstruct.NLC(count.NLC.n).func = models_list.melement{idx}; outstruct.NLC(count.NLC.n).section = models_list.msection{idx}; ## check if parameters are specified for prm_idx = 1:(length (ca)-6)/2 if length (ca)>=4+prm_idx*2 outstruct.NLC(count.NLC.n).npar++; outstruct.NLC(count.NLC.n).nparnames++; outstruct.NLC(count.NLC.n).parnames{1, prm_idx} = ca{2*prm_idx+5}; outstruct.NLC(count.NLC.n).pvmatrix(1, prm_idx) = literal2num (ca{2*prm_idx+6}); else syntaxError (line); endif endfor ## add model parameters to list prm_idx = outstruct.NLC(count.NLC.n).npar; len = length (models_list.plist{idx}.pnames); for mpidx = 1:len outstruct.NLC(count.NLC.n).parnames{prm_idx+mpidx} = models_list.plist{idx}.pnames{mpidx}; outstruct.NLC(count.NLC.n).pvmatrix(1, prm_idx+mpidx) = models_list.plist{idx}.pvalues(mpidx); endfor outstruct.NLC(count.NLC.n).npar = outstruct.NLC(count.NLC.n).npar+len; outstruct.NLC(count.NLC.n).nparnanames = outstruct.NLC(count.NLC.n).nparnames+len; outstruct = NLCintvar(outstruct, count.NLC.n, ca{1}); else syntaxError (line); endif endfunction function [outstruct, count]= prs_spice_P (line, outstruct, count) element = "Mpmosfet"; ## check wheter the element type already exists in output structure ## update counters count.NLC.n++; count.NLC.list{count.NLC.n} = element; ## if the element doesn't exists, add it to the output structure outstruct.NLC(count.NLC.n).func = element; outstruct.NLC(count.NLC.n).section = "simple"; ## outstruct.NLC(count.NLC.n).section = "lincap"; outstruct.NLC(count.NLC.n).nextvar = 4; outstruct.NLC(count.NLC.n).npar = 0; outstruct.NLC(count.NLC.n).nrows = 1; outstruct.NLC(count.NLC.n).nparnames = 0; outstruct.NLC(count.NLC.n).parnames = {}; ##outstruct.NLC(count.NLC.n).vnmatrix = []; outstruct.NLC(count.NLC.n).pvmatrix = []; ## convert input line string into cell array ca = str2ca (line); ## update parameter value and connectivity matrix ##[outstruct.NLC(idx).vnmatrix] = [add_nodes(ca(2:5))]; [outstruct.NLC(count.NLC.n).vnmatrix] = [add_nodes(ca(2:5))]; ## check if parameters are specified for prm_idx = 1:(length (ca)-5)/2 ## [tf, str_idx] = ismember (outstruct.NLC(count.NLC.n).parnames{prm_idx}, ca); ## TODO: can the loop be executed in a single operation? ## [tf, str_idx] = ismember (outstruct.NLC(count.NLC.n).parnames, ca); if (length (ca) >= 3+prm_idx*2) ## find specified parameter name ##if tf outstruct.NLC(count.NLC.n).npar++; outstruct.NLC(count.NLC.n).nparnames++; outstruct.NLC(count.NLC.n).parnames{1, prm_idx} = ca{2*prm_idx+4}; outstruct.NLC(count.NLC.n).pvmatrix(1, prm_idx) = literal2num (ca{2*prm_idx+5}); ##else ## TODO: set to a default value undefined parameters, instead of rising an error? ## errstr=sprintf("Undefined parameter %s in line: %s", outstruct.NLC(count.NLC.n).parnames{prm_idx}, line); ## error(errstr); ##endif else syntaxError (line); endif endfor outstruct = NLCintvar(outstruct, count.NLC.n, ca{1}); endfunction function [outstruct, count]= prs_spice_R (line, outstruct, count) element = "Mresistors"; ## check wheter the element type already exists in output structure [tf, idx] = ismember ({element}, count.LCR.list); if !tf ## update counters count.LCR.n++; count.LCR.list{count.LCR.n} = element; ##idx = count.LCR.n; ## if the element doesn't exists, add it to the output structure outstruct.LCR(count.LCR.n).func = element; outstruct.LCR(count.LCR.n).section = "LIN"; outstruct.LCR(count.LCR.n).nextvar = 2; outstruct.LCR(count.LCR.n).npar = 1; outstruct.LCR(count.LCR.n).nrows = 0; outstruct.LCR(count.LCR.n).nparnames = 1; outstruct.LCR(count.LCR.n).parnames = {"R"}; outstruct.LCR(count.LCR.n).vnmatrix = []; outstruct.LCR(count.LCR.n).pvmatrix = []; endif ## add an element to the structure ##outstruct.LCR(idx).nrows++; outstruct.LCR(count.LCR.n).nrows++; ## convert input line string into cell array ca = str2ca (line); if (length (ca) > 3) ## update parameter value and connectivity matrix ##[outstruct.LCR(idx).vnmatrix] = [outstruct.LCR(idx).vnmatrix; add_nodes(ca(2:3))]; ##[outstruct.LCR(idx).pvmatrix] = [outstruct.LCR(idx).pvmatrix; literal2num(ca{4})]; [outstruct.LCR(count.LCR.n).vnmatrix] = [outstruct.LCR(count.LCR.n).vnmatrix; add_nodes(ca(2:3))]; [outstruct.LCR(count.LCR.n).pvmatrix] = [outstruct.LCR(count.LCR.n).pvmatrix; literal2num(ca{4})]; else syntaxError (line); endif outstruct = LCRintvar(outstruct, count.LCR.n, ca{1}); endfunction function [outstruct, count] = prs_spice_V (line, outstruct, count) ## Sine ## SIN(VO VA FREQ TD THETA) ## ## VO (offset) ## VA (amplitude) ## FREQ (frequency) ## TD (delay) ## THETA (damping factor) ## ## 0 to TD: V0 ## TD to TSTOP: VO + VA*exp(-(time-TD)*THETA)*sine(twopi*FREQ*(time+TD) ## check if it is a sinwave generator sine = regexp (line, '(?SIN)[\s]*\((?.+)\)', 'names'); ## Pulse ## PULSE(V1 V2 TD TR TF PW PER) ## ## parameters default values units ## V1 (initial value) Volts or Amps ## V2 (pulsed value) Volts or Amps ## TD (delay time) 0.0 seconds ## TR (rise time) TSTEP seconds ## TF (fall time) TSTEP seconds ## PW (pulse width) TSTOP seconds ## PER (period) TSTOP seconds ## check if it is a pulse generator pulse = regexp (line, '(?PULSE)[\s]*\((?.+)\)', 'names'); if (! isempty (sine.stim)) ## sinwave generator ca = str2ca (sine.prms); if (length (ca) == 5) vo = literal2num (ca{1}); va = literal2num (ca{2}); freq = literal2num (ca{3}); td = literal2num (ca{4}); theta = literal2num (ca{5}); pvmatrix = [va freq td vo]; element = "Mvoltagesources"; section = "sinwave"; nextvar = 2; npar = 4; nparnames = 4; parnames = {"Ampl", "f", "delay", "shift"}; ## convert input line string into cell array ca = str2ca (line); vnmatrix = add_nodes (ca(2:3)); [outstruct, count] = addNLCelement (outstruct, count, element, section, nextvar, npar, nparnames, parnames, vnmatrix, pvmatrix); outstruct = NLCintvar(outstruct, count.NLC.n, ca{1}); else #length(ca) == 5 syntaxError (line); endif #length (ca) == 5 elseif (! isempty (pulse.stim)) ca = str2ca (pulse.prms); if length (ca) == 7 low = literal2num (ca{1}); high = literal2num (ca{2}); delay = literal2num (ca{3}); ## TODO: add rise and fall times! ## tr = literal2num (ca{4}); ## tf = literal2num (ca{5}); thigh = literal2num (ca{6}); period = literal2num (ca{7}) tlow = period-thigh; pvmatrix = [low high tlow thigh delay]; element = "Mvoltagesources"; section = "squarewave"; nextvar = 2; npar = 5; nparnames = 5; parnames = {"low", "high", "tlow", "thigh", "delay"}; ## convert input line string into cell array ca = str2ca (line); vnmatrix = add_nodes (ca(2:3)); [outstruct, count] = addNLCelement (outstruct, count, element, section, nextvar, npar, nparnames, parnames, vnmatrix, pvmatrix); outstruct = NLCintvar(outstruct, count.NLC.n, ca{1}); else ##length (ca) == 7 syntaxError (line); endif ##length (ca) == 7 else ##~isempty (tran.stim) ## DC generator element = "Mvoltagesources"; section = "DC"; nextvar = 2; npar = 1; nparnames = 1; parnames = {"V"}; ## convert input line string into cell array ca = str2ca (line); vnmatrix = add_nodes (ca(2:3)); pvmatrix = literal2num (ca{4}); [outstruct, count] = addLCRelement (outstruct, count, element, section, nextvar, npar, nparnames, parnames, vnmatrix, pvmatrix); outstruct = LCRintvar(outstruct, count.LCR.n, ca{1}); endif #~isempty(tran.stim) endfunction function [outstruct, count] = prs_spice_dot (line, outstruct, count) ## .MODEL MNAME TYPE(PNAMEl = PVALl PNAME2 = PVAL2 ... ) ## TYPE can be: ## R resistor model ## C capacitor model ## URC Uniform Distributed RC model ## D diode model ## NPN NPN BIT model ## PNP PNP BJT model ## NJF N-channel JFET model ## PJF P-channel lFET model ## NMOS N-channel MOSFET model ## PMOS P-channel MOSFET model ## NMF N-channel MESFET model ## PMF P-channel MESFET model ## SW voltage controlled switch ## CSW current controlled switch global models_list; model = regexp (line, '.MODEL[\s]+(?[\S]+)[\s]+(?R|C|URC|D|NPN|PNP|NJF|PJF|NMOS|PMOS|NMF|PMF|SW|CSW)[\s]*\([\s]*(?.+)[\s]*\)', 'names'); if !isempty (model) switch (model.mtype) case 'R' case 'C' case 'URC' case 'D' element = "Mdiode"; case 'NPN' case 'PNP' case 'NJF' case 'PJF' case 'NMOS' element = "Mnmosfet"; case 'PMOS' element = "Mpmosfet"; case 'NMF' case 'PMF' case 'SW' case 'CSW' otherwise syntaxError (line); endswitch ## get model level (=section) level = regexp (model.prms, 'LEVEL=(?[\S]+)[\s]+(?.+)', 'names'); if isempty (level.level) section = "simple"; else section = level.level; model.prms = level.prms; endif midx = length (models_list.mname)+1; models_list.mname{midx} = model.mname; models_list.melement{midx} = element; models_list.msection{midx} = section; ## set model parameters ca = str2ca (model.prms); midx = length (models_list.mname); models_list.plist{midx} = struct ("pnames", {""}, "pvalues", []); for prm_idx = 1:length (ca)/2 ## save parameter name models_list.plist{midx}.pnames{prm_idx} = ca{2*prm_idx-1}; ## save parameter value models_list.plist{midx}.pvalues = [models_list.plist{midx}.pvalues literal2num(ca{2*prm_idx})]; endfor endif #!isempty (model) endfunction ## adds nodes to nodes_list and returns the indexes of the added nodes function indexes = add_nodes (nodes) global nodes_list; for ii = 1:length (nodes) [tf, idx] = ismember (nodes(ii), nodes_list); if tf indexes(ii) = idx-1; else indexes(ii) = length (nodes_list); nodes_list{length (nodes_list)+1} = nodes{ii}; endif endfor endfunction %!demo %! outstruct = prs_spice ("rlc"); %! vin = linspace (0, 10, 10); %! x = zeros (outstruct.totextvar+outstruct.totintvar, 1); %! %! for idx = 1:length (vin) %! outstruct.NLC(1).pvmatrix(1) = vin(idx); %! out = nls_stationary (outstruct, x, 1e-15, 100); %! vout(idx) = out(2); %! end %! %! plot (vin, vout); %! grid on; %!demo %! ## Circuit %! %! cir = menu ("Chose the circuit to analyze:", %! "AND (Simple algebraic MOS-FET model)", %! "AND (Simple MOS-FET model with parasitic capacitances)", %! "Diode clamper (Simple exponential diode model)", %! "CMOS-inverter circuit (Simple algebraic MOS-FET model)", %! "n-MOS analog amplifier (Simple algebraic MOS-FET model)", %! "Linear RC circuit", %! "Diode bridge rectifier", %! "RLC circuit"); %! %! switch cir %! case 1 %! outstruct = prs_spice ("and"); %! x = [.5 .5 .33 .66 .5 1 0 0 1 ]'; %! t = linspace (0, .5, 100); %! pltvars = {"Va", "Vb", "Va_and_b"}; %! dmp = .2; %! tol = 1e-15; %! maxit = 100; %! case 2 %! outstruct = prs_spice ("and2"); %! x = [.8;.8;0.00232;0.00465;.8; %! .8;0.00232;0.00465;0.00000; %! 0.0;0.0;0.0;0.00232;0.0; %! 0.0;0.0;0.0;1.0;0.0;-0.0; %! 0.0;1.0;0.00465;0.0;0.0; %! -0.0;1.0;0.00465;0.0; %! 0.0;0.0;1.0;1.0;0.0;0.0;0.0; %! 0.0;0.0;0.0]; %! t = linspace (.25e-6, .5e-6, 100); %! dmp = .1; %! pltvars = {"Va", "Vb", "Va_and_b"}; %! tol = 1e-15; %! maxit = 100; %! case 3 %! outstruct = prs_spice ("diode"); %! x = [0 0 0 0 0]'; %! t = linspace (0, 3e-10, 200); %! dmp = .1; %! pltvars = {"Vin", "Vout", "V2"}; %! tol = 1e-15; %! maxit = 100; %! case 4 %! outstruct = prs_spice ("inverter"); %! x = [.5 .5 1 0 0]'; %! t = linspace (0, 1, 100); %! dmp = .1; %! pltvars={"Vgate", "Vdrain"}; %! tol = 1e-15; %! maxit = 100; %! case 5 %! outstruct = prs_spice ("nmos"); %! x = [1 .03 1 0 0]'; %! t = linspace (0, 1, 50); %! dmp = .1; %! pltvars = {"Vgate", "Vdrain"}; %! tol = 1e-15; %! maxit = 100; %! case 6 %! outstruct = prs_spice ("rcs"); %! x = [0 0 0 0]'; %! t = linspace (0, 2e-5, 100); %! dmp = 1; %! pltvars = {"Vout"}; %! tol = 1e-15; %! maxit = 100; %! case 7 %! outstruct = prs_spice ("rect"); %! x = [0 0 0 0 ]'; %! t = linspace (0, 3e-10, 60); %! dmp = .1; %! pltvars = {"Vin", "Voutlow", "Vouthigh"}; %! tol = 1e-15; %! maxit = 100; %! case 8 %! outstruct = prs_spice ("rlc") %! #x = [0 0 0 0 0]'; %! #x = [0 0 0 ]'; %! #x = [0 0 0 0]'; %! x = [0 0 0 0 0 0 ]'; %! t = linspace (0, 2e-5, 200); %! dmp = 1; %! #pltvars = {"Vin", "Vout"}; %! pltvars = {"I(C3)"}; %! #pltvars = {"Vout"}; %! tol = 1e-15; %! maxit = 100; %! otherwise %! error ("unknown circuit"); %! endswitch %! %! clc; %! slv = menu("Chose the solver to use:", %! "BWEULER", # 1 %! "DASPK", # 2 %! "THETA", # 3 %! "ODERS", # 4 %! "ODESX", # 5 %! "ODE2R", # 6 %! "ODE5R" # 7 %! ); %! %! out = zeros (rows (x), columns (t)); %! %! switch slv %! case 1 %! out = tst_backward_euler (outstruct, x, t, tol, maxit, pltvars); %! # out = TSTbweuler (outstruct, x, t, tol, maxit, pltvars); %! case 2 %! out = tst_daspk (outstruct, x, t, tol, maxit, pltvars); %! # out = TSTdaspk (outstruct, x, t, tol, maxit, pltvars); %! case 3 %! out = tst_theta_method (outstruct, x, t, tol, maxit, .5, pltvars, [0 0]); %! # out = TSTthetamethod (outstruct, x, t, tol, maxit, .5, pltvars, [0 0]); %! case 4 %! out = tst_odepkg (outstruct, x, t, tol, maxit, pltvars, "oders", [0, 1]); %! # out = TSTodepkg (outstruct, x, t, tol, maxit, pltvars, "oders", [0, 1]); %! case 5 %! out = tst_odepkg (outstruct, x, t, tol, maxit, pltvars, "odesx", [0, 1]); %! # out = TSTodepkg (outstruct, x, t, tol, maxit, pltvars, "odesx", [0, 1]); %! case 6 %! out = tst_odepkg (outstruct, x, t, tol, maxit, pltvars, "ode2r", [0, 1]); %! # out = TSTodepkg (outstruct, x, t, tol, maxit, pltvars, "ode2r", [0, 1]); %! case 7 %! out = tst_odepkg (outstruct, x, t, tol, maxit, pltvars, "ode5r", [0, 1]) %! # out = TSTodepkg (outstruct, x, t, tol, maxit, pltvars, "ode5r", [0, 1]) %! otherwise %! error ("unknown solver"); %! endswitch %! %! #utl_plot_by_name (t, out, outstruct, pltvars); %! utl_plot_by_name (t, out, outstruct, pltvars); %! axis ("tight"); ocs/inst/nls/nls_newton_raphson.m000644 000765 000000 00000006370 12207456226 017763 0ustar00carlowheel000000 000000 ## Copyright (C) 2006-2009 Carlo de Falco ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## author: Massimiliano Culpo ## -*- texinfo -*- ## @deftypefn{Function File}{[@var{y},@var{numit},@var{resnrm}] =} @ ## nls_newton_raphson (@var{y0},@var{RES},@var{JAC},@var{tol},@ ## @var{maxit},@var{verbosity},@var{update}); ## ## Solve a non-linear system of equations using the Newton-Raphson ## method with damping and return the computed solution vector @var{y}. ## ## The initial guess for the algorithm is set to @var{y0}. ## ## The Jacobian and residual at each step are computed via the function ## handles @var{RES} and @var{JAC}. ## ## The variables @var{tol} and @var{maxit} are the relative tolerance on the ## error of the computed solution and the maximum number of iterations to be ## performed by the algorithm. ## ## The optional parameter @var{verbosity} produce verbose output if non-zero. ## ## The optional function handle @var{update} may be used to provide ## a faster mean to update Jacobian and residual at runtime. ## ## @var{numit} is the number of performed iterations while @var{resnrm} ## is a vector containing the residual norm at each step. ## ## @seealso{nls_stationary,tst_backward_euler,tst_theta_method,tst_daspk,tst_odepkg} ## @end deftypefn function [y,ii,resnrm] = nls_newton_raphson(y0,RES,JAC,tol,maxit,... verbosity,update); ## Check input ## FIXME: add input check! if ((nargin < 5) || (nargin > 7)) error("nls_newton_raphson: wrong number of input parameters."); endif if ~exist("verbosity") verbosity = 0; endif if ~exist("update") update = @(x) ({}); endif jjtot = 0; y = y0; uptodate = update(y); res_y = RES(y,uptodate{:}); resnrm(1) = norm(res_y,inf); for ii = 1:maxit jac_y = JAC(y,uptodate{:}); ynew = jac_y\(-res_y+jac_y*y); uptodate = update(ynew); res_y = RES(ynew,uptodate{:}); resnrm(ii+1) = norm(res_y,inf); jj = 0; while ((resnrm(ii+1)>resnrm(ii))&&(jj<10)) jj++; damp = 2^(-jj); ynew = y*(1-damp) + ynew*damp; uptodate = update(ynew); res_y = RES(ynew,uptodate{:}); resnrm(ii+1) = norm(res_y,inf); endwhile jjtot += jj; y = ynew; if resnrm(ii+1). ## ## author: Carlo de Falco ## -*- texinfo -*- ## @deftypefn{Function File} {[@var{out}, @var{niter}]} = nls_stationary @ ## (@var{instruct},@var{x},@var{tol},@var{maxit}) ## Compute the stationary state solution @var{out} of the system described ## by @var{instruct}. ## ## @var{x} is the initial guess used by the Newton-Raphson algorithm implemented in ## @code{nls_newton_raphson}, while @var{tol} and @var{maxit} are the corresponding ## parameters. ## ## The optional output @var{niter} returns the number of Newton iterations ## needed to reach convergence. ## ## @seealso{nls_newton_raphson} ## @end deftypefn function [out, varargout] = nls_stationary(outstruct,x,tol,maxit) ## Check input ## FIXME: add input check! if nargin != 4 error("nls_stationary: wrong number of input parameters."); endif [A0,B,C] = asm_initialize_system(outstruct,x); JAC = @(x) TSTSTATFUNJAC(outstruct,x,B); RES = @(x) TSTSTATFUNRES(outstruct,x,B,C); UPD = @(x) TSTSTATUP(outstruct,x); [out,ii,resnrm] = nls_newton_raphson(x,RES,JAC,tol,maxit,0,UPD); if nargin > 1 varargout{1} = ii; endif endfunction ## Jacobian for steady state problems function lhs = TSTSTATFUNJAC(outstruct,x,B,Jac,res) if nargin < 5 [A1,Jac,res] = asm_build_system(outstruct,x,0); endif lhs = (B + Jac); endfunction ## Residual for steady state problem function rhs = TSTSTATFUNRES(outstruct,x,B,C,Jac,res) if nargin < 6 [A1,Jac,res] = asm_build_system(outstruct,x,0); endif rhs = (res + C + B*x); endfunction ## Update for transient problem function update = TSTSTATUP(outstruct,x) [A1,Jac,res] = asm_build_system(outstruct,x,0); update = {Jac,res}; endfunctionocs/inst/asm/asm_build_system.m000644 000765 000000 00000006413 12207456226 017370 0ustar00carlowheel000000 000000 ## Copyright (C) 2006,2007,2008 Carlo de Falco, Culpo Massimiliano ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## author: culpo@math.uni-wuppertal.de ## -*- texinfo -*- ## @deftypefn{Function File} {[@var{A},@var{Jac},@var{res}] =}@ ## asm_build_system(@var{instruct},@var{x},@var{t}) ## ## Cycle through the circuit description structure @var{instruct} ## to build the system matrices @var{A}, @var{Jac}, @var{res} for ## the current step of the Newton method. ## ## @var{x} is the current value of the state variables, while @var{t} is the current time point. ## ## See the @cite{IFF file format specifications} for details about ## the output matrices. ## ## @seealso{asm_initialize_system,prs_iff} ## ## @end deftypefn function [A,Jac,res] = asm_build_system(instruct,x,t); ## Check input if nargin != 3 error("asm_build_system: wrong number of input parameters."); elseif !(isstruct(instruct) && isfield(instruct,"LCR") && isfield(instruct,"NLC")) error("asm_build_system: first input is not a valid structure."); elseif !isvector(x) error("asm_build_system: second input is not a valid vector."); elseif !isscalar(t) error("asm_build_system: third input is not a valid scalar."); endif n = instruct.totextvar + instruct.totintvar; A = sparse(n,n); Jac = sparse(n,n); res = sparse(n,1); ## NLC section nblocks = length(instruct.NLC); for ibl = 1:nblocks for iel = 1:instruct.NLC(ibl).nrows ## Evaluate element if instruct.NLC(ibl).nintvar(iel) intvars = instruct.totextvar+instruct.NLC(ibl).osintvar(iel) + ... [1:instruct.NLC(ibl).nintvar(iel)]'; else intvars=[]; endif il = instruct.NLC(ibl).vnmatrix(iel,:)'; nzil = find(il!=0); y = zeros(size(il)); y(nzil) = x(il(nzil)); z = x(intvars); [a,b,c] = feval(instruct.NLC(ibl).func,... instruct.NLC(ibl).section,... instruct.NLC(ibl).pvmatrix(iel,:),... instruct.NLC(ibl).parnames,... y,z,t); ## Assemble matrices ## Global indexing vars = [il(nzil);intvars]; ## Local indexing lclvars = [nzil; instruct.NLC(ibl).nextvar + (1:length(intvars))' ]; ## Reshaping sparse stamps a = a(lclvars,lclvars); b = b(lclvars,lclvars); c = reshape(c(lclvars),[],1); [na,ma,va] = find(a); [nb,mb,vb] = find(b); [nc,mc,vc] = find(c); ## Stamping A += sparse(vars(na),vars(ma),va,n,n); Jac += sparse(vars(nb),vars(mb),vb,n,n); res += sparse(vars(nc),1,vc,n,1); endfor endfor endfunctionocs/inst/asm/asm_initialize_system.m000644 000765 000000 00000006571 11703660103 020426 0ustar00carlowheel000000 000000 ## Copyright (C) 2006,2007,2008 Carlo de Falco, Culpo Massimiliano ## ## This file is part of: ## OCS - A Circuit Simulator for Octave ## ## OCS is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program (see the file LICENSE); if not, ## see . ## ## author: Carlo de Falco ## author: culpo@math.uni-wuppertal.de ## -*- texinfo -*- ## ## @deftypefn{Function File} {[@var{A},@var{B},@var{C}] =}@ ## asm_initialize_system(@var{instruct},@var{x}) ## ## Cycle through the circuit description structure @var{instruct} ## to build the system matrices @var{A}, @var{B}, @var{C} for ## the linear and time-invariant part of the system. ## ## @var{x} is the current value of the state variables. ## ## See the @cite{IFF file format specifications} for details about ## the output matrices. ## ## @seealso{asm_build_system,prs_iff} ## ## @end deftypefn function [A,B,C] = asm_initialize_system(instruct,x); ## Check input if nargin != 2 error("asm_initialize_system: wrong number of input parameters."); elseif !(isstruct(instruct) && isfield(instruct,"LCR") && isfield(instruct,"NLC")) error("asm_initialize_system: first input is not a valid structure."); elseif !isvector(x) error("asm_initialize_system: second input is not a valid vector."); endif ## Build linear part of the system n = instruct.totextvar + instruct.totintvar; # Number of variables ## Initialize to zero any state variable that is not in the input argument lx = length(x); if lx < n x(lx+1:n) = 0; endif ## FIXME: should a warning be passed if lx != n ? A = sparse(n,n); ## LCR section B = sparse(n,n); C = sparse(n,1); nblocks = length(instruct.LCR); for ibl = 1:nblocks for iel = 1:instruct.LCR(ibl).nrows ## Evaluate element if instruct.LCR(ibl).nintvar(iel) intvars = instruct.totextvar + instruct.LCR(ibl).osintvar(iel) + [1:instruct.LCR(ibl).nintvar(iel)]'; else intvars=[]; endif il = instruct.LCR(ibl).vnmatrix(iel,:)'; nzil = find(il!=0); y = zeros(size(il)); y(nzil) = x(il(nzil)); z = x(intvars); [a,b,c] = feval(instruct.LCR(ibl).func, instruct.LCR(ibl).section, instruct.LCR(ibl).pvmatrix(iel,:), instruct.LCR(ibl).parnames, y,z,0); ## Assemble matrices ## Global indexing vars = [il(nzil);intvars]; ## Local indexing lclvars = [nzil; instruct.LCR(ibl).nextvar + (1:length(intvars))' ]; ## Reshaping sparse stamps a = a(lclvars,lclvars); b = b(lclvars,lclvars); c = reshape(c(lclvars),[],1); [na,ma,va] = find(a); [nb,mb,vb] = find(b); [nc,mc,vc] = find(c); ## Stamping A += sparse(vars(na),vars(ma),va,n,n); B += sparse(vars(nb),vars(mb),vb,n,n); C += sparse(vars(nc),1,vc,n,1); endfor endfor endfunctionocs/doc/and.cir000644 000765 000000 00000001103 11005317740 014077 0ustar00carlowheel000000 000000 % 0.1b1 % A Simple CMOS AND GATE % % N-Mosfets % There are 3 N-Mosfets Mnmosfet simple 4 3 3 3 k Vth rd 1e-4 0.1 1e7 1e-4 0.1 1e7 1e-4 0.1 1e7 1 3 4 0 2 0 3 0 4 0 5 0 % % P-Mosfets Mpmosfet simple 4 3 3 3 k Vth rd -1e-4 -0.1 1e7 -1e-4 -0.1 1e7 -1e-4 -0.1 1e7 1 6 4 6 2 6 4 6 4 6 5 6 % % Input voltage sources Mvoltagesources sinwave 2 4 2 4 Ampl f delay shift 0.5 1 0.0 0.5 0.5 2 0.25 0.5 1 0 2 0 END % % Power supply Mvoltagesources DC 2 1 1 1 V 1 6 0 ENDocs/doc/and.nms000644 000765 000000 00000000063 11005317740 014123 0ustar00carlowheel000000 000000 % 0.1b1 1 Va 2 Vb 5 Va_and_b 6 Vdd 7 I1 8 I2 9 I3 ocs/doc/and.spc000755 000765 000000 00000000731 11706574500 014127 0ustar00carlowheel000000 000000 * AND (simple Algebraic MOS-FET model) .MODEL mynmos NMOS(LEVEL=simple k=2.94e-05 Vth=0.08 rd=.957e7) .MODEL mypmos PMOS( k=-2.94e-05 Vth=-0.08 rd=.957e7) M1 Va 3 4 0 mynmos M2 Vb 0 3 0 mynmos * nside of the inverter M3 4 0 Va_and_b 0 mynmos M4 Va Vdd 4 Vdd mypmos M5 Vb Vdd 4 Vdd mypmos * pside of the inverter M6 4 Vdd Va_and_b Vdd mypmos V1 Va 0 SIN(0.5 0.5 1 0 0) V2 Vb 0 SIN(0.5 0.5 2 0.25 0) V3 Vdd 0 1 .END ocs/doc/and2.spc000755 000765 000000 00000000765 11706574500 014220 0ustar00carlowheel000000 000000 * A Simple CMOS AND GATE * models declarations .MODEL mynmos NMOS(LEVEL=lincap k=4.354e-5 Vth=0.7 rd=1e6 Cb=13e-14) .MODEL mypmos PMOS(LEVEL=lincap k=-4.354e-5 Vth=-0.7 rd=1e7 Cb=13e-14) * N-Mosfets M1 Va 3 4 0 mynmos M2 Vb 0 3 0 mynmos M3 4 0 Va_and_b 0 mynmos * P-Mosfets M4 Va Vdd 4 Vdd mypmos M5 Vb Vdd 4 Vdd mypmos M6 4 Vdd Va_and_b Vdd mypmos * Input voltage sources V2 Vb 0 SIN(0.8 -0.8 4MEG -0.0625u 0) * Power supply V1 Va 0 1.6 V3 Vdd 0 1.6 .END ocs/doc/AND_BW.png000644 000765 000000 00000023113 11005317740 014343 0ustar00carlowheel000000 000000 ‰PNG  IHDR Xb%± IDATxœíÝÙ¶£¸@|Wÿÿ/û>ÐE»cRJOUgðÁr²IÄôz¿ßçü¯öDb°¬+ÁJ`°¬+ÁJðOÆ×z½^ó?NîÌ?s"õÞ‘s°¦Ä%Îõö2Óëõ:x5«á¿Î”yþÁZÖ‹'Ýÿ£ÛaÚ¾fþÁª2‘÷.ô¯Ì™Õ‡yèwjÍ|Öy>ÁJ`°<=XU‹\|«a‚áëNô?XSr¸€¿“Ñ>ABeU/ŠêâeVÅÏ,a°¬°2+Aòj8rr%Vj%ö4¸§ëÎîi5?5Xóî©F®ð âõY+OÖ{øÁš¯ë±$éa°c°Ø&¨¿»“÷_d|Íÿ^<©²²œ~—Õ0Á•€v¿Ge%0Ÿ ôò8ƒ˜–Y»ã2Ί,³TÛÝ)×:–£²Ø‘N`°¬+ÁJ`°¬+Áz°¶]uöiߌ¯ö0|«aƒ•À`%0X Ö_Ž7Ö¶† TVƒ•À`%0X Vƒ•@ë@e%0X Vƒ•À`%0X Vƒ•À`%È»à¤{Ÿÿù,ô&»;ÿù9îkßîM–ïfVЛÿ´[C£ü·qß=™zôÁZ*h;4ùWÃn¬†Æjx—ÁJ`°¬+ÁJÐù`mŸFávÁ_-íR–]àNë`¯eõ•;£ÖÉ`}‚¼s* Ö3 Vƒ• ø}Js½B îSÊ×ÁÊU }ÔÔ¬xfLE†sv°îßࣃuùìAÖ›oµƒ‘š´I VwfKáfcÏ«•€ gÑôÒwȬ½eVѾõ¶]H«a‚‡¶†!VáŸÒëÖÃã×ÅÕðÂ;yÇ.VÞãqQd¸Åyë×I_ÏVÞ=]wp9/8/׫3X±Æh¡)M`°¬+ÁJ`°¬+A'ƒõÌþ©ÀTÖ3 Vƒ•À`%0Xÿùy€ÖÖ0ÊJ`°¬+ÁJ`°h(ÂZH ‹"E(,ŠPX¡°(âî™·ãœý> [—™Ç¢›BŠh´°ÆÙÂöúN-,*ÊRë ‹µÝ¶;õ’åú…Uq[ððŸþq&aÛ-ZÝ®ñç>_ýª¨©=â* ó~¿S£èärÖ¹‚ü§¦>ò¢ª¿ÓocºyK„F ‹ênVüЛBÊQX¡°(¢óÂêu^»}Võ}®aÙ+ì\­)vžXú¼YÀnUíþ@vNô³¹iÊçDZûÑüü,î&VËUUôI %\XàfßcÏ=VËE¿ëÂ7û‹ôXÍ®F<¦Ha½ßïfפç=°Ž5¸ç/¬×Ù_ùä_¯òw<°Ž5¸gë±–ÝÃß$ÏË–XµêI?צ OlÊøÃèçÚ”³ÇÚ­!Ÿú˜rV 5ÔÂ209VH! «²^÷<E”*¬NÌg¨þ¯àAèê%uf†ú°ŸTª°ZøÀÎ/ƒ³Ê²ÓcMSÕՠׂ.^XÕ7ˆTQ¼°z]#9fSH½–-o#Jš¼úÇö[娭”M¬Z7{þ²Rêœ÷ÝØØ.R]*•X?/•¤o½5ïj·½PX¡°(BaQ„¢…E ‹"E(,ŠPXñ£°Îœ‚Òòi*-/Û®p ü«S(¦"E(,ŠPX¡°øêÎ.ª½BŠX¡°(BaQ„¢…E ‹"L7P„Ä¢…E ‹"E(,ŠPX¡°(BaQ„¢…E ‹"E(,ŠPXq÷ «ÝÜÄ‚­;§TÅ;+ïcv[~hoËËö“M!E(,ŠPXq·y/dµO¥ÕXZ–v8¾-LܦjåzaÍCS¨Á,:¾M}xM-LF× «×aúÈÑËŸòÝ+nyµ°A\4µ0Ó4½ÿ˜¾,ÛÏ·yÿö|á*šZ˜•Ýeû( «Üˆ7·-ÔÖ·¸0P kõ®šª†¼ª¿Ó3ñdõ(, ¹'Ë]ak["'D2;þ1…ž¥ÑgÍ?ÓCóN9'#êBóøÄŒ,BŸšRÎý ÒFR×ý•ͦphåfÎÖÐÊÍÊ*¬Ñj1E(,ŠPX¡°(¢çª~ÊÈz.¬3L»â€EŒžX¢°(BaÅömåóë×.³¹IaÅv¦E®ÒF+¬®œ9iø «Ÿçåíž°°»e,Z‚¦(¢çÄjd£p^ê·³áÛê¹°¦–jëd´³À7ÙRÄÝÄZu‚ݬpÜT$±\SEç=µä,,[íaGÃ6‹"l )"sa¼ÇMvÃnqš•ùÞ ŸVû†#+¸)lᦚԒ§°2Þ•>ä)¬Ï‚?™RÛ~NF6"ç¦ðäMAÙMaiËÓ>¿ReIXɹ)ܲaVÁ½BÓ #Ë<µ:ù:P¡Ç )BaQ„ª£ûýe…E ‹"E” í¾“¸¯×!*ø&3d#³)¬¬×Õ/ÿ!e¤æ¯8p?·2½~¨-ÈYX«£ÎÕ?¶ê 0²ü'úÁä 4…ä¿Ä>¢¸Kެ̉ñä¾f—yUîm.ä7¥Æ´ÙO‹g”šÇrµêàä E˜y§…EeÏnØýwé¿E JÖöðŽÏ~(E kw®Am ¥Ha­NpØ~î•mÞV’³L{U|¯ðø¦YÙ¯ÄW¦(^Xgnš•±trhb+ohéäZÐDaÑŸ‡z¬;?@DBS„M!E¼`µ5fkŸdSH6…¡°(BaQ„¢…E ‹"E(,ŠPX¡°(BaQ„¢…E ‹"E(,ŠPX¡°(⨰vo¬°úbËoµ¼l»Â-ð‰E.¦ ‰E ‹"E(,ŠPX¡°(BaQ„¢…E ‹}7oÁ¯°øêÎá>Ç )BbQ„¢…E ‹"E(,ŠPX¡°(BaQ„¢…E ‹"E8»ÖC`a, „!°€0†ÀÂX@ C`a, „!°€0þ©ûç?ŸÏú¾óÙ} Ë{lð /ÛÁ›AÐÏ´o:, ÷ÃzÂëÕî8·¼l-3nUè°€0FµÀš§-ï<MÀ ºÿ(^Ï/jÄâŽÕÈúL™ªï¾ßoœT'°–œ ÚjÁh‹'{ŽjÖœSÒªí7FfåçùÃó·ŽÇ-ר:J˜AÄ·©øæÌê7ˆ¤Kž7•aˆÎÄI‡‡ùL³¸ð¿ýÊç×ï|:ë®Á/¸ë’Ïtº+?ÃÞXuWIJ¶¿óÍ€Qõ­.BÑÑX#j…L2Ôȼ^¯ãÃô6lyû©-ƒz¿ßÇSuIóèßšÓ¼í¼Ó F?¬Ë·ß囪ë`H/´i—?Ê7ðBøyֵ零K„!°`h± ,Z¬É>„!°€0†ÀÂX@NÍ&ÖáaˆH`eëð0Dd—C`a, ŒvË6]J-ìù6{ÿ]½æÁŠ;xÜz»e›.}Þ3ïÌc¨çÛì­¾rüúßþ›ëIµXЫ9³¶÷½K½]çîwO&QЇ®×¿1cõ›CV_²ó™öªæyXsU),dÕ—=¼þÚ…ÜM¸…/mœ;#óÀÇý+> ÍVHK­Ä*ôgÌcrsdŒðŠ;F•/͉ØÝ4¸•Vz„}‚Tî°v?³ƒ“J€‘µ¸K¸pÝö_ò FÖb`M™¦!DèÍXè…^£õãSk»’N,°`ÑÁ•qŸºy#E¹_[VÓvÇE<øÆyyû¡Wõ,g£ÝÀ:8ãa¨“!Æy§—…¢Ð ÿ¼w žG;+ôv¸ ­ÀJ:å_lÁhÚ ¬Ý³®Ìãe˜=4‡uþ=Ÿ¿²œµŠÎ{+²–!˱°b<7鞺ά„Ô™Ûž%ij Lí,T×Ö.áAñíêù–›# ¯¶+i½âMy€*Ú ¬ÙÏØU0¦köó<,`4íÖ˜òO€Î, ÅXÎ<»”fµ{ñ3YÄ}4 lé°:çé/ôD‡Õ?QE7tX@Á:¬Ýçèè Ø:?›žeÞ]>#X`m)¶ªb÷òr›½(¢– »v}’ƒ†» EMÏaÜkE…Á€šî°¤ÒkƒcH ­ÅÀÊuò±•3Õ˜;ÚgîÂF#Z ,URË#ïòòЂÍamÀµ`7@i:°Ž·~Ÿwy·Ö]¦Å w OrÄFÓt‡•D“E-züÇî°fú,ªS{é§Ãº×C`õÔ»&X«ÕØ£UaÁëÌ¿IOc Xçg7;›•¿0 ¬o“;Çkr7ëygù ׄ ¬•ϳ>S)5¡æŸï&× oáÏÚþάÔN$Dç2æM`+L‡µê¤¶ß}~ñüz~r³i³05¥þK½}°Óå!„H5;¸CÃòE¹]Š:‡µI×rêø4ÔêÜÍæš6î‹·K K`a, „!°€0†ÀÂX@ C`a, „!°€0†ÀÂX@ C`a, „!°€0®?̦͇$¨õ,Oß°K„!°€0†ÀÂX@ C`a, „!°€0†ÀÂX@ C`a, „!°€0†ÀÂX@ C`a, „!°€0<ªC‡„!°€0†ÀÂX@ C`a, „!°€0†ÀÂX@ C`a, „!°€0†ÀÂX@ C`a, „!°€0†ÀÂø§îŸ½^ó?ÞïwÝ%¹ãø]Ìßmó ,[Íeq?Ó¾½êúR@ µr£r‡µ½±Š»5Öa}÷3}@Å>£r‡Õ׫ÑìòM7øÛ?PqdLºa, „!°€0†À¨XNΫsâèrGã繬Î7 ¯Ç‹ÝøGPZÐÏtXõ¯% ´ÂZÔ•¸K^𑉥Î.áR%Ê8Ϥ;¦bŸQy d5å÷üZ\y—Д'´ïõz-7¨˜MÖâå[Ϩ¼KºÏ’¶ôä[=ÏûCßVÕù['×…û«Œ9¬ëÎNÔÉÙ›ŸëB®;ˆ ¬[d;H«í׿­ yov(°îŠ»W+jy@ÞºÀ—öc©ããv,K± ¬ÊZŽŒ¸Í#÷]«ÌƒßÊ[k\ΆãŸ§>Ü,95(iÅc’N}8&°niy‡î˜´ÓR±Ÿð™K+Ï%ŒH“BPqKW`]ô#‡“ç‚fyåÏ>îþ9Y õ³Ï:øÝoí~1ïvÝ ê™]„¼3e Ø—thï[;–÷Ö, †óy¬ðø'OfÖc³øQ´æò÷xM÷FûhŽg¬¦/»?çÑ·ygÒ(èÛnÝÁ}²¶¿›…ÀÎZ®¬Õ{šÃÂX@ ØÑ敆 Xkö©ÀþÒlZM X]ŸÜlZM XNgo<­&LN°j<­&ÌÚO«I`, „!°€0†ÀÂX@nàÒr-Eˆsg •ÍåÛqܹÇý{€ˆ<Xy\^í¯]½¥ÃbLæ°BŠråä%°€0†ÀÂX@ C`a4XËFm> î¸PÕg~åõÇñïv°N9qž³:uîÌiÃgζûö3«¯wpâ^sôí³Í9™ IÒ·î ½š9ûÊc(-ÎaMßÁg>cË¥ì Vê9U£µ²äWèê„o$×I1 ¶:XÉVJ` ¶¾=Ǿ ,Bê,¡:8I`5­ƒ½ŽE¹Ý`#Z¬ê·d­k´÷; q’FkÙì|{<‘Ôb`ïÏÏß²Ïjî´†“I䞥0 ¶+©o-³†z³°«­Àâ»À0µX©ëä ë°´‚YCµ½›ûâüouIZÁ¬¡ÀÚÚ=­¡'nAI:­áÂ:¹º½ÌçÍüV)ÖÁ ÿ횸\o­ïÜgÖ™æòÊwmüyín–·ÖA Ã¬é]ÂÅrCgÓÏï?~FÜÀ¢¡À:^o¿ÝÀ¯§üÚ5Úéfp ¡ÀšÒ»‰AÖd™³¶‹oºo$ጶ+©•èl> ø©­ÀšNg–´‚µx{™%³v#Éý°`X-Ö´÷ÌçåëD•ö®i4°Vl`ÑÜ'9Ñ , „!°€0†ãëQ97‚é°€0Z?‹;¶§ÝÖZÈB`õLBÑÕ¹Ÿwa†@Vçä=1éÓäR§ 8G$ Åè¤U ±KÏ}Ò*Ø“îJ][2ÏÖ-v`Á®óñáÙÚ±Ø%ÂXæJÉÅ–/ŠÀ5rZÍ+Ø…ÕìõG… ̳µ£9‡õY[#ÇÖ¤5ÈgάÁË©}!KU-R‡BÀPWí X\n¬“„Öè–FØj1°L%“ èX°Àš ,^`Íý”†/°¦½&Ë<µ¸ÅØ“‚MºÏ¶Ù$­¨Eí=)d‡ŒI`a, „!°¢2×Ë€¢ÖîQd‡–¡oñëàâA×è@߂֙DÝÿz)°ÎŸÎ.³ K‘+išÙœ4ô'L`]è˜4YЙ0µí˜~æ‘& :&°¶²äQû×Ù7¾xð¤õ¹ßYŸÛè±ÛæÀ§úu!,>×aëóOÍÆ1¤ªX÷]n”ÚJ{³ U„¼ßÊrÖÕ…Õ["@ a:¬ãîiyvÎù_¹óÃ@a«t÷Ôx«%Oa XÓ#S³¹àb#˜bÖù•¶Ë³ú{G*R`Mç2ëNZ hY°ÀšozuùXá·š/°f7ðËø‚@Sz8ë¦UoÕTrý<™ã±%¬¦Wûƒe³Ë€¢îX@ ÃVŸV3\-X€óVŸD]²K„!°€0†ÀÂX@ C`a, „!°€0†ÀÂX@ C`a, „!°€0†ÀÂX@ C`a, „!°€0†ÀÂX@ C`a, „!°€0†ÀÂX@ ãõ~¿¯üÚëµüûç+Ì?¼ûcËë\[Œa·ÒŒp›20šZ9þÏý—Ða=ϸ•f„TìW.vXÀ°^¯j¹aÒC`a, „!°€0†ÀÂX@ C`a, „!°€0†ÀÂX@ C`a¸E2† #ÃSs€A¬ž—óüþ™]B »„@š×ëUëÑ„:, †ÀÂX@ C`a, „!°€0†ÀÂX@ C`a, „!°€0†ÀÂX@ C`a, „!°€0†ÀÂX@ ãõ~¿k/@Wìd¦ÁÈLƒ™ 3 @f,€Ì4X™i°2Ó`d¦ÁÈLƒ™ 3 @f,€Ì4X™i°2Ó`d¦ÁÈLƒ™ 3 @f,€Ì4X™i°2Ó`d¦ÁÈLƒÙ?µ ¦×ëµýâûý~~I˜-ŸHê§pùgÀ¹@ÙÀ¯‘ ]ƒÕŽËŸ…ñÎÊÎsˆ(k·Éµ‘¤:‡fÀ¹@ÙpÁë5\¿1ܦq—WÂ×Þ, 8(R øÑ;D™ 3 @f,€Ì4X™x'w— EÕ`Í—‰ê«€¢:D8wW¯µ—(¼ƒ1¼<¼ÚßœTÇ…¡l œ±f°¦½\ðîg@QÍ`>X{)€þ Ô`M{=–ãƒË·³œçMíç×»?zÄs°>oÓ »ªB_û0N*53² Ÿþ¼a=ت.[ÞÝ;%-¿~aiO.XöWþi¸krýK–]ŸÅ3 8©Ô 'ì`Ž+ês~ëfÉ­¸Š¯ŸÍ²¡WÕ Õ!B꫾Ÿ1Îʆ6mooYkIV4XTf‡øaœTZ+šµ ´v®ãÑ`QÔ~˜'•š‰nuçôÕ·iDz¥Á¢©ý0N*5ÓŸíLO;“=—µü< 4Rýã0à¤R3#¸Ö‹<Ö–\¼mãXl‰Òh°€—{¬¤Û‡žo•^.,U!nÓ#ºp£©ÕïNfŒ’^v÷†ò%Ô`@ÿ¶mÇÍF$ãš—åÉõR-Ð`QÊå©ÚnÖ®‡p.P6ãX×Ëõ$Á¤6ëÛ\n­¶“pL_MÓÔÊrPQ;å8ÕX˜¦Þþóû4õI5µ0dwçó]z¸Ÿ¯pþ'ƒ2ƒäq0GÕìå~…¸Š 3 @f,€Ì4X0¢ ×6u'ÏÆi°`DŸwXø©³›T=@ƒãúÙfi­®Ñ`Àèv/¨µºCƒü5•¥µºÏF€iªr1ƒ™ 3 @f,€Ì4X™i°2Ó`dæ>Xð¨å^Én6Ð1 ¿ÈÁ_9þî÷û}ù•mªZ ÁJ£dùÖ…l[ׇ“/¾¼ÈÏNhº:“t¡Ç:xk€Ë4XôlÛ…ìNð¼?LéýÐÏ™ªËSYI÷ø­-?“}1Øò,B:7w!LJ RÛŽ ‡á–ÖÍÁ˜Á ËLÏî´éï¬k ÐÉ9ª¤©¬3ÝØÁ[»ö‚dakšÀ¾Ícm;žåóo›†oß:3U6}9w» ß~2õï.¯|¹w<éÎeým…Go,´VÓðƒðüÛ|À¹¦©²ija Mã"\æ„k/ЛA,»_@9Ã5·Vº+ªXÝ[YrFSeÓÔÂ\³{&PÄ7Bãj°Z{n€õy4»÷¬²$„Vq^ Ãy5Xn@B]»W*ÕZi§lú¨aM!Ï´ÛÐf}|4\EHM•MS mô$÷B,˜†m°¦”§oÞ¹s0 q¬Ù™6ë`ºË<9°5zƒ5;ÿ¤§Oº+`—ë¬Uõíq¡ßþ ŒCƒ•ͪßr= k û`Ý·<®|÷à #†À5Ò£–ín°‚\4XiÎwW¦¯€Ÿ´VÕ Ñ`%Û]·_´ÒÇtWuÍ»ÁŸ;Ã>2Ò`<ÍSç[°;þº^rq’;À£lÂa,€Gé®`,FäöÑ¥ÁÊÉ•ƒ)ôJ Ί’¨ÂÅIå$÷+–-ëöæ¢'è˜+ÁÜ-%]ûóù“˯—X6 ¬S²ôFó¯k³ {¬²÷CÚ,螓ܔ»àü²NŠï’ ÖW\¯«ÇꌉIf¬}gº«×wþ«Z+>9ëŠí¡C·§ 糯½y7 Ÿ>+f°’ínMMDÉÄ»ºj°žiq¾mMz,½¥©1€¦tÕ`µ`÷áVU–„˜¹`—s°rú¼ÇÕê‹´&×ç²|è>h¬}óÌĵMfÒoÙ0÷A›À'‡¿zàèíqg1`¦Á:2o/Kl2ç—Õ]õg÷01£qˆð‡ìtaÿ|¾ƒÓ`’¥ÍÒZÀ 4X –Þèü¿?RkƒÐ`]ñ­UÚžV¥©j‡“ÞxŒ+'Ûïf:ëüòË*€¾i°µ(·A7ÏÆ cYî’»IDATnÓ™ 3 @fÎÁ‚0ŽOÞ:þ®ÓêÇt|ñ¬Ó¡ £è Ãèà-ÐE…8D™ 3 @f,Öœÿ7i°øÏÜZ9ùnÒ`ð/ÏD‡\4X˜¸‚Ì4XížÄðúãùåØÒZA ¬ç,)6ûü"@Ž B!¬çH1à²îÄÞ&Ñ`ÕdߨkŽ Í d§ÁªFw4B›ÙyØóÓ–¾Jw5¦yöL{½»½Tx|ó~¿íøA.f°žãRÁ­®u1) 2•¹h°®û™A«^Jk„ ¬à> Ö梸àóöÛÿÐç`¥™OP°]ä²'OsQ¨µh°8ý“^}ïVä÷9DxŠc‚ôjõ€ÏÈBƒC³ÛзãÏ÷ò§¯ÿ†Ÿ4X§¸t™|>‰\ãp‡+6‹¾}%Tçwh°’ÍWýü±Ÿ?³ÜÑ;ÏbÍÐ`]qfÿ¸sA"íXê|”P}Ü¡Áºîçèä\Ôµ}ä€îŠç©::£Á*k·Ç:˜ð|:è€>íøàËrðÑÎнƒýIHt¬â>¢sXÈC:æá’NÆÒ„@tf°rðˆßÕcàtWë9»“v úã!@f,€Ì4X™9 ¾:¾¢Ó-aøFƒUÇÏm³“ßCð1°Kƒõ¥£š7É'7Ì«ßBÐ`77I×:¤å·î¼ð0 VA»¢åI;¹^(GƒUD¡NH›…ç Îmò+Ý}¶Y´Fû À¤Á*¤ôöÕö»AZ+fvòÎI󳟗_øCOæy> >™ÁzÎ2ñܩ¡úÁ¾×ë5ÿõå¤2qÀ–¬iz°ÅÙn†ç‰¨oó?7Þy—\•jiOk/È4iòZ¢ÁúW®ÓÁ¶öÛŸø<\xþ·Î|÷§Õßµ…^9sÃýF6Òä0Ó`5aé±¾³h AtíôX´Ã9X™OGÿâçFzõß-õvT?—€Öh°Š(½­-ôúŸ/«]H¥Í`¡Áʯô†¶ÄÑÃíkj®¹<… @OœƒUD¡gÚ”;1ËÑÆŒ &¬‚2¶YUn¶ä4/¸FƒUÜêX[RËrónï—¹y&Ü¡ÁzȪY9sƒ¥ío•¶º×<p«ŽÖ:˜ùh`kKA¹Šij¯ákD¡Ûè»Ì {,€Ì4X™i°2Ó`d¦Á‚¸L ),€ÌÜ ¢:¸Ýƒ -€º4X•.  Y,ˆm5¥ëh bÓQ4ÈIî™i°2Ó`d¦ÁÈLƒ™ 3 @f,€Ì4X™i°2Ó`d¦ÁÈLƒ™ 3 @f,€Ì4X™i°2Ó`d¦ÁÈLƒ™ 3 @f,€Ì4X™i°2Ó`d¦ÁÈLƒ™ 3 @f,€Ì4X™½Þï÷£ïõÚ~1Ë2,¯œúj—.PoD§†áŒ¬Ë¯Y®Ûƒ-õFtjÎsˆ(k·;ïÛ?µ ƒyÿé¬õå_„ ÔÑ©a8ïéC„Àh^¯áú ‡2Ó`d¦ÁÈLƒ™ 3 @f,€Ì4X™i°2Ó`d¦ÁÈLƒ™ 3 @f,€Ì4X™i°2{½ßïÚË„÷z½.ÿn݈ 3‡2Ó`d¦ÁÈLƒ™ 3 @f,€Ì4X™i°2Ó`d¦ÁÈLƒ™ 3 @f,€Ì4X™i°2Ó`d¦ÁÈLƒ™ 3 @f,€Ì4X™i°2Ó`d¦ÁÈLƒ™ 3 @f,€Ì4X™i°2û?Ÿ£­ª.qVXIEND®B`‚ocs/doc/and_output.png000644 000765 000000 00000014707 11005317740 015544 0ustar00carlowheel000000 000000 ‰PNG  IHDR€à,ÖsBITÛáOà)PLTEÿÿÿ   ÿÀ€ÿÀÿîîÀ@îî ÀÿÀ €@ €ÿ€@ÿ€ÿÀ`ÀÀ`€À`€€@ÿ€0`€€`@@@@€€€`€``€`€Àÿ`ã°À@À€` À`À`À €€€` €``` @@ @€`€ `€``€€€€@ € €€€    ÐàÀ €€À`€ÀàÀ`ÀÀ€À€`ÿ@ÿ@@€Àÿÿ€`ÿ€€À ÀÀÀÀÿÀÿÿÿÿ€ ÀÀ ÿ``ÿÿ€ÿ €àà àà ÿ ÀÀÀ    ÿ€ € €@ €@€€`À€`ÿ€€ÀÀÿ€@ÿ @ÿ `ÿ pÿÀÀÿÿÿÿ€ÿÿÀT&¼sGtEXtSoftwaregnuplot version 4.0 patchlevel 0 on Linux 2.6.15-1.2054_FC5smp7/÷³÷IDATxœíÑbâ: É–þÿ/ß[Z ‰íX’e[ 3»lNdkÖ àv€d™]|4 ÂD„‰,‚a2SA@˜ ÂT¦‚€0•Š€ \„1:é© 8mϽ²¿^÷ýƒ!ºÎýÁê¶ìïà ³ àÈè|vI»-Îm*{ïÛãGëŸé²U "àÈèL¶@½›¦æîd-;YîÞ¿0g+–A½Ï–ÚwÛ ˜»«­ì’}Û_²¥ "àÈèM¶Â¾Ô¿4ÀRö¡~ ìÙBpdô;[eß-/à6ÆPvM¿ÛSQÛ” `—=;dkí;ìå3L]vuù{o†€Ú_wÜsk¶Þ¾j+‘Ú²eúýnùqÖŸ£<«€ûn’V~})Ë–û÷ÿ¶'`S hYü~uR.<ü¾6WmýcE[Ž“¿H;)VP+Ôb2Eÿ­O¶ç3D[-«ÝTPë´h—Ì&ú¥…%[ùŒn]A½K‹é^hãŸw ñÌï‰îÅýúþl't†û!  gõÓûWÙ§Õ?ý=І«€­úÙ<دÝ?õ}І£€íúý+ï»E@åІŸ€íú5˜ß}“Ê»#  /–¿›BÀ%½VÐ辈/ ‹~m&E´ú§K@@.ú,·V·u´û§Ê@@zé×,àºÿ4)h£]@·åïæ à«ÿð—Àzêç!à_ENþ)‚ÐF£€®ú5 øweå—£€â$´Ñ$ ïòwÓ<¸ÜZ¾üüó5tׯUÀwÏÚ0¨€þú©^ Yv¯x\TŸ/ïËÀ]´Ú° Øaù»9 x^®êQÑo 4a°‹~º×‚—ÕŸkÞo¬k š0 Øgù»5 øx |¿ÃЫNìm°—~Ê«a–ÛÞ¿Ÿ?4Mèì¶üÝ|ù·þ©SµЄZÀŽúi¯\Òðþºõb”hB+`WÿšÌ~¾•KÉØ €=¿?(¯ˆ^öÿÌÀšKÕUЄJÀÎú©¯ÈßÏËýù1;û_Œ0Mhìí_Ë[B”` š Øûð{kðȇê°bûë×*`EÞ"  ©€#üë+`oЄPÀ!þµ X¢¤¯hB$à€Ó¿lº#p~mÊ®™êh š8Ì¿¥×-7½© 8οö3MÔuú÷À. â]Hm#B@g*ŽÔo€ƒ*î M 8Ö?»€Ê·a¶ }9p°¦we¾.ÃÒLRÐÄ‘€£ý3 ¨ÿŽÁ†¡! +÷o € D@eÇûg0s~ûðГ¢€ü* »h¢$à ÿŒZ¿èÜæmÃû Ý D@?²Nò¯QÀÃOlËãi šÈ 8Ë?ÃGì\ÈhêŽ{7ÐFFÀiþ 0Á8ØÌˆ€&Rçù§ÿh˜µ 6ý D@‰€ý›" qÀèÄ^À™þ©?fãU@/ÐÄNÀ©þMÐ6hôa+à\ÿôŸMtßü+[€‹hb#àdÿ4<øÄ2ð3({i¨¾Õ gû§¾"zã€á•7ƒ , lB[pºZïûϧT¾¼Æ0øðÊ ’­†8ß?µ€žûn70š€²“bÑV# àŸR@Wÿ,pŽ Aúöß"Sl60®€éGÆæ¶š)`ý”zûgø_x—ð‡à þÍP?›¢ ¸ï8Àƒ(þ©ìáŸz*Î àRÛñô§aÂø@Àc ¸þ³´aý‰è ÿ|ùjðš2…€üÓx$àïÜl{×\ž‚õÒxŒ³þEXoJ£¯€*¹¦œò/Äx³PÀõáòVÙÛÅ|ùr;|:D@•¡Ì-nûó€¹~Y¿1½ r»úg50œ€ë—BÞ?Üx .Å[#¿ )' ç$) ,`îv,¿lߘž0ZÀì8IÀw1Ñ,‹ÇàáB~¦³X–Àpf§ÏM{æ1Ég0è;Iã ûŠèß)FÀr èEºÿ&ø„{O’Ú@ÔðœÞŽª×ÿï¿ûgîøúÑ¡€¾¯w‰ D@=¯Éõy0ûx+ùÉÑ=þþ0sÇ÷–âs€MoJÊ¢4 ðèGùˆ_3YëUµ, äùøÄ½î÷Ô:½r´ø(Lï¹ùQñEщèw7PÁê¿ö‡ ¨Dº>ŠB@)ëiõz-xYý™ý• ž€*PÈfR; (» sµ•HÀJµ­´ D@9Û)u»f¹íýKn”îö¼Q@…(c€²Ç¤›­Þpžuï&ÔïzÀ¥°ž\@¹(a?gpû<`1ÊýyÀ?d" ˆd2¯ˆ^ ÿl>ܾRNò~%ä‰È@”Ne?_o+¾·* øÜê~ü ¤×{e"`•ÌDžê=!ß RFb VÉM#Šˆ€²“x&çù'2+ `ØL~ PHÝÀïz}Ÿ,`aO$àTÿ"à¥éë) 6[!àŒ²k~×ÿ‹|®€ÅÉ;€›îN)»b –)O&”³› üT&² DÀGÓv·½Uö¡XU4X3ð3<œ´³¸ëì´²&³Ÿ· `ÂqöÁtþÔlà' Xy䆀 •ìò„"`†Ú³§'pß×™e§Sª¯!`B5»4©ú DÀ„@*üCÀ±˜ë®_€ õì´þàÈÀOPp&²ó‹€;$בŸBÀ´§³ËÎN-n½—kv'WœIÀìäþ àÀ@L˜ÞÉ7E3^6V‘½¡z'ßœJÀÜô>P6ð“~¤ÉüN¾( ˜ëg€²Ó FÀÒOV ÐÉ''0b|#þ|íüãl&“ü€èS\Ï„ºnù—¬„èä/³ÝŒQönšð6Ð.àÁw™œmÝŠoÚ‹ÑÉyó½ Röv¢ðÍ·Ýéä'p;Õø‹Æ¿0¼SÀÍd¯0è G¡ª[å_œN,t2NÙ«éFÀ؈2û=ßøƒÎ¿HÌ X:™ TvVÀ1_ª= EÝJÿ"uò¤¾§õþEêäY|MúfÙÊ// Ú¿HÌX|I!PÙ·×´# Þ¿H<¯€€W°|YI ²NŸ \5ˆ€mÑ:,óŠhÁÑù;ø¨“õ73G븀^äëöð/P'/%àº9WÐÅ¿@¼–€y0!N'ëñmŽÖá#àª?×ÐÇ¿@¼®€ï]H@'ÿuòjæ–Àëèå_ NÖ¿gÈ­ÃKÀw“®' ›:y=S0!N'ë_vjŽÖá'à«OWÐÏ¿@¼²€ÏQ]D@GÿuòŠî—Àkèé_ NþvOæ_ ²×d>ãõ¯YWÐÕ¿@¼¦€[¯  ¯:yQÿ†€âtòÑ=¡Ê^“ÿ¶»GÇ.# ³:ymGv~½ý ÔÉŸîIý TöšÂWn¿—ÀÓ èî_ N^WÀ·gÐß¿@¼°€Æ!`–8üVø¨ì5E:w;ø¨“Wðgtç°‡:yiÿ–ÀS ØÅ¿@üVø¨ì5þß>̧“ðaà™ìã_ N~+ü Töš+ ØÉ¿@¼º€?žWÀ^þêäå¼}!`JœNVº×­£›€'^»ù¨“°ºžVÀ~Ñq:ùžùAH/ÂtòŽ€qY4çç:ÂtóÞ9fѼH #J'02Ø­®/àGÁ‘Y4W*éÒIå¥ì=¨&H'04—P{RvÂ…ìe`ŒN"`l®.àÏØ00ºû¢“4G@À„‹ øæ·î.Fè$F­Ñ0áÚþŽ óWwtÃsiÿF…€yÖÝÁÀùDÀø  -Ú&\YÀç˜00¯ºý œÞI<hŠ6‚€ ð5" Ì»nwgwÏÀu|³ªÛÛ@ôÌŽ&àò‹l[ÙïPmæ:.»¿· èmàÜN®ƒ€î,™[åmÐ7ÚÎU\ · Û" o´ X; \nr œÚÉõPЛõøxÇËvó£¨Ê¢¸œ€•ãëß/Åú8³“›  7ëÇÀ»Ð3º…‹ X;¾Jž«A@mt ×°v|]’¹6ü»ÿ»Ûa|OªÂ•Ì ¶½óQKÆzékpûOÏ%pâR²+ 7ës¿%ÿ?ö¿p4p^'wƒ¸„€µQŒP´¼ 6A@]t×0÷Z\qÓèh ºf‡pýRÈû‡%?MÀýЛìkÁø»S8{ègà¬N&@@r}ÎP[Ë ìXö¸"ú‰—“:ÙèŽÑÍ `*¢›AÀ„\ÝNÎédZ<FåÑí `B¶n§t2S:FÅÑ `Š£@À„|Ý.Îèd®pŒ J£=@À„BÝNèd¶lŒ  £]@À„K ˜¯#SªÛÁ@tÍF@-蚀Z†w²P3F¦Xw»蚀ZFw²T1F¦\w³蚀ZÐ5µ îd±^ŒÌAÝ­" k6jÛÉrµ™£º D@×lÔ‚€®Ù¨eh'jEÀÈÖÝf ºf# –‘<ª#s\w“蚀Zvò°NŒ V¢]AÀ„JÝ-" k6j×Éã*02µº D@×lÔ2¬“•/"`eW°Á@ôÍF@%蛀JFu²V!F¦^·Ù@ôÍF@%ƒ:Y­##¨Ûj`•þ!àXð ÚL8½€ÞG`‹¤n£蛀J†t²^†FT·Í@ôÍF@%蛀JFtRP†FV·É@ôÍF@%:)© C#¬Ûb úf# ’þU…€¡‘Öm0}³P úf¶€»wRV†³Ñ@ÀyÝj{wRX†sѽ¸€Ë/Í[)êÖع“Òr°ËîoóV˜‰îÆe\2·l[iêVØ·“âbП¥pÛ°¦Ñý¸ €ÕÓÀäÂ_äÐص“òRПõ±+  ?ËêÆHuö줢ôgýè+  ?Ëê/ÑŽ}ßtvìä]‘€þ,ÉŸ’íó¿Úð¯Æ½ºÅ4e|w«b0É@¶½sðJÌzé;|"Ðõ•Š%°ßRr×d³ú³>÷k|•÷ `õƒßÆÓ;uÝr»uò®ÊF@ÖÏþ­n펵øýY›ö^ ÷g{}”Ø«“w]6ú“}•ó ` Gà!Š ìÔÉ»2{{ <æhË>IÀ+¢EOSZêا“wm6†÷ àPLuË ìÒÉ»:Cƒ€{p(¶ºEöèäsÇòl­8܃€C1Ö-1°C'_»EÀ=˜€€ÎÙ¸B` 'ß;EÀ=˜€€ÎÙ¸¦n {'W»DÀ=˜€€ÎÙ¸¡j w'×;DÀ=˜€€ÎÙ¸¥f s'7»CÀ=˜€€ÎÙ¸£b o'·;CÀ=˜€€ÎÙ¸çØ@×Nîv…€{0Á³“û=!àžðØ@tÎFÀ„Q&ûAÀ=Ÿ)à¡蜀)cL÷‚€{>TÀ#Ý:™ÙîAÀtÎFÀe½:™ÛîùXË" s6æ)èÔÉl<îAÀŸNæÓpÏ X2³°D«$êhLøh[ÏӴɘ‚€ l?¿DÀØ8ÕÝöT‰*V™€±ñª»éÕ E¨:cãVwËòL}6Æ&²€.¯3#`lüên¸fOhÊFÀØ8Öm¿l^gÌFÀØxÖm~çš lÇG x8¼Ùß»[J@À=xCÀÞÙXÃøù-•  ¸Ø>Bí0&‹8[íŽÅ»nÓ§˜„@À=ø‹‡€ž€Ž€Áq¯ÛòIö¥„2¸Ÿ¾L&ÿ#p¾ÐŸ[îÞÇ à|€½²P†þ;}“ûÖ@À=¸â×"Ël ýCÀ\óðÈ0ÛRÿ07ÜMÑbÿäÙz{v²1åÜïúh¹è=~ußµÑ ÿÐ;zëÖõX2  st'–_޶è¸sR:[Ð;ºËîïƒMºì]n•Ò?ôŽîÂ’¹UÞ¦Çî…ÇUÝá÷/[Îc)Ü.nÔcÿ·Ôú}ª€·ïòpb X> ì-`]/ýòwûXÆZÀeÞ x«fÒO^öÁ’ÑmÁ!»4¢È.ÁJ–ÝúIË6è^ÀÒ"XÀå6[À¼jfûn²²Mú@ÀüÀâ ¸¬n7ê¸ÿ'÷·„÷ûݾøå²3õ;ƒ€?ƒûÞ/¬€ë?sÁE#•†õÒ°<¸:ës?„á¬ü" gýìÂpÖç¥Ã½ Ð ŽÀ0Ã\Â>G WÆë’qŽaW²lÓH:F«îå_vðwÍ=ñºhKœc˜ Y¶i$£U÷RΊ$:°t+¼.[çþ7ʲM#é­º×Áç÷˜£O! ×…û✣OªiÊ6¤c´ê^ÊYÑ—–õ;—œ¬ŸOuÌVî¡c´&ûðó{ÌÑ'Pyhȱ (­Ñ  {´"{ý!ŽÑçÐph´æ˜רÐ?Zž½(ƒ¥Ñ§P{hɱ (¯Q- 8Úðø¦–½¨“…Ñgxf3zE9Få5ªW)q´Á’Zö²ûÛ1:ÙG@–äÏþ96å5ªW)Q´z)‘e/É ·èÜ^±þOÔ, 0Ç$  ÛpÀÑß?Û. ªka \ŸE´ (ͱ(ȶ”¯¾ru­g›^/Ów-²€¦ÿƒ-9Ù¦êõÃW_j²•+`·²ãõ!nùœüj½€’l£€ò²µ»QfëìWö`¼>Ä-›S8¬¨eÛT”­Ý2[%`Dz³n»äx (ʶ‚•ѪC° ÛÜ·ìÑøó9NʲmåËʶM’bJ”É]ËîÑ”.ÇçP–m¬_V¶m’äSÒ)Ú«·}ñz¹fò¥ÅÖë'—ýÞ¶G´Wo¦ó<ûGÜ'„ðIEND®B`‚ocs/doc/buildsystemIFF.m_in000644 000765 000000 00000002512 11533542746 016414 0ustar00carlowheel000000 000000 function [varargout] = buildsystemIFF(instruct,x,t); ## [varargout] = buildsystemIFF(instruct,x,t) n = instruct.totextvar+instruct.totintvar; A = spalloc(n,n,0); Jac = spalloc(n,n,0); res = spalloc(n,1,0); ## NLC section nblocks = length(instruct.NLC); for ibl = 1:nblocks for iel = 1:instruct.NLC(ibl).nrows ## evaluate element if instruct.NLC(ibl).nintvar(iel) intvars = instruct.totextvar+instruct.NLC(ibl).osintvar(iel)+... [1:instruct.NLC(ibl).nintvar(iel)]'; else intvars=[]; end il = instruct.NLC(ibl).vnmatrix(iel,:)'; nzil = find(il!=0); y = zeros(size(il)); y(nzil)=x(il(nzil)); z = x(intvars); [a,b,c] = feval(instruct.NLC(ibl).func,... instruct.NLC(ibl).section,... instruct.NLC(ibl).pvmatrix(iel,:),... instruct.NLC(ibl).parnames,... y,z,t); ## assemble matrices vars = [il;intvars]; for irow=1:rows(a) if (vars(irow)) for icol=1:columns(a) if (vars(icol)) A(vars(irow),vars(icol)) += a(irow,icol); Jac(vars(irow),vars(icol)) += b(irow,icol); end ## endif end ## endfor res(vars(irow)) += c(irow); end ## endif end ## endfor end ## endfor end ## endfor varargout{1}=A; varargout{2}=Jac; varargout{3}=res; ocs/doc/diode.spc000755 000765 000000 00000000221 11706574500 014443 0ustar00carlowheel000000 000000 * diode clamper V1 Vin 0 SIN(0 5 10G 0 0) R2 Vin V2 1k R3 V2 0 1e3 C4 V2 Vout 1p D5 Vout 0 Is=1e-9 Vth=75e-3 D6 0 Vout Is=1e-9 Vth=75e-3 .END ocs/doc/funjac.m_in000644 000765 000000 00000000315 11533542746 014770 0ustar00carlowheel000000 000000 function jac = funjac(x,xdot,T,d) global A_MATRIX_IFF B_MATRIX_IFF C_MATRIX_IFF OUTSTRUCT_IFF [A,B,res] = buildsystemIFF(OUTSTRUCT_IFF,x,T); jac = (B+B_MATRIX_IFF) + d * (A+A_MATRIX_IFF); endfunctionocs/doc/funres.m_in000644 000765 000000 00000000342 11533542746 015024 0ustar00carlowheel000000 000000 function res = funres(x,xdot,T) global A_MATRIX_IFF B_MATRIX_IFF C_MATRIX_IFF OUTSTRUCT_IFF [A,Jac,res] = buildsystemIFF(OUTSTRUCT_IFF,x,T); res += (A+A_MATRIX_IFF) * xdot + B_MATRIX_IFF * x + C_MATRIX_IFF; endfunction ocs/doc/iffspec_ocs.tex000644 000765 000000 00000052541 12564410364 015666 0ustar00carlowheel000000 000000 \documentclass{scrartcl} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \usepackage{hyperref} \usepackage[pdftex]{graphicx} \usepackage[usenames]{xcolor} \usepackage{amssymb} \usepackage{amsmath} \usepackage{amsfonts} \usepackage{listings} \let\tt=\normalfont\ttfamily \let\bf=\normalfont\bfseries \let\it=\normalfont\itshape \newcommand{\Iff}{{\tt IFF}} \newcommand{\nlc}{{\tt NLC}} \newcommand{\cir}{{\tt CIR}} \newcommand{\lcr}{{\tt LCR}} \newcommand{\nms}{{\tt NMS}} \newcommand{\sbn}{{\tt SBN}} \newcommand{\ord}{{\tt ORD}} \newcommand{\dem}{{\tt DEM}} \newcommand{\nl}{{\tt \backslash n}} \newcommand{\oct}{{\tt Octave}} \newcommand{\mylink}[2]{\hyperlink{#1}{#2}} \newcommand{\mylisting}[1]{\hypertarget{listing:#1}% {{\sffamily\bfseries\large file : #1 \normalfont}}% \null\lstinputlisting[]{#1}} \newcommand{\mylistingm}[1]{\hypertarget{listing:#1.m}% {{\sffamily\bfseries\large file : #1.m \normalfont}}% \null\lstinputlisting[]{#1.m_in}} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \title{IFF version 0.1b1 File Format Specification} \author{Carlo de Falco} \begin{document} \maketitle \section*{Introduction} This document contains the specification of an {\bf I}ntermediate {\bf F}ile {\bf F}ormat ({\Iff}) for describing coupled electrical circuits, devices and systems. The present version of this documents refers to the {\Iff} version 0.1b1. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{List of Files} A circuit description is comprised of a set of files of three different types: \begin{itemize} \item 1 {\cir} ({\bf Cir}cuit) file: an {\tt ASCII } text file with filename {$<$circuitname$>$.cir} \item 1 {\nms} ({\bf N}a{\bf m}e{\bf s}) file: an {\tt ASCII } text file with filename {$<$circuitname$>$.nms} \item $N \geq 1$ {\sbn} ({\bf S}u{\bf bn}et) files: a set of M-functions or DLD-functions following the template described in \autoref{ssecsbn} below. %\item 1 {\ord} (Re{\bf ord}ering ) file: an M-function or DLD-function %following the template described in \autoref{ssecord} below. \end{itemize} {\sbn} files are not necessarily specific to one circuit and can be grouped in \emph{libraries} as long as the directory containing the library is added to the path when the {\Iff} parser is run. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{File Formats} Below we describe the purpose and the syntax of each of file categories. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsubsection{{\cir} files} The {\cir} file is divided into two sections describing the linear time--independent ({\lcr} = {\bf l}inear {\bf c}i{\bf r}cuit) and the non--linear and/or time--dependent ({\nlc} = {\bf n}on--{\bf l}inear {\bf c}ircuit) partitions of the circuit respectively. The syntax for the {\lcr} and {\nlc} section is identical. {\nlc} can also contain linear elements, in fact the whole circuit could be described only by the {\nlc} section but this could result in the evaluator unnecessarily recomputing local matrices for linear time--independent elements The content of {\cir} files is organized as follows\footnote{ This description makes use of Extended Backus-Naur Form (EBNF) see this \hyperref{http://www.garshol.priv.no/download/text/bnf.html}{}{}{article} or the EBNF entry in the \hyperref{http://en.wikipedia.org}{}{}{wikipedia} for an explanation of (E)BNF }: \begin{lstlisting}[language=Mathematica,mathescape=true,backgroundcolor={}] cir := header nlc separator lcr separator ; header := '%' version_id '$\nl$' comment* ; comment:= '%' text '$\nl$' ; nlc := block* ; block := blockcomment? blockheader pv_matrix vnum_matrix ; block_comment := '%' text '$\nl$' ; block_header := func section n_extvar n_par '$\nl$' n_rows n_parnames '$\nl$' par_name*; section := string ; n_extvar := number ; n_par := number ; n_rows := number ; n_parnames := number ; par_name := string ; pv_matrix := matrix ; vnum_matrix := matrix ; matrix := number+ ; separator := 'END $\nl$' ; lcr := block* ; \end{lstlisting} where \begin{description} \item {\tt version\_id} is a string identifying the version on {\Iff} in which the file is encoded \item $\nl$ is the new-line character \item {\tt string} represents anything that the {\oct} command {\tt s=fscanf(file,\%s) } would parse as a string {\it i.e.} any sequence of chars without white-space \item {\tt text} is any sequence of chars without a $\nl$, this differs from {\tt string} because it can contain white--space \item {\tt number} represents anything that the {\oct} command {\tt s=fscanf(file,\%g) } would parse as a number \item {\tt func} is the name of a function to evaluate the elements described in the block \item {\tt n\_extvar} Is the number of {\it external variables} for the elements of a block \item {\tt n\_par} Is the number of {\it parameters} for the elements of a block \item {\tt n\_rows} Is the number of {\it elements} in a block \item {\tt n\_parnames} Is the number of {\it parameter names} for the elements of a block, it corresponds to the number of {\tt par\_name} entries. If {\tt n\_parnames} is 0 the line with the {\tt par\_name}s is missing. \item {\tt pv\_matrix} Is a list of {\tt n\_rows} $\times$ {\tt n\_par} numbers separated by any character the {\oct} command {\tt s=fscanf(file,\%g) } would consider whitespace (including $\nl$). \item [] every row (a set of {\tt n\_par} contiguous entries) in {\tt pv\_matrix} refers to an element of the circuit. The {\tt n\_par} numbers in a row represent the values of the parameters to be passed to the function that evaluates that element. \item {\tt vnum\_matrix} Is a list of {\tt n\_rows} $\times$ {\tt n\_extvar } numbers separated by any character the {\oct} command {\tt s=fscanf(file,\%g) } would consider white-space (including $\nl$). \item [] every row (a set of {\tt n\_extvar} contiguous entries) in {\tt vnum\_matrix} refers to an element of the circuit. The {\tt n\_extvar} numbers in the row represent the global numbering of the element external variables. \end{description} \subsubsection{{\nms} files} {\nms} files are meant to contain the names of the circuit variables, the format of {\nms} is just a list of variable names one on each row preceded by the variable number: \begin{lstlisting}[language=Mathematica,mathescape=true,backgroundcolor={}] nms := version_id '$\nl$' comment* line* ; line := var_number var_name ; var_number := number ; var_name := string ; \end{lstlisting} the variable are ordered as follows: \begin{itemize} \item first all external variables of all elements in the order given by the global numbering of external variables as explicitly written in the {\cir} files \item then the internal variables of the elements in the same order as the corresponding elements appear in the {\cir} file ( internal variables of non-linear elements first, then those of linear elements) \end{itemize} Notice that the number of internal variables of each element is not included in the {\Iff} files. This is because elements with a number of internal variables that is huge, that depends on the value of some parameter, or even that changes in time (for example distributed elements treated with a FEM with adaptive meshing, a large linear sub-circuit that is reduce via MOR...) and therefore it is more convenient to compute the number of internal variables when initializing the system. \subsubsection{{\sbn} files} \label{ssecsbn} {\sbn} files are {\oct} functions, implemented as (M-scripts or as DLD functions) with a header as follows: \begin{lstlisting} function [a,b,c,] =... func (string, m(i,:), extvar, intvar, t) \end{lstlisting} i.e. it should get as inputs: \begin{itemize} \item the string entry of the block header \item one row of the {\tt pv\_matrix} entry of the block \item the current values of all internal and external variables \item the current time \end{itemize} and it should produce as outputs three matrices: \begin{itemize} \item $a,b \in \mathbb{R}^{ \mbox{\tt (n\_extvar + n\_intvar})\times \mbox{\tt (n\_extvar + n\_intvar)}}$ \item $c\in \mathbb{R}^{\mbox{\tt (n\_extvar + n\_intvar)}} $ \end{itemize} where {\tt n\_intvar} is the number of \emph{internal variables} (see \autoref{sec:appintext} for explanation of \emph{internal variables} and \emph{external variables} ) that can be assembled in the complete system matrices. We assume that the full DAE system can be written in the form \begin{equation}\label{eqdaesystem} \left(A(t) \mathbf{x}\right)_{,t} + B \mathbf{x} + \mathbf{C} + \mathbf{f}(\mathbf{x},t)= 0 \end{equation} The local matrices $a$,$b$,$c$ of a linear element $E_{l}$, will contain the contributions to $A$, $B$, $C$ due to $E_{l}$. At a given instant of time $t=\tilde{t}$ and for a given set of state variables $\mathbf{x}=\mathbf{\tilde{x}}$, the local matrices of a non-linear element $E_{nl}$, will contain the local contributions to: \begin{itemize} \item $a$ to $A(\tilde{t})$ \item $b$ to the Jacobian matrix $\left.\frac{\partial \mathbf{f}}{\partial\mathbf{x}}\right|_{\mathbf{x}= \mathbf{\tilde{x}},t=\tilde{t}}$ \item $c$ to $\mathbf{f}(\mathbf{\tilde{x}},\tilde{t})$ \end{itemize} due to $E_{nl}$. \subsection{Internal and External Variables}\label{sec:appintext} To better understand what is intended by \emph{internal} and \emph{external} variables we consider below an example with a linear system, For another example see~\cite{freund99}, Pag.398. Consider the system below, where, for sake of simplicity, we assume all coefficient matrices to be independent of time and of the state vector $\mathbf{x}$ \begin{equation}\label{eq:coupledlinsys} S: \,\, A \mathbf{x}_{,t} + B \mathbf{x} + \mathbf{C} = 0. \end{equation} We assume that the system $S$ obeying~\eqref{eq:coupledlinsys} can be partitioned into two subsystems $S1$ and $S2$ and therefore the state vector $\mathbf{x}$ can be written as: \newcommand{\xprtd}{\left[\begin{array}{c}% \mathbf{x}_{c} \\ \mathbf{x}_{1} \\ \mathbf{x}_{2} \\ \end{array}\right]} \begin{equation}\label{eq:staepart} \mathbf{x} = \xprtd \end{equation} where $\mathbf{x}_{1}$ represents the vector of the unknowns belonging only to $S1$, $\mathbf{x}_{2}$ represents the vector of the unknowns belonging only to $S2$ and $\mathbf{x}_{c}$ represents the vector of the unknowns common to $S1$ and $S2$. If $\mathbf{x}_{1}$ and $\mathbf{x}_{2}$ depend on each other only through $\mathbf{x}_{c}$, then the \emph{flat} representation~\eqref{eq:coupledlinsys} takes the form \newcommand{\MTT}[9]{\left[ \begin{array}{ccc}#1 & #2 & #3 \\#4 & #5 & #6 \\#7 & #8 & #9 \end{array} \right]} \begin{equation}\label{eq:partitionedcoupledlinsys} S: \,\, \MTT{A_{cc1}+A_{cc2}}{A_{c1}}{A_{c2}} {A_{1c}}{A_{11}}{0} {A_{2c}}{0}{A_{22}} \left(\xprtd\right)_{,t} + \MTT{B_{cc1}+B_{cc2}}{B_{c1}}{B_{c2}}{B_{1c}}{B_{11}}{0}{B_{2c}}{0}{B_{22}} \xprtd + \left[ \begin{array}{c}% \mathbf{C}_{c1}+\mathbf{C}_{c2} \\ \mathbf{C}_{1} \\ \mathbf{C}_{2} \\ \end{array}\right] = 0. \end{equation} which is equivalent to $$ \begin{array}{ll} (A_{cc1}+A_{cc2}) \mathbf{x}_{c,t} + A_{c1} \mathbf{x}_{1,t} + A_{c2} \mathbf{x}_{2,t} + (B_{cc1}+B_{cc2}) \mathbf{x}_{c} + B_{c1} \mathbf{x}_{1} + B_{c2} \mathbf{x}_{2} + (C_{c1} + C_{c2}) &= 0\\ % A_{1c} \mathbf{x}_{c,t} + A_{11} \mathbf{x}_{1,t} + B_{1c} \mathbf{x}_{c} + B_{11} \mathbf{x}_{1} + C_{1} &= 0\\ % A_{2c} \mathbf{x,t}_{c} + A_{22} \mathbf{x}_{2,t} + B_{2c} \mathbf{x}_{c} + B_{22} \mathbf{x}_{1} + C_{2} &= 0\\ \end{array} $$ Then $S$ can be represented as the coupling of two systems $S1$ and $S2$ in the following way: \newcommand {\matrow}[2]{\left[ \begin{array}{cc} #1 & #2 \end{array}\right]} \newcommand {\matcol}[2]{\left[ \begin{array}{c} #1 \\ #2 \end{array}\right]} \begin{eqnarray} \label{eq:s1} S1 : & & \,\, \matrow{A_{1c}}{A_{11}} \matcol{ \mathbf{x}_{1,t}^{(e)}}{ \mathbf{x}_{1,t}} + \matrow{B_{1c}}{B_{11}} \matcol{ \mathbf{x}_{1}^{(e)}}{ \mathbf{x}_{1}} + C_{1} = 0 \\ % \label{eq:s2} S2 : & &\,\, \matrow{A_{2c}}{A_{22}} \matcol{ \mathbf{x}_{2,t}^{(e)}} { \mathbf{x}_{2,t}} + \matrow{B_{2c}}{B_{22}} \matcol{ \mathbf{x}_{2}^{(e)}}{ \mathbf{x}_{2}} + C_{2} = 0 \\ % \label{eq:s1s2coupling} COUPLING : & & \,\, \left\{\begin{array}{l} \mathbf{x}_{1}^{(e)} = \mathbf{x}_{2}^{(e)} = \mathbf{x}_{c} \\[.5cm] \matrow{A_{cc1}}{A_{c1}} \matcol{ \mathbf{x}_{1,t}^{(e)}}{ \mathbf{x}_{1,t}} + \matrow{A_{cc2}}{A_{c2}} \matcol{ \mathbf{x}_{2,t}^{(e)}}{ \mathbf{x}_{2,t}} + \\ + \matrow{B_{cc1}}{B_{c1}} \matcol{ \mathbf{x}_{1}^{(e)}}{ \mathbf{x}_{1}} + \matrow{B_{cc2}}{B_{c2}} \matcol{ \mathbf{x}_{2}^{(e)}}{ \mathbf{x}_{2}} + C_{c1} + C_{c2} = 0 \end{array}\right. \end{eqnarray} It is easy to see that, reversing the procedure shown above, it is possible to reconstruct the full system $S$ from the subsystems $S1$ and $S2$ the information that is needed for this purpose is the following: \begin{itemize} \item the local matrices \begin{eqnarray} \label{eq:locmati} A_{i} = & & \left[ \begin{array}{cc} A_{cci} & A_{ci} \nonumber \\ A_{ic} & A_{ii} \end{array} \right]\\ B_{i} = & & \left[ \begin{array}{cc} B_{cci} & B_{ci} \\ B_{ic} & B_{ii} \end{array} \right] \nonumber \\ C_{i} = & & \left[ \begin{array}{c} C_{ci} \\ C_{i} \end{array} \right] \nonumber \\ i=1,2 && \nonumber \end{eqnarray} \item a partitioning of the state variables of each subsystem in \emph{internal} ($\mathbf{x}_{i}$) and \emph{external} ($\mathbf{x}_{i}^{(e)}$) variables: \item a \emph{global numbering} of external variables {\it i.e.} an equation of the form of~\eqref{eq:s1s2coupling} or more generally, in the case the ordering of the external variables is different in the subsystems, a set of identities of the form $$ x_{i}^{(e)} (j) = x_c (j)$$ \end{itemize} \subsection{Examples} In this section a set of examples is provided to show how to represent some circuit topologies in the {\Iff} format, how to parse {\Iff} files and how to build the systems of equations to be solved at each linearization step within each time-step of a transient simulation. The programs shown are simplified versions of thos included in the OCS package. \begin{table} \begin{tabular}{|p{.15\linewidth}|l|l|l|l|l|} \hline description & script & flag & {\cir} file & {\nms} file & {\sbn} file(s) \\ \hline \hline %% An inverting amplifier with one n-channel MOSFET and a resistive load & \mylink{listing:runme.m}{\tt runme.m} & \mylink{listing:runme.m}{\tt nmos} & \mylink{listing:nmos.cir}{\tt nmos.cir} & \mylink{listing:nmos.nms}{\tt nmos.nms} & \begin{minipage}{.2\linewidth} \mylink{listing:Mnmosfet.m}{\tt Mnmosfet.m}\\ \mylink{listing:Mvoltagesources.m}{\tt Mvoltagesources.m}\\ \mylink{listing:Mresistors.m}{\tt Mresistors.m} \end{minipage}\\ \hline %% An inverting amplifier with one p-channel MOSFET and a resistive load & \mylink{listing:runme.m}{\tt runme.m} & \mylink{listing:runme.m}{\tt pmos} & \mylink{listing:pmos.cir}{\tt pmos.cir} & \mylink{listing:pmos.nms}{\tt pmos.nms} & \begin{minipage}{.2\linewidth} \mylink{listing:Mpmosfet.m}{\tt Mpmosfet.m}\\ \mylink{listing:Mvoltagesources.m}{\tt Mvoltagesources.m}\\ \mylink{listing:Mresistors.m}{\tt Mresistors.m} \end{minipage}\\ \hline %% A CMOS inverter with one n-channel and one p-channel MOSFET & \mylink{listing:runme.m}{\tt runme.m} & \mylink{listing:runme.m}{\tt inverter} & \mylink{listing:inverter.cir}{\tt inverter.cir} & \mylink{listing:inverter.nms}{\tt inverter.nms} & \begin{minipage}{.2\linewidth} \mylink{listing:Mpmosfet.m}{\tt Mpmosfet.m}\\ \mylink{listing:Mvoltagesources.m}{\tt Mvoltagesources.m}\\ \mylink{listing:Mnmosfet.m}{\tt Mnmosfet.m} \end{minipage}\\ \hline %% A CMOS AND gate with three n-channel and three p-channel MOSFETs & \mylink{listing:runme.m}{\tt runme.m} & \mylink{listing:runme.m}{\tt and} & \mylink{listing:and.cir}{\tt and.cir} & \mylink{listing:and.nms}{\tt and.nms} & \begin{minipage}{.2\linewidth} \mylink{listing:Mpmosfet.m}{\tt Mpmosfet.m}\\ \mylink{listing:Mvoltagesources.m}{\tt Mvoltagesources.m}\\ \mylink{listing:Mnmosfet.m}{\tt Mnmosfet.m} \end{minipage}\\ \hline %% An inverting amplifier with one n-channel MOSFET and a capacitive load & \mylink{listing:runmedaspk.m}{\tt runmedaspk.m} & \mylink{listing:runmedaspk.m}{\tt nmos2} & \mylink{listing:nmos2.cir}{\tt nmos2.cir} & \mylink{listing:nmos2.nms}{\tt nmos2.nms} & \begin{minipage}{.2\linewidth} \mylink{listing:Mvoltagesources.m}{\tt Mvoltagesources.m}\\ \mylink{listing:Mnmosfet.m}{\tt Mnmosfet.m} \mylink{listing:Mcapacitors.m}{\tt Mcapacitors.m} \end{minipage}\\ \hline %% A small element of a (lossy) transmission line modeled with lumped parameters & \mylink{listing:runmedaspk.m}{\tt runmedaspk.m} & \mylink{listing:runmedaspk.m}{\tt TLelement} & \mylink{listing:TLelement.cir}{\tt TLelement.cir} & \mylink{listing:TLelement.nms}{\tt TLelement.nms} & \begin{minipage}{.2\linewidth} \mylink{listing:Mvoltagesources.m}{\tt Mvoltagesources.m}\\ \mylink{listing:Mcapacitors.m}{\tt Mcapacitors.m} \mylink{listing:Minductors.m}{\tt Minductors.m} \end{minipage}\\ \hline \end{tabular} \caption{List of examples}\label{tab:exmpl} \end{table} \subsubsection{A CMOS AND Gate} In this section we discuss in slightly deeper detail the CMOS AND gate example, to point out more clearly some features of the {\Iff} format. \autoref{fig:and} depicts the schematic of the circuit, while \autoref{fig:andout} represents the output of a transient simulation. The file \mylink{listing:runme.m}{\tt runme.m} is a script that performs all the operations needed to simulate transient behavior of the circuit at hand. Notice that a time independent model is used for the MOSFETs (for the description of the adopted model see~\cite{neamen} Sec.11.3) and that no energy storing elements are present in the circuit so no time discretization is used and at each time-step a non-linear system of equations is solved via a damped Newton method. The main steps of the simulation are the following: \begin{itemize} \item Parsing the {\cir} and {\nms} files. This is accomplished by the call \begin{lstlisting} outstruct = parseIFF("and"); \end{lstlisting} it produces as output the structure {\tt outstruct } which will be described below. \item Initializing the system. This is accomplished by the call \begin{lstlisting} [A,Jac,res,B,C,outstruct] = initsystemIFF(outstruct,x,t(0)); \end{lstlisting} which builds the linear and time independent matrices {\tt A}, {\tt B} and {\tt C} and the initial value of the Jacobian matrix {\tt Jac} and of the residual {\tt res}. \item Cycle over time-steps and Newton steps \begin{lstlisting} for it=1:length(t) for ii=1:maxit ... end end \end{lstlisting} \item Rebuild time or state dependent components of the system \begin{lstlisting} [A,Jac,res] = buildsystemIFF(outstruct,x,t(it)); \end{lstlisting} \item Update the state vector \begin{lstlisting} xnew = (B+Jac)\(-res - C + Jac*x); x = (1-damp)*x+damp*xnew; \end{lstlisting} \item Plot the solution \begin{lstlisting} plotbynameIFF(t(1:it),out,outstruct,pltvars) \end{lstlisting} \end{itemize} The run-time representation of the circuit that {\tt parseIFF} builds from the {\Iff} file is the {\tt outstruct} structure which is composed as follows: \begin{lstlisting} outstruct = { LCR: struct % the fields of LCR are shown below NLC: struct % NLC has the same fields as LCR namesn: matrix % numbers of vars that are assigned a name in and.nms namess: cell % the names corresponding to the vars above totextvar: scalar % the total number of external variables totintvar: scalar % the total number of internal variables } outstruct.LCR = { 1x2 struct array containing the fields: % array has one element per block func % name of the sbn file corresponding to each block section % string parameter to be passed to the sbn files nextvar % number of external variables for each element of the block vnmatrix % numbers of the external variables of each element nintvar % number of internal variables for each element of the block osintvar % number of the first internal variable npar % number of parameters nparnames% number of parameter names nrows % number of rows in the block parnames % list of parameter names pvmatrix % list of parameter values for each element } \end{lstlisting} \begin{figure} \begin{center} \includegraphics[width=.99\linewidth]{AND_BW.png} \end{center} \caption{Schematic of a CMOS AND Gate}\label{fig:and} \end{figure} \begin{figure} \begin{center} \includegraphics[width=.66\linewidth]{and_output.png} \end{center} \caption{Result of the CMOS AND Gate transient simulation}\label{fig:andout} \end{figure} %\part*{Appendices} %\appendix \subsection{Source Code of the Examples}\label{app:source} \subsubsection{{\sbn} Files } \mylistingm{Mvoltagesources} \mylistingm{Mcurrentsources} \mylistingm{Mresistors} \mylistingm{Mnmosfet} \mylistingm{Mpmosfet} \mylistingm{Minductors} \mylistingm{Mcapacitors} \subsubsection{{\cir} and {\nms} Files} \mylisting{nmos.cir} \mylisting{nmos.nms} \mylisting{pmos.cir} \mylisting{pmos.nms} \mylisting{inverter.cir} \mylisting{inverter.nms} \mylisting{and.cir} \mylisting{and.nms} \mylisting{nmos2.cir} \mylisting{nmos2.nms} \mylisting{TLelement.cir} \mylisting{TLelement.nms} \subsubsection{Example Parser and Matrix Asembler} \mylistingm{parseIFF} \mylistingm{initsystemIFF} \mylistingm{buildsystemIFF} \subsubsection{Example Transient Simulations} \mylistingm{runme} \mylistingm{runmedaspk} \mylistingm{plotbynameIFF} \mylistingm{funres} \mylistingm{funjac} \end{document}ocs/doc/initsystemIFF.m_in000644 000765 000000 00000010005 11533542746 016254 0ustar00carlowheel000000 000000 function [varargout] = initsystemIFF(instruct,x); ## Check number of internal variables intvar = 0; ## NLC section nblocks = length(instruct.NLC); for ibl = 1:nblocks for iel = 1:instruct.NLC(ibl).nrows ## evaluate element il = instruct.NLC(ibl).vnmatrix(iel,:)'; nzil = find(il!=0); y = zeros(size(il)); y(nzil)=x(il(nzil)); [a,b,c] = feval(instruct.NLC(ibl).func,... instruct.NLC(ibl).section,... instruct.NLC(ibl).pvmatrix(iel,:),... instruct.NLC(ibl).parnames,... y,[],0); instruct.NLC(ibl).nintvar(iel) = columns(a)-instruct.NLC(ibl).nextvar; instruct.NLC(ibl).osintvar(iel) = intvar; intvar += instruct.NLC(ibl).nintvar(iel); end ## endfor end ## endfor ## LCR section nblocks = length(instruct.LCR); for ibl = 1:nblocks for iel = 1:instruct.LCR(ibl).nrows ## evaluate element il = instruct.LCR(ibl).vnmatrix(iel,:)'; nzil = find(il!=0); y = zeros(size(il)); y(nzil)=x(il(nzil)); [a,b,c] = feval(instruct.LCR(ibl).func,... instruct.LCR(ibl).section,... instruct.LCR(ibl).pvmatrix(iel,:),... instruct.LCR(ibl).parnames,... y,[],0); instruct.LCR(ibl).nintvar(iel) = columns(a)-instruct.LCR(ibl).nextvar; instruct.LCR(ibl).osintvar(iel) = intvar; intvar += instruct.LCR(ibl).nintvar(iel); end ## endfor end ## endfor instruct.totintvar = intvar; ##################################### ## ## Build initial system ## ##################################### n = instruct.totextvar+instruct.totintvar; A = spalloc(n,n,0); ###### ## LCR section ###### B = spalloc(n,n,0); C = spalloc(n,1,0); nblocks = length(instruct.LCR); for ibl = 1:nblocks for iel = 1:instruct.LCR(ibl).nrows ## evaluate element if instruct.LCR(ibl).nintvar(iel) intvars = instruct.totextvar+instruct.LCR(ibl).osintvar(iel)+... [1:instruct.LCR(ibl).nintvar(iel)]'; else intvars=[]; end il = instruct.LCR(ibl).vnmatrix(iel,:)'; nzil = find(il!=0); y = zeros(size(il)); y(nzil)=x(il(nzil)); z = x(intvars); [a,b,c] = feval(instruct.LCR(ibl).func,... instruct.LCR(ibl).section,... instruct.LCR(ibl).pvmatrix(iel,:),... instruct.LCR(ibl).parnames,... y,z,0); ## assemble matrices vars = [il;intvars]; for irow=1:rows(a) if (vars(irow)) for icol=1:columns(a) if (vars(icol)) A(vars(irow),vars(icol)) += a(irow,icol); B(vars(irow),vars(icol)) += b(irow,icol); end ## endif end ## endfor C(vars(irow)) += c(irow); end ## endif end ## endfor end ## endfor end ## endfor varargout{4}=B; varargout{5}=C; end ## endif ###### ## NLC section ###### Jac = spalloc(n,n,0); res = spalloc(n,1,0); nblocks = length(instruct.NLC); for ibl = 1:nblocks for iel = 1:instruct.NLC(ibl).nrows ## evaluate element if instruct.NLC(ibl).nintvar(iel) intvars = instruct.totextvar+instruct.NLC(ibl).osintvar(iel)+... [1:instruct.NLC(ibl).nintvar(iel)]'; else intvars=[]; end il = instruct.NLC(ibl).vnmatrix(iel,:)'; nzil = find(il!=0); y = zeros(size(il)); y(nzil)=x(il(nzil)); z = x(intvars); [a,b,c] = feval(instruct.NLC(ibl).func,... instruct.NLC(ibl).section,... instruct.NLC(ibl).pvmatrix(iel,:),... instruct.NLC(ibl).parnames,... y,z,0); ## assemble matrices vars = [il;intvars]; for irow=1:rows(a) if (vars(irow)) for icol=1:columns(a) if (vars(icol)) A(vars(irow),vars(icol)) += a(irow,icol); Jac(vars(irow),vars(icol)) += b(irow,icol); end ## endif end ## endfor res(vars(irow)) +=... c(irow); end ## endif end ## endfor end ## endfor end ## endfor varargout{1}=A; varargout{2}=Jac; varargout{3}=res; varargout{6}=instruct; ocs/doc/inverter.cir000644 000765 000000 00000000622 11005317740 015200 0ustar00carlowheel000000 000000 %0.1b1 % A Simple MOSFET inverter % Input voltage sources Mvoltagesources sinwave 3 4 1 4 Ampl f delay shift 0.5 1 0.0 0.5 1 0 4 % P-Mosfet Mpmosfet simple 4 3 1 3 k Vth rd -1e-4 -0.1 1e6 1 3 2 3 % N-Mosfet Mnmosfet simple 4 3 1 3 k Vth rd 1e-4 0.1 1e6 1 0 2 0 END % Power supply Mvoltagesources DC 3 1 1 1 V 1 3 0 5 END ocs/doc/inverter.nms000644 000765 000000 00000000031 11005317740 015212 0ustar00carlowheel000000 000000 % 0.1b1 1 Vgate 2 Vdrain ocs/doc/inverter.spc000755 000765 000000 00000000426 11706574500 015224 0ustar00carlowheel000000 000000 * A Simple MOSFET inverter * Input voltage sources V1 Vgate 0 SIN(0.5 0.5 1 0 0) * P-Mosfet .MODEL mypmos PMOS( k=-1e-4 Vth=-0.1 rd=1e6) M2 Vgate 3 Vdrain 3 mypmos * N-Mosfet .MODEL mynmos NMOS( k=1e-4 Vth=0.1 rd=1e6) M3 Vgate 0 Vdrain 0 mynmos * Power supply V4 3 0 1 .END ocs/doc/Mcapacitors.m_in000644 000765 000000 00000001036 11533542746 015770 0ustar00carlowheel000000 000000 function [a,b,c] =... Mcapacitors(string,parameters,parameternames,extvar,intvar,t) ## Mcapacitors(string,parameters,parameternames,extvar,intvar,t) if isempty(intvar) intvar = 0; end switch string case "LIN" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) end q = intvar(1); a = [0 0 1; 0 0 -1; 0 0 0]; b = [0 0 0;0 0 0;C -C -1]; c = [0 0 0]'; break otherwise error (["unknown section:" string]) end ocs/doc/Mcurrentsources.m_in000644 000765 000000 00000001323 11533542746 016725 0ustar00carlowheel000000 000000 function [a,b,c] =... Mcurrentsources(string,parameters,parameternames,extvar,intvar,t) ## [a,b,c] = ... ## Mcurrentsources(string,parameters,parameternames,extvar,intvar,t) switch string case "DC" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) end a = zeros(2); b = a; c = [I -I]'; break case "sinwave" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) end I = shift+Ampl * sin(2*pi*(t+delay)*f ); a = zeros(2); b = a; c = [I -I]'; break otherwise error (["unknown section:" string]) end ocs/doc/Minductors.m_in000644 000765 000000 00000001112 11533542746 015645 0ustar00carlowheel000000 000000 function [a,b,c] =... Minductors(string,parameters,parameternames,extvar,intvar,t) ## Minductors(string,parameters,parameternames,extvar,intvar,t) if isempty(intvar) intvar = [0 0]; end switch string case "LIN" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) end phi = intvar(1); jl = intvar(2); a = [0 0 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 -L]; b = [0 0 -1 0; 0 0 0 1; 1 -1 -1 0; 0 0 1 0]; c = [0 0 0 0]'; otherwise error (["unknown section:" string]) end ocs/doc/Mnmosfet.m_in000644 000765 000000 00000002136 11533542746 015315 0ustar00carlowheel000000 000000 function [a,b,c]=Mnmosfet... (string,parameters,parameternames,extvar,intvar,t) ## [a,b,c]=Mnmosfet... ## (string,parameters,parameternames,extvar,intvar,t) switch string case 'simple', rd = 1e6; for ii=1:length(parameternames) eval([parameternames{ii} "=",... num2str(parameters(ii)) " ;"]) end vg = extvar(1); vs = extvar(2); vd = extvar(3); vb = extvar(4); vgs = vg-vs; vds = vd-vs; if (vgs < Vth) gm = 0; gd = 1/rd; id = vds*gd; elseif ((vgs-Vth)>=(vds))&(vds>=0) id = k*((vgs-Vth)*vds-(vds^2)/2)+vds/rd; gm = k*vds; gd = k*(vgs-Vth-vds)+1/rd; elseif ((vgs-Vth)>=(vds))&(vds<0) gm = 0; gd = 1/rd; id = vds*gd; else # (i.e. if 0 <= vgs-vth <= vds) id = k*(vgs-Vth)^2/2+vds/rd; gm = k*(vgs-Vth); gd = 1/rd; end a = zeros(4); b = [0 0 0 0; -gm (gm+gd) -gd 0; gm -(gm+gd) gd 0; 0 0 0 0]; c = [0 -id id 0]'; break; otherwise error(["unknown option:" string]); end ocs/doc/Mpmosfet.m_in000644 000765 000000 00000002116 11533542746 015315 0ustar00carlowheel000000 000000 function [a,b,c]=Mpmosfet... (string,parameters,parameternames,extvar,intvar,t) ## [a,b,c]=Mpmosfet... ## (string,parameters,parameternames,extvar,intvar,t) switch string case 'simple', rd = 1e6; for ii=1:length(parameternames) eval([parameternames{ii} "=",... num2str(parameters(ii)) " ;"]); end vg = extvar(1); vs = extvar(2); vd = extvar(3); vb = extvar(4); vgs = vg-vs; vds = vd-vs; if (vgs > Vth) gm = 0; gd = 1/rd; id = vds*gd; elseif ((vgs-Vth)<=(vds))&(vds<=0) id = k*((vgs-Vth)*vds-(vds^2)/2)+vds/rd; gm = k*vds; gd = k*(vgs-Vth-vds)+1/rd; elseif ((vgs-Vth)<=(vds))&(vds>0) gm = 0; gd = 1/rd; id = vds*gd; else id = k*(vgs-Vth)^2/2+vds/rd; gm = k*(vgs-Vth); gd = 1/rd; end a = zeros(4); b = [0 0 0 0; -gm (gm+gd) -gd 0; gm -(gm+gd) gd 0; 0 0 0 0 ]; c =[0 -id id 0]'; break; otherwise error(["unknown option:" string]); end ocs/doc/Mresistors.m_in000644 000765 000000 00000001037 11533542746 015676 0ustar00carlowheel000000 000000 function [a,b,c] =... Mresistors(string,parameters,parameternames,extvar,intvar,t) ## [a,b,c] = Mresistors(string,parameters,parameternames,extvar,intvar,t) switch string case "LIN" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) end vp = extvar(1); vm = extvar(2); a = zeros(2); b = [1 -1 ;-1 1]/R; c = -[0; 0]; break otherwise error (["unknown section:" string]) end ocs/doc/Mvoltagesources.m_in000644 000765 000000 00000002375 11533542746 016714 0ustar00carlowheel000000 000000 function [a,b,c] =... Mvoltagesources(string,parameters,parameternames,extvar,intvar,t) ## Mvoltagesources(string,parameters,parameternames,extvar,intvar,t) if isempty(intvar) intvar = 0; end switch string case "DC" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) end j = intvar(1); a = zeros(3); b = [0 0 1;0 0 -1;1 -1 0]; c = [0 0 -V]; break case "sinwave" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) end DV = shift+Ampl * sin(2*pi*(t+delay)*f ); j = intvar(1); a = zeros(3); b = [0 0 1;0 0 -1;1 -1 0]; c = [0 0 -DV]' + b * [extvar;intvar]; break case "squarewave" for ii=1:length(parameternames) eval([parameternames{ii} "=" num2str(parameters(ii)) ";"]) end if t0)|(ii>1) [A,Jac,res] = buildsystemIFF(outstruct,x,t(it)); end xnew = (B+Jac)\(-res - C + Jac*x); nrm(it) = norm(x-xnew,inf); damp = dmp; if (ii>2)&(nrm(it)1 axis([min(t) max(t) 0 1]); plotbynameIFF(t(1:it),out,outstruct,pltvars) end end ocs/doc/runme.m_in000644 000765 000000 00000002652 11533542746 014656 0ustar00carlowheel000000 000000 exmpl ="nmos" out=[]; nrm=[]; switch exmpl case "nmos" outstruct = parseIFF("nmos"); x = [1 .03 1 0 0]'; t = linspace(0,1,50); dmp = .1; pltvars={"Vgate","Vdrain"}; case "pmos" outstruct = parseIFF("pmos"); x = [1 .1 1 0 -1e-6]'; t = linspace(0,.5,50) dmp = .1; pltvars={"Vgate","Vdrain"}; case "inverter" outstruct = parseIFF("inverter"); x = [.5 .5 1 0 0]'; t = linspace(0,1,50); dmp=.1; pltvars={"Vgate","Vdrain"}; case "and" outstruct = parseIFF("and"); x = [.5 .5 .33 .66 .5 1 0 0 1]'; t = linspace(0,.5,50); dmp = .1; pltvars = {"Va","Vb","Va_and_b"}; end tol = 1e-6; dtol= 1e-5; maxit = 200; [A,Jac,res,B,C,outstruct] = initsystemIFF(outstruct,x,0); for it=1:length(t) for ii=1:maxit if (t(it)>0)|(ii>1) [A,Jac,res] = buildsystemIFF(outstruct,x,t(it)); end xnew = (B+Jac)\(-res - C + Jac*x); nrm(it) = norm(x-xnew,inf); damp = dmp; if (ii>2)&(nrm(it)1 axis([min(t) max(t) 0 1]); plotbynameIFF(t(1:it),out,outstruct,pltvars) end end ocs/doc/runmedaspk.m_in000644 000765 000000 00000001407 11533542746 015676 0ustar00carlowheel000000 000000 exmpl ="nmos" out=[]; nrm=[]; switch exmpl case "nmos" outstruct = parseIFF("nmos2"); x = [0 1 1 0 0 0 ]'; t = linspace(0,10,200); pltvars={"Vgate","Vdrain"}; case "TLelement" outstruct = parseIFF("TLelement"); x = [0 0 0 0 0 ]'; t = linspace(0,1,200); pltvars={"Vin","Vout"}; end global A_MATRIX_IFF B_MATRIX_IFF C_MATRIX_IFF OUTSTRUCT_IFF [A_MATRIX_IFF,Jac,res,B_MATRIX_IFF,C_MATRIX_IFF,OUTSTRUCT_IFF] =... initsystemIFF(outstruct,x,0); daspk_options("algebraic variables",[1 1 1 1 1 0 ]'); daspk_options("compute consistent initial condition",2); #daspk_options("relative tolerance",1e-); [x,xdot,istate,msg]= daspk(["funres";"funjac"],x,zeros(size(x)),t); axis([min(t) max(t) 0 1]); plotbynameIFF(t,x',OUTSTRUCT_IFF,pltvars) ocs/doc/spice2ocs_demo.m_in000755 000765 000000 00000005732 11706605532 016426 0ustar00carlowheel000000 000000 clear all; clc; ## Circuit cir = menu ("Chose the circuit to analyze:",\ "AND (Simple algebraic MOS-FET model)",\ "AND (Simple MOS-FET model with parasitic capacitances)",\ "Diode clamper (Simple exponential diode model)",\ "CMOS-inverter circuit (Simple algebraic MOS-FET model)",\ "n-MOS analog amplifier (Simple algebraic MOS-FET model)",\ "Linear RC circuit",\ "Diode bridge rectifier"); switch cir case 1 outstruct = prs_spice ("and"); x = [.5 .5 .33 .66 .5 1 0 0 1 ]'; t = linspace (0,.5,100); pltvars = {"Va","Vb","Va_and_b"}; dmp = .2; tol = 1e-15; maxit = 100; case 2 outstruct = prs_spice ("and2") x = [.8;.8;0.00232;0.00465;.8; .8;0.00232;0.00465;0.00000; 0.0;0.0;0.0;0.00232;0.0; 0.0;0.0;0.0;1.0;0.0;-0.0; 0.0;1.0;0.00465;0.0;0.0; -0.0;1.0;0.00465;0.0; 0.0;0.0;1.0;1.0;0.0;0.0;0.0; 0.0;0.0;0.0]; t = linspace (.25e-6,.5e-6,100); dmp = .1; pltvars = {"Va","Vb","Va_and_b"}; tol = 1e-15; maxit = 100; case 3 outstruct = prs_spice ("diode"); x = [0 0 0 0 0]'; t = linspace (0, 3e-10, 200); dmp = .1; pltvars = {"Vin", "Vout","V2"}; tol = 1e-15; maxit = 100; case 4 outstruct = prs_spice ("inverter"); x = [.5 .5 1 0 0]'; t = linspace (0,1,100); dmp = .1; pltvars={"Vgate","Vdrain"}; tol = 1e-15; maxit = 100; case 5 outstruct = prs_spice ("nmos"); x = [1 .03 1 0 0]'; t = linspace (0,1,50); dmp = .1; pltvars = {"Vgate","Vdrain"}; tol = 1e-15; maxit = 100; case 6 outstruct = prs_spice ("rcs"); x = [0 0 0 0]'; t = linspace (0,2e-5,100); dmp = 1; pltvars = {"Vout"}; tol = 1e-15; maxit = 100; case 7 outstruct = prs_spice ("rect"); x = [0 0 0 0 ]'; t = linspace (0, 3e-10, 60); dmp = .1; pltvars = {"Vin","Voutlow","Vouthigh"}; tol = 1e-15; maxit = 100; otherwise error ("unknown circuit"); endswitch #clc; ## DAE solver slv = menu("Chose the solver to use:", "BWEULER", # 1 "DASPK", # 2 "THETA", # 3 "ODERS", # 4 "ODESX", # 5 "ODE2R", # 6 "ODE5R" # 7 ); out = zeros(rows(x),columns(t)); switch slv case 1 out = tst_backward_euler (outstruct,x,t,tol,maxit,pltvars); case 2 out = tst_daspk (outstruct,x,t,tol,maxit,pltvars); case 3 out = tst_theta_method (outstruct,x,t,tol,maxit,.5,pltvars,[0 0]); case 4 out = tst_odepkg (outstruct,x,t,tol,maxit,pltvars,"oders",[0,1]); case 5 out = tst_odepkg (outstruct,x,t,tol,maxit,pltvars,"odesx",[0,1]); case 6 out = tst_odepkg (outstruct,x,t,tol,maxit,pltvars,"ode2r",[0,1]); case 7 out = tst_odepkg (outstruct,x,t,tol,maxit,pltvars,"ode5r",[0,1]) otherwise error ("unknown solver"); endswitch utl_plot_by_name (t,out,outstruct,pltvars); axis ("tight"); ocs/doc/spice2ocs_syntax.txt000755 000765 000000 00000007065 11706605532 016726 0ustar00carlowheel000000 000000 spice2ocs Syntax Case ---- The parser is case sensitive for parameters, while it is insensitive for element names. Therefore vm1 1 2 3 is the same as: VM1 1 2 3 While M2 3 4 mynmos Vth=0.7 is NOT the same as: M2 3 4 mynmos vth=0.7 Representing numbers: -------------------- Both octave syntax and spice syntax are allowed to be used for representing numbers. For instance, "1U" and "1e-6" are both valid expressions for 10^(-6). SPICE syntax for numbers: MIL -> 25.4e-6 A -> 1e-18 F -> 1e-15 P -> 1e-12 N -> 1e-9 U -> 1e-6 M -> 1e-3 K -> 1e3 MEG -> 1e6 G -> 1e9 T -> 1e12 Elements Cards -------------- - Capacitors: Cname n+ n- cvalue - Diodes: Cname anode knode modelname - MOS: Mname gnode dnode snode bnode modelname N.B.: one instance of a MOS element MUST be preceeded (everywhere in the file) by the declaration of the related model. For instance: .MODEL mynmos NMOS( k=1e-4 Vth=0.1 rd=1e6) M2 Vgate 0 Vdrain 0 mynmos - Resistors: Rname n+ n- rvalue - Voltage sources: Vname n+ n- Transvalue specifies a transient voltage source SIN(VO VA FREQ TD THETA) where: VO (offset) VA (amplitude) FREQ (frequency) TD (delay) THETA (damping factor) 0 to TD: V0 TD to TSTOP: VO + VA*exp(-(time-TD)*THETA)*sine(twopi*FREQ*(time+TD)) Currently the damping factor has no effect. Pulse PULSE(V1 V2 TD TR TF PW PER) parameters meaning V1 (initial value) V2 (pulsed value) TD (delay time) TR (rise time) TF (fall time) PW (pulse width) PER (period) Currently rise and fall time are not implemented yet. - .MODEL cards Defines a model for semiconductor devices .MODEL MNAME TYPE(PNAME1=PVAL1 PNAME2=PVAL2 ... ) TYPE can be: NMOS N-channel MOSFET model PMOS P-channel MOSFET model D diode model The parameter "LEVEL" is currently assigned to the field "section" in the call of the element functions by the solver. Currently supported values for the parameter LEVEL for NMOS and PMOS are: - simple - lincap (see OCS documentation of function Mdiode). Currently supported values for the parameter LEVEL for D are: - simple (see OCS documentation of functions Mdiode and Mpmosfet). Variable names -------------- While in IFF, the variable names are specified into an .nms file, using spice2ocs the variable names are automatically generated by te parser. Particularly, each node is identified by a name (string), related to a(-n external) variable into the state matrix vector. The ground node (index 1 into the variable vector) is by default assigned to the name "0", and it must always appear into the netlist. The parser assigns to each node name an index into the state variable vector. The assigned index depends on the order of appearance of the node name into the netlist. Internal variables represent currents and charges into the system. The name of the internal variables is automatically generated by the parser. For instance, given the element V1 Va Vb 1 It will be related to the variable I(V1) into the vector outstruct.namesn. outstruct.namesn{iv1}="I(V1)" If more internal variables belong to a same element, a variable name is generated just for the first variable. For instance: if the element V1 had 3 internal variables starting from the index iv1, it would result: outstruct.namesn{iv1}="I(V1)" outstruct.namesn{iv1+1}="" outstruct.namesn{iv1+2}="" One is allowed to plot internal and/or external variable of a circuit solved (out) by IFF, by listing them into the pltvars field, when calling the function utl_plot_by_name (t, out, outstruct, pltvars); ocs/doc/TLelement.cir000644 000765 000000 00000000476 11005317740 015242 0ustar00carlowheel000000 000000 % 0.1b1 % A transmition line element % Input voltage source Mvoltagesources sinwave 2 4 1 4 Ampl f delay shift .5 1 0.75 0.5 1 0 END % Resistors Mresistors LIN 2 1 1 1 R 1e6 2 0 % Capacitors %Mcapacitors LIN 2 1 %1 1 %C %1e-7 %3 0 % Inductors Minductors LIN 2 1 1 1 L 1e5 1 2 END ocs/doc/TLelement.nms000644 000765 000000 00000000032 11005317740 015246 0ustar00carlowheel000000 000000 % 0.1b1 1 Vin 2 Vrl 3 Vout