Re: [Help-gnucap] how to model sinusoidal dependence on charge?

"[email protected]" <[email protected]>
Newsgroups gmane.comp.gnu.gnucap.devel,gmane.comp.gnu.gnucap.general
Message-ID <[email protected]>
[email protected] a écrit :
> Hi all,
>
> I'm trying to model a device which has a voltage that depends periodically
> on the charge which has passed through it: V=Vc*sin(q)
>
> This seems almost possible with the controlled sources, but not quite,
> since the SIN function always depends on time. Is it possible to implement
> such a device with the model compiler, or could the trigonometric functions
> be generalized to achieve this somehow?
>
>   
Hello,

I have extended an old version of gnucap (2008-08-10 !) to enable the 
use of such functions :
E1 (out 0 in 0) FUNC(3,5) exp=true   means : out=e^(3*in+5)
E1 (out 0 in 0) FUNC(314,-78.5) cos=true means : out=cos(314*in -0,785) 
=  sin(314*in)
E1 (out 0 0 0) FUNC(4,5) xtime=true means : out=4*t+5 where t is the 
time of the simulation

I hope it fit with a new version but I haven't time enough to test it. 
So try it and if it doesn't fit
I'll write it again in a few day (I have started to upgrade to 2009-11-10)

Here what I did in a test purpose. It's not a good program, you are free 
to enhance it.
Morever, I don't know how such an extension fit with the convergence 
algorithm.
So I distribute it in the hope that it will be useful but WITHOUT ANY 
WARRANTY      ;-)

Good Luck.


diff src/Makefile.in
 > am__objects_5 = bm_complex.$(OBJEXT) bm_exp.$(OBJEXT) bm_fit.$(OBJEXT) \
 >     bm_generator.$(OBJEXT) bm_poly.$(OBJEXT) bm_posy.$(OBJEXT) \
 >     bm_pulse.$(OBJEXT) bm_pwl.$(OBJEXT) bm_sffm.$(OBJEXT) \
 >     bm_sin.$(OBJEXT) bm_tanh.$(OBJEXT) bmm_table.$(OBJEXT) \
 >     bmm_semi.$(OBJEXT) bm_func.$(OBJEXT)

 > # behavioral modeling functions
 > BM_SRCS = \
 > bm_complex.cc bm_exp.cc bm_fit.cc bm_generator.cc \
 > bm_poly.cc bm_posy.cc bm_pulse.cc bm_pwl.cc bm_sffm.cc \
 > bm_sin.cc bm_tanh.cc bmm_table.cc bmm_semi.cc bm_func.cc

and here bm_func.cc

// This file was built from bm_posy.cc written by Albert Davis
/* behavioral modeling - functions
 * E1 (out 0 in 0) FUNC(3,5) exp=true   means : out=e^(3*in+5)
 * E1 (out 0 in 0) FUNC(314,-78.5) cos=true means : out=cos(314*in 
-0,785) =  sin(314*in)
 * E1 (out 0 0 0) FUNC(4,5) xtime=true means : out=4*t+5 where t is the 
time of the simultation
 */
#include "u_lang.h"
#include "globals.h"
#include "e_elemnt.h"
#include "bm.h"
/*--------------------------------------------------------------------------*/
namespace {
/*--------------------------------------------------------------------------*/
const bool   _default_exp(false);
const bool   _default_ln(false);
const bool   _default_cos(false);
const bool   _default_tan(false);
const bool   _default_xtime(false);

/*--------------------------------------------------------------------------*/
class EVAL_BM_FUNC : public EVAL_BM_ACTION_BASE {
private:
  PARAMETER<bool>   _exp;
  PARAMETER<bool>   _ln;
  PARAMETER<bool>   _cos;
  PARAMETER<bool>   _tan;
  PARAMETER<bool>   _xtime;
  std::vector<std::pair<PARAMETER<double>,PARAMETER<double> > > _table;
  explicit    EVAL_BM_FUNC(const EVAL_BM_FUNC& p);
public:
  explicit      EVAL_BM_FUNC(int c=0);
        ~EVAL_BM_FUNC()        {}
private: // override vitrual
  bool        operator==(const COMMON_COMPONENT&)const;
  COMMON_COMPONENT* clone()const    {return new EVAL_BM_FUNC(*this);}
  void        print_common_obsolete_callback(OMSTREAM&, LANGUAGE*)const;
  void      elaborate(const COMPONENT*);
  //COMMON_COMPONENT* deflate();    //COMPONENT_COMMON/nothing
  void        tr_eval(ELEMENT*)const;
  //void    ac_eval(ELEMENT*)const; //EVAL_BM_ACTION_BASE
  //bool    has_tr_eval()const;    //EVAL_BM_BASE/true
  //bool    has_ac_eval()const;    //EVAL_BM_BASE/true
  std::string    name()const        {return "func";}
  bool        ac_too()const        {untested();return false;}
  bool        parse_numlist(CS&);
  bool        parse_params_obsolete_callback(CS&);
};
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
EVAL_BM_FUNC::EVAL_BM_FUNC(int c)
  :EVAL_BM_ACTION_BASE(c),
   _exp(_default_exp),
   _ln(_default_ln),
   _cos(_default_cos),
   _tan(_default_tan),
   _xtime(_default_xtime),
   _table()
{
}
/*--------------------------------------------------------------------------*/
EVAL_BM_FUNC::EVAL_BM_FUNC(const EVAL_BM_FUNC& p)
  :EVAL_BM_ACTION_BASE(p),
   _exp(p._exp),
   _ln(p._ln),
   _cos(p._cos),
   _tan(p._tan),
   _xtime(p._xtime),
   _table(p._table)
{
}
/*--------------------------------------------------------------------------*/
bool EVAL_BM_FUNC::operator==(const COMMON_COMPONENT& x)const
{
  const EVAL_BM_FUNC* p = dynamic_cast<const EVAL_BM_FUNC*>(&x);
  bool rv = p
    && _exp == p->_exp
    && _ln == p->_ln
    && _cos == p->_cos
    && _tan == p->_tan
    && _xtime == p->_xtime
    && _table == p->_table
    && EVAL_BM_ACTION_BASE::operator==(x);
  if (rv) {
    untested();
  }
  return rv;
}
/*--------------------------------------------------------------------------*/
void EVAL_BM_FUNC::print_common_obsolete_callback(OMSTREAM& o, LANGUAGE* 
lang)const
{
  assert(lang);
  o << name() << '(';
  for (std::vector<std::pair<PARAMETER<double>,PARAMETER<double> > >::
     const_iterator p = _table.begin();  p != _table.end();  ++p) {
    o << p->second << ',' << p->first << ' ';
  }
  o << ')';
  print_pair(o, lang, "exp", _exp, _exp.has_hard_value());
  print_pair(o, lang, "ln", _ln, _ln.has_hard_value());
  print_pair(o, lang, "cos", _cos, _cos.has_hard_value());
  print_pair(o, lang, "tan", _tan, _tan.has_hard_value());
  print_pair(o, lang, "xtime", _xtime, _xtime.has_hard_value());
  EVAL_BM_ACTION_BASE::print_common_obsolete_callback(o, lang);
}
/*--------------------------------------------------------------------------*/
void EVAL_BM_FUNC::elaborate(const COMPONENT* c)
{
  assert(c);
  const CARD_LIST* par_scope = c->scope();
  assert(par_scope);
  EVAL_BM_ACTION_BASE::elaborate(c);
  _exp.e_val(_default_exp, par_scope);
  _ln.e_val(_default_ln, par_scope);
  _cos.e_val(_default_cos, par_scope);
  _tan.e_val(_default_tan, par_scope);
  _xtime.e_val(_default_xtime, par_scope);

  for (std::vector<std::pair<PARAMETER<double>,PARAMETER<double> > >::
     iterator p = _table.begin();  p != _table.end();  ++p) {
    p->first.e_val(0, par_scope);
    p->second.e_val(0, par_scope);
  }
}
/*--------------------------------------------------------------------------*/
void EVAL_BM_FUNC::tr_eval(ELEMENT* d)const
{
  double x_raw = (_xtime) ? ioffset(SIM::time0) : ioffset(d->_y[0].x);
  double f0 = 0.;  // value
  double f1 = 0.;  // derivative
 
  // x = ax + b
  std::vector<std::pair<PARAMETER<double>,PARAMETER<double> > >::
    const_iterator p = _table.begin(); 
  double x = p->second * x_raw + p->first;
  f1 = p->second;
 
  if(_exp) {
    f0=exp(x); 
    f1*=f0;    
  } else if(_ln) {  // use even   
    if(x>0) {
      f0=log(x);
      f1*=1/x;
    } else if(x==0) {
      f0=-BIGBIG;
      f1=BIGBIG;
      untested();      // why ?
    } else {
      f0=log(-x);
      f1*=1/x;
    } 
  } else if(_cos) {
    f0=cos(x); 
    f1*=-sin(x);
  } else if(_tan) {
    f0=sin(x);
    f1=cos(x);
    if(f1==0.0) {
      if(f0>0.0) f0=BIGBIG;
      else f0=-BIGBIG;
      f1=BIGBIG;
    } else {
      f0=f0/f1;
      f1=1+f0*f0;      
    }
  } else {
    f0=x;
  }

    // end as in bm_posy
  d->_y[0] = FPOLY1(ioffset(d->_y[0].x), f0, f1);      
  tr_final_adjust(&(d->_y[0]), d->f_is_value());
  trace3("fa", d->_y[0].x, d->_y[0].f0, d->_y[0].f1);
}
/*--------------------------------------------------------------------------*/
bool EVAL_BM_FUNC::parse_numlist(CS& cmd)
{
  unsigned start = cmd.cursor();
  unsigned here = cmd.cursor();
  for (;;) {
    unsigned start_of_pair = here;
    std::pair<PARAMETER<double>, PARAMETER<double> > p;
    cmd >> p.second; // value
    if (cmd.stuck(&here)) {
      // no more, graceful finish
      break;
    }else{
      cmd >> p.first; // key
      if (cmd.stuck(&here)) {
    // ran out, but already have half of the pair
    // back up one, hoping somebody else knows what to do with it
    cmd.reset(start_of_pair);
    break;
      }else{
    _table.push_back(p);
      }
    }
  }
  if (cmd.gotit(start)) {
  }else{
    untested();
  }
  return cmd.gotit(start);
}
/*--------------------------------------------------------------------------*/
bool EVAL_BM_FUNC::parse_params_obsolete_callback(CS& cmd)
{
  return ONE_OF
    || Get(cmd, "exp",  &_exp)
    || Get(cmd, "ln",  &_ln)
    || Get(cmd, "cos",  &_cos)
    || Get(cmd, "tan",  &_tan)
    || Get(cmd, "xtime",  &_xtime)
    || EVAL_BM_ACTION_BASE::parse_params_obsolete_callback(cmd)
    ;
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
EVAL_BM_FUNC p1(CC_STATIC);
DISPATCHER<COMMON_COMPONENT>::INSTALL d1(&bm_dispatcher, "func", &p1);
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.