⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cktsens.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/**********Copyright 1991 Regents of the University of California.  All rights reserved.**********/#include "spice.h"#include "util.h"#include "ifsim.h"#include "sperror.h"#include "spmatrix.h"#include "gendefs.h"#include "devdefs.h"#include "cktdefs.h"#include "smpdefs.h"#include "sensdefs.h"#include "sensgen.h"/* #define ASDEBUG */#ifdef ASDEBUG#define DEBUG(X)	if ((X) < Sens_Debug)int Sens_Debug = 0;char SF1[] = "res";char SF2[] = "dc";char SF3[] = "bf";#endifchar *Sfilter = NULL;double Sens_Delta = 0.000001;double Sens_Abs_Delta = 0.000001;static int sens_setp( ), sens_load( ), sens_temp( );int sens_getp( );extern SPICEdev *DEVices[];/* *	Procedure: * *		Determine operating point (call CKTop) * *		For each frequency point: *			(for AC) call NIacIter to get base node voltages *			For each element/parameter in the test list: *				construct the perturbation matrix *				Solve for the sensitivities: *					delta_E = Y^-1 (delta_Y E - delta_I) *				save results */extern double		inc_freq( );static int	error;sens_sens(ckt, restart)	CKTcircuit	*ckt;	int		restart;{	SENS_AN	*sen_info = ((SENS_AN *) ckt->CKTcurJob);	static int	size;	static double	*delta_I, *delta_iI,			*delta_I_delta_Y, *delta_iI_delta_Y;	sgen		*sg;	static double	freq;	static int	nfreqs;	static int	i;	static SMPmatrix	*delta_Y = NULL, *Y;	static double	step_size;	double		*E, *iE;	IFvalue		value, nvalue;	double		*output_values;	IFcomplex	*output_cvalues;	double		delta_var;	int		(*fn)( );	static int	is_dc;	int		k, j, n;	int		num_vars, branch_eq;	char		*sen_data;	char		namebuf[513];	IFuid		*output_names, freq_name;	int		bypass;	int		type;#ifndef notdef	double		*save_states[8];#ifdef notdef	for (sg = sgen_init(ckt, 0); sg; sgen_next(&sg)) {		if (sg->is_instparam)			printf("%s:%s:%s -> param %s\n",				DEVices[sg->dev]->DEVpublic.name,				sg->model->GENmodName,				sg->instance->GENname,				sg->ptable[sg->param].keyword);		else			printf("%s:%s:%s -> mparam %s\n",				DEVices[sg->dev]->DEVpublic.name,				sg->model->GENmodName,				sg->instance->GENname,				sg->ptable[sg->param].keyword);	}#endif#ifdef ASDEBUG	DEBUG(1)		printf(">>> restart : %d\n", restart);#endif	/* get to work */	restart = 1;	if (restart) {		freq = 0.0;		is_dc = (sen_info->step_type == SENS_DC);		nfreqs = count_steps(sen_info->step_type, sen_info->start_freq,			sen_info->stop_freq, sen_info->n_freq_steps,			&step_size);		if (!is_dc)			freq = sen_info->start_freq;		error = CKTop(ckt,			(ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT,			(ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT,			ckt->CKTdcMaxIter);#ifdef notdef		ckt->CKTmode = (ckt->CKTmode & MODEUIC)			| MODEDCOP | MODEINITSMSIG;#endif		if (error)			return error;		size = spGetSize(ckt->CKTmatrix, 1);		/* Create the perturbation matrix */		/* XXX check error return, '1' is complex -- necessary?		 * only in ac */		delta_Y = spCreate(size, !is_dc, &error);		size += 1;		/* Create an extra rhs */		delta_I = NEWN(double, size);		delta_iI = NEWN(double, size);		delta_I_delta_Y = NEWN(double, size);		delta_iI_delta_Y = NEWN(double, size);		num_vars = 0;		for (sg = sgen_init(ckt, is_dc); sg; sgen_next(&sg)) {			num_vars += 1;		}		if (!num_vars)			return OK;	/* XXXX Should be E_ something */		k = 0;		output_names = NEWN(IFuid, num_vars);		for (sg = sgen_init(ckt, is_dc); sg; sgen_next(&sg)) {			if (!sg->is_instparam) {				sprintf(namebuf, "%s:%s",					sg->instance->GENname,					sg->ptable[sg->param].keyword);			} else if ((sg->ptable[sg->param].dataType				& IF_PRINCIPAL) && sg->is_principle == 1)			{				sprintf(namebuf, "%s", sg->instance->GENname);			} else {				sprintf(namebuf, "%s_%s",					sg->instance->GENname,					sg->ptable[sg->param].keyword);			}			(*SPfrontEnd->IFnewUid)((GENERIC *) ckt,				output_names + k, NULL,				namebuf, UID_OTHER, NULL);			k += 1;		}		if (is_dc) {			type = IF_REAL;			freq_name = NULL;		} else {			type = IF_COMPLEX;			(*SPfrontEnd->IFnewUid)((GENERIC *) ckt,				&freq_name, NULL,				"frequency", UID_OTHER, NULL);		}		error = (*SPfrontEnd->OUTpBeginPlot)((GENERIC *) ckt,			(GENERIC *) ckt->CKTcurJob,			ckt->CKTcurJob->JOBname, freq_name, IF_REAL, num_vars,			output_names, type, (GENERIC **) &sen_data);		if (error)			return error;		FREE(output_names);		if (is_dc) {			output_values = NEWN(double, num_vars);			output_cvalues = NULL;		} else {			output_values = NULL;			output_cvalues = NEWN(IFcomplex, num_vars);			if (sen_info->step_type != SENS_LINEAR)			    (*(SPfrontEnd->OUTattributes))((GENERIC *)sen_data,				    NULL, OUT_SCALE_LOG, NULL);		}	} else {		/*XXX Restore saved state */	}#ifdef ASDEBUG	DEBUG(1)		printf("start: %f, num: %d, dc: %d\n", freq, nfreqs, is_dc);#endif	if (!sen_info->output_volt)		branch_eq = CKTfndBranch(ckt, sen_info->output_src);	bypass = ckt->CKTbypass;	ckt->CKTbypass = 0;	/* The unknown vector of node voltages overwrites rhs */	E = ckt->CKTrhs;	iE = ckt->CKTirhs;	ckt->CKTrhsOld = E;	ckt->CKTirhsOld = iE;	Y = ckt->CKTmatrix;#ifdef ASDEBUG	DEBUG(1) {		printf("Operating point:\n");		for (i = 0; i < size; i++)			printf("          E [%d] = %20.15g\n", i, E[i]);	}#endif#ifdef notdef	for (j = 0; j <= ckt->CKTmaxOrder + 1; j++) {		save_states[j] = ckt->CKTstates[j];		ckt->CKTstates[j] = NULL;	}#endif	for (i = 0; i < nfreqs; i++) {		/* XXX handle restart */		n = 0;		if ((*SPfrontEnd->IFpauseTest)( )) {			/* XXX Save State */			return E_PAUSE;		}		for (j = 0; j < size; j++) {			delta_I[j] = 0.0;			delta_iI[j] = 0.0;		}		if (freq != 0.0) {			ckt->CKTrhs = E;			ckt->CKTirhs = iE;			ckt->CKTmatrix = Y;			/* This generates Y in LU form */			ckt->CKTomega = 2.0 * M_PI * freq;			/* Yes, all this has to be re-done */			/* XXX Free old states */			error = CKTunsetup(ckt);			if (error)				return error;			/* XXX ckt->CKTmatrix = Y; */			error = CKTsetup(ckt);			if (error)				return error;			E = ckt->CKTrhs;			iE = ckt->CKTirhs;			Y = ckt->CKTmatrix;#ifdef notdef			for (j = 0; j <= ckt->CKTmaxOrder + 1; j++) {				/* XXX Free new states */				ckt->CKTstates[j] = save_states[j];			}#endif			error = CKTtemp(ckt);			if (error)				return error;			error = CKTload(ckt); /* INITSMSIGS */			if (error)				return error;			error = NIacIter(ckt);			if (error)				return error;#ifdef notdef			/* XXX Why? */			for (j = 0; j <= ckt->CKTmaxOrder + 1; j++) {				ckt->CKTstates[j] = NULL;			}#endif		}		/* Use a different vector & matrix */		ckt->CKTrhs = delta_I;		ckt->CKTirhs = delta_iI;		ckt->CKTmatrix = delta_Y;		/* calc. effect of each param */		for (sg = sgen_init(ckt, is_dc /* sen_info->plist */);			sg; sgen_next(&sg))		{#ifdef ASDEBUG			DEBUG(2) {				printf("E/iE: %x/%x; delta_I/iI: %x/%x\n",					E, iE, delta_I, delta_iI);				printf("cktrhs/irhs: %x/%x\n",					ckt->CKTrhs, ckt->CKTirhs);				if (sg->is_instparam)					printf("%s:%s:%s -> param %s\n",					DEVices[sg->dev]->DEVpublic.name,						sg->model->GENmodName,						sg->instance->GENname,						sg->ptable[sg->param].keyword);				else					printf("%s:%s:%s -> mparam %s\n",					DEVices[sg->dev]->DEVpublic.name,						sg->model->GENmodName,						sg->instance->GENname,						sg->ptable[sg->param].keyword);			}#endif			spClear(delta_Y);			for (j = 0; j < size; j++) {				delta_I[j] = 0.0;				delta_iI[j] = 0.0;			}			/* ? should this just call CKTsetup			 * ? but then CKThead would have to get fiddled with */			ckt->CKTnumStates = sg->istate;			fn = DEVices[sg->dev]->DEVsetup;			if (fn)				(*fn)(delta_Y, sg->model, ckt,					/* XXXX insert old state base here ?? */					&ckt->CKTnumStates);			/* ? CKTsetup would call NIreinit instead */			ckt->CKTniState = NISHOULDREORDER | NIACSHOULDREORDER;			/* XXX instead of calling temp here, just swap			 * back to the original states */			(void) sens_temp(sg, ckt);			/* XXX Leave original E until here!! so that temp reads			 * the right node voltages */			if (sens_load(sg, ckt, is_dc)) {				if (error && error != E_BADPARM)					return error;	/* XXX */				continue;			}			/* Alter the parameter */#ifdef ASDEBUG			DEBUG(1) printf("Original value: %g\n", sg->value);#endif#ifdef ASDEBUG			DEBUG(2) {				printf("Effect of device:\n");				spPrint(delta_Y, 0, 1, 1);				printf("LHS:\n");				for (j = 0; j < size; j++)					printf("%d: %g, %g\n", j,						delta_I[j], delta_iI[j]);			}#endif			if (sg->value != 0.0)				delta_var = sg->value * Sens_Delta;			else				delta_var = Sens_Abs_Delta;			nvalue.rValue = sg->value + delta_var;#ifdef ASDEBUG			DEBUG(1)				printf("New value: %g\n", nvalue.rValue);#endif			sens_setp(sg, ckt, &nvalue);			if (error && error != E_BADPARM)				return error;			spConstMult(delta_Y, -1.0);			for (j = 0; j < size; j++) {				delta_I[j] *= -1.0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -