/* ac.c  94.11.18
 * Copyright 1983-1992   Albert Davis
 * ac analysis top
 */
#include "ecah.h"
#include "ac.h"
#include "branch.h"
#include "io.h"
#include "mode.h"
#include "nodestat.h"
#include "status.h"
#include "declare.h"
/*--------------------------------------------------------------------------*/
	void	cmd_ac(const char*,int*);
static	void	ac_sweep(ac_t*);
static	void	ac_first(ac_t*);
static	int	ac_next(ac_t*);
static	void	ac_solve(void);
static	void	ac_clear(void);
static	void	ac_out(const ac_t*);
/*--------------------------------------------------------------------------*/
extern struct nodestuff ns;
extern double *reals, *imags;	    /* big array allocation bases	    */
extern const unsigned aspace;	    /* count of non-zero array elements	    */
extern struct status stats;
extern const struct ioctrl io;
extern ac_t ac;
extern int run_mode;	/* variations on handling of dot cmds		    */
extern int sim_mode;	/* simulation type (AC, DC, ...)		    */
/*--------------------------------------------------------------------------*/
void cmd_ac(const char *cmd, int *cnt)
{
 sim_mode = sAC;
 time_zstart(&(stats.total));
 time_zstart(&(stats.ac));

 allocate(sim_mode);
 ac_setup(cmd,cnt,&ac);
 if (run_mode != rEXECUTE)
    return;
 ac_sweep(&ac);

 time_stop(&(stats.ac));
 time_stop(&(stats.total));
}
/*--------------------------------------------------------------------------*/
static void ac_sweep(ac_t *ac)
{
 tr_head(ac->start, ac->stop, ac->linswp, "Freq");
 ac_first(ac);
 do {
    ac_solve();
    ac_out(ac);
 } while (ac_next(ac));
}
/*--------------------------------------------------------------------------*/
static void ac_first(ac_t *ac)
{
 ac->freq = ac->start;
 ac->omega = ac->freq * kPIx2;
}
/*--------------------------------------------------------------------------*/
static int ac_next(ac_t *ac)
{
double stop;

 if (io.whence)
    return YES;
 stop = (ac->linswp)
    ? ac->stop - ac->step/100.
    : ac->stop / pow(ac->step,.01);
 if (!inorder(ac->start, ac->freq, stop))
    return NO;
 ac->freq = (ac->linswp)
    ? ac->freq + ac->step
    : ac->freq * ac->step;
 ac->omega = ac->freq * kPIx2;
 if (inorder(ac->freq, ac->start, ac->stop))
    return NO;
 return YES;
}
/*--------------------------------------------------------------------------*/
static void ac_solve(void)
{
 ac_clear();
 time_start(&(stats.load));
 ++stats.iter[iTOTAL];
 ac_fill_rl(firstbranch_dev());
 time_stop(&(stats.load));
 xlu();
 xsolve();
}
/*--------------------------------------------------------------------------*/
static void ac_clear(void)
{
 (void)memset((void*)reals,  0, (size_t)aspace	  * sizeof(double));
 (void)memset((void*)imags,  0, (size_t)aspace	  * sizeof(double));
 (void)memset((void*)ns.acx, 0, (size_t)(stats.total_nodes+2)* sizeof(double));
 (void)memset((void*)ns.acy, 0, (size_t)(stats.total_nodes+2)* sizeof(double));
}
/*--------------------------------------------------------------------------*/
static void ac_out(const ac_t *ac)
{
 time_start(&(stats.output));
 plottr(ac->freq);
 tr_print(ac->freq);
 tr_alarm();
 time_stop(&(stats.output));
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
