Qucs-core  0.0.19
qucs_interface.cpp
Go to the documentation of this file.
00001 /*
00002  * qucs_interface.cpp - m-code interface implementation
00003  *
00004  * Copyright (C) 2013 Richard Crozier <richard.crozier@yahoo.co.uk>
00005  *
00006  * This is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2, or (at your option)
00009  * any later version.
00010  *
00011  * This software is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this package; see the file COPYING.  If not, write to
00018  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020  *
00021  * $Id$
00022  *
00023  */
00024 
00025 #if HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028 
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <assert.h>
00032 #include <string.h>
00033 #include <time.h>
00034 
00035 #include "logging.h"
00036 #include "precision.h"
00037 #include "component.h"
00038 #include "components.h"
00039 #include "net.h"
00040 #include "input.h"
00041 #include "dataset.h"
00042 #include "equation.h"
00043 #include "environment.h"
00044 #include "exceptionstack.h"
00045 #include "check_netlist.h"
00046 #include "module.h"
00047 #include "qucs_interface.h"
00048 #include "analysis.h"
00049 #include "e_trsolver.h"
00050 
00051 #if HAVE_UNISTD_H
00052 #include <unistd.h>
00053 #endif
00054 
00055 #include <string>
00056 
00057 using namespace qucs;
00058 
00059 // constructor
00060 qucsint::qucsint ()
00061 {
00062 
00063     //int listing = 0;
00064     ret = 0;
00065     err = 0;
00066 
00067     loginit ();
00068     ::srand (::time (NULL));
00069 
00070 }
00071 
00072 qucsint::qucsint (char* infile)
00073 {
00074     //int listing = 0;
00075     ret = 0;
00076     err = 0;
00077 
00078     loginit ();
00079     ::srand (::time (NULL));
00080 
00081     prepare_netlist (infile);
00082 }
00083 
00084 // destructor
00085 qucsint::~qucsint ()
00086 {
00087     delete subnet;
00088     delete in;
00089 //    delete out;
00090     delete root;
00091 
00092     // delete modules
00093     module::unregisterModules ();
00094 
00095     netlist_destroy_env ();
00096 }
00097 
00099 int qucsint::prepare_netlist (char * infile)
00100 {
00101 
00102     // create static modules
00103     module::registerModules ();
00104 
00105     // create root environment
00106     root = new qucs::environment (std::string("root"));
00107 
00108     // create netlist object and input
00109     subnet = new net ("subnet");
00110 
00111     // test if the file actually exists
00112     FILE * pFile;
00113     pFile = fopen (infile,"r");
00114     if (pFile!=NULL)
00115     {
00116         // close the file again
00117         fclose (pFile);
00118     }
00119     else
00120     {
00121         return NETLIST_FILE_NOT_FOUND;
00122     }
00123 
00124     in = infile ? new input (infile) : new input ();
00125 
00126     // pass root environment to netlist object and input
00127     subnet->setEnv (root);
00128     in->setEnv (root);
00129 
00130     // get input netlist
00131     if (in->netlist (subnet) != 0)
00132     {
00133         if (netlist_check)
00134         {
00135             // replace with mex error message
00136             logprint (LOG_STATUS, "checker notice, netlist check FAILED\n");
00137         }
00138         return NETLIST_FAILED_CHECK;
00139     }
00140 
00141     // attach a ground to the netlist
00142     gnd = new ground ();
00143     gnd->setNode (0, "gnd");
00144     gnd->setName ("GND");
00145     subnet->insertCircuit (gnd);
00146 
00147     // apply some data to all analyses
00148     subnet->setActionNetAll(subnet);
00149 
00150     return NETLIST_OK;
00151 }
00152 
00153 int qucsint::evaluate ()
00154 {
00155     // analyse the netlist
00156     err = 0;
00157     ret = 0;
00158     out = subnet->runAnalysis (err);
00159     ret |= err;
00160 
00161     return ret;
00162 }
00163 
00164 int qucsint::output (char * outfile)
00165 {
00166     // evaluate output dataset
00167     ret |= root->equationSolver (out);
00168 
00169     if (outfile != NULL)
00170     {
00171         out->setFile (outfile);
00172         out->print ();
00173     }
00174 
00175     return ret;
00176 }
00177 
00178 /*/////////////////////////////////////////////////////////////////////////////
00179 
00180                             trsolver_interface
00181 
00183 
00184 trsolver_interface::trsolver_interface ()
00185     : qucsint ()
00186 {
00187     etr = 0;
00188     isInitialised = false;
00189 }
00190 
00191 trsolver_interface::trsolver_interface (char * infile)
00192     : qucsint (infile)
00193 {
00194     isInitialised = false;
00195 
00196     int result = prepare_netlist (infile);
00197 
00198     if (result == NETLIST_OK)
00199     {
00200         getETR ();
00201     }
00202 }
00203 
00204 //trsolver_interface::~trsolver_interface ()
00205 //{
00206 //
00207 //}
00208 
00209 int trsolver_interface::getN (void)
00210 {
00211     if (etr) return etr->getN ();
00212     else return -2;
00213 }
00214 
00215 int trsolver_interface::getM (void)
00216 {
00217     if (etr) return etr->getM ();
00218     else return -2;
00219 }
00220 
00221 // gets a pointer to the trsolver_interface if it is present
00222 void trsolver_interface::getETR()
00223 {
00224     // get a pointer to the external transient solver interface
00225     // the pointer will be to the supclass of e_trsolver, analysis
00226     // so we must perform a dynamic cast to convert it to an e_trsolver
00227     etr = dynamic_cast<e_trsolver *>(subnet->findAnalysis (ANALYSIS_E_TRANSIENT));
00228 
00229     if (etr)
00230     {
00231         isInitialised = true;
00232     }
00233     else
00234     {
00235         isInitialised = false;
00236     }
00237 }
00238 
00239 int trsolver_interface::init (double start, double firstdelta, int mode)
00240 {
00241     if (etr) return etr->init ((nr_double_t)start, (nr_double_t)firstdelta, mode);
00242     else return -2;
00243 }
00244 
00245 
00246 int trsolver_interface::stepsolve_sync (double synctime)
00247 {
00248     if (etr) return etr->stepsolve_sync ((nr_double_t)synctime);
00249     else return -2;
00250 }
00251 
00252 void trsolver_interface::acceptstep_sync (void)
00253 {
00254     if (etr) etr->acceptstep_sync ();
00255 }
00256 
00257 int trsolver_interface::stepsolve_async (double steptime)
00258 {
00259     if (etr) return etr->stepsolve_async ((nr_double_t)steptime);
00260     else return -2;
00261 }
00262 
00263 void trsolver_interface::acceptstep_async (void)
00264 {
00265     if (etr) etr->acceptstep_async ();
00266 }
00267 
00268 void trsolver_interface::rejectstep_async (void)
00269 {
00270     if (etr) etr->rejectstep_async ();
00271 }
00272 
00273 void trsolver_interface::getsolution (double * sol)
00274 {
00275     if (etr) etr->getsolution (sol);
00276 }
00277 
00278 int trsolver_interface::setECVSVoltage(char * ecvsname, double V)
00279 {
00280     if (etr) return etr->setECVSVoltage (ecvsname, (nr_double_t)V);
00281     else return -2;
00282 }
00283 
00284 int trsolver_interface::getJacRows ()
00285 {
00286     if (etr) return etr->getJacRows ();
00287     else return -2;
00288 }
00289 
00290 int trsolver_interface::getJacCols ()
00291 {
00292     if (etr) return etr->getJacCols ();
00293     else return -2;
00294 }
00295 
00296 int trsolver_interface::getJacData (int r, int c, double& data)
00297 {
00298     if (etr)
00299     {
00300         nr_double_t tempdata = (nr_double_t)data;
00301         etr->getJacData (r, c, tempdata);
00302         data = (double)tempdata;
00303         return 0;
00304     }
00305     else
00306     {
00307         return -2;
00308     }
00309 }
00310 
00311 int trsolver_interface::getNodeV (char * label, double& nodeV)
00312 {
00313     if (etr)
00314     {
00315         nr_double_t tempnodeV = (nr_double_t)nodeV;
00316         int flag = etr->getNodeV (label, tempnodeV);
00317         nodeV = (double)tempnodeV;
00318         return flag;
00319     }
00320     else
00321     {
00322         return -2;
00323     }
00324 }
00325 
00326 int trsolver_interface::getVProbeV (char * probename, double& probeV)
00327 {
00328     if (etr)
00329     {
00330         nr_double_t tempprobeV = (nr_double_t)probeV;
00331         int flag = etr->getVProbeV (probename, tempprobeV);
00332         probeV = (double)tempprobeV;
00333         return flag;
00334     }
00335     else
00336     {
00337         return -2;
00338     }
00339 }
00340 
00341 
00342 int trsolver_interface::getIProbeI (char * probename, double& probeI)
00343 {
00344     if (etr)
00345     {
00346         nr_double_t tempprobeI = (nr_double_t)probeI;
00347         int flag = etr->getIProbeI (probename, tempprobeI);
00348         probeI = (double)tempprobeI;
00349         return flag;
00350     }
00351     else
00352     {
00353         return -2;
00354     }
00355 }
00356 
00357 //void trsolver_interface::debug (void)
00358 //{
00359 //    if (etr) etr->debug ();
00360 //}
00361 //
00362 
00363 void trsolver_interface::printSolution (void)
00364 {
00365     if (etr) etr->printx ();
00366 }
00367 
00368 void trsolver_interface::setMessageFcn(void (*newmessagefcn)(int level, const char * format, ...))
00369 {
00370     etr->messagefcn = newmessagefcn;
00371 }