/**********
Copyright 1990 Regents of the University of California.  All rights
reserved.
Author: 1990 Jaijeet S. Roychowdhury
**********/

#include "spice.h"
#include <stdio.h>
#include "util.h"
#include "cktdefs.h"
#include "ltradefs.h"
#include "trandefs.h"
#include "sperror.h"
#include "suffix.h"

int
LTRAacLoad(inModel,ckt)
    GENmodel *inModel;
    CKTcircuit *ckt;
   /* load the appropriate values for the current timepoint into the 
    * sparse matrix and the right-hand-side vector
    */
{
    register LTRAmodel *model = (LTRAmodel *)inModel;
    register LTRAinstance *here;
	double y0_r, y0_i, lambda_r, lambda_i, mag, theta;
	double exparg_r, exparg_i, explambda_r, explambda_i;
	double y0exp_r, y0exp_i;
	int savemode, error;

/*
 * LTRAacLoad - loads for LTRA lines for the s.s. ac case
 * the equations are the following:
 *
 * Y_0(s) * V_1(s) - I_1(s) = exp(-lambda(s)*length) * (Y_0(s) * V_2(s) + I_2(s))
 * Y_0(s) * V_2(s) - I_2(s) = exp(-lambda(s)*length) * (Y_0(s) * V_1(s) + I_1(s))
 *
 * where Y_0(s) and lambda(s) are as follows:
 *
 * Y_0(s) = sqrt( (sC+G)/(sL+R) )
 * lambda(s) = sqrt( (sC+G)*(sL+R) )
 *
 * for the RC, RLC, and LC cases, G=0. The RG case is handled
 * exactly as the DC case, (and the above equations require
 * reformulation because they become identical for the DC case.)
 */

    /*  loop through all the transmission line models */
    for( ; model != NULL; model = model->LTRAnextModel ) {

	switch (model->LTRAspecialCase) {
	
	case LTRA_MOD_LC:

		y0_r = model->LTRAadmit;
		y0_i = 0.0;
		lambda_i = model->LTRAtd*ckt->CKTomega;
		lambda_r = 0.0;
		break;

	case LTRA_MOD_RLC:
		
		theta = 0.5*atan(model->LTRAresist/(ckt->CKTomega*model->LTRAinduct));
		mag = sqrt(ckt->CKTomega*model->LTRAcapac/
			sqrt(model->LTRAresist*model->LTRAresist + 
			ckt->CKTomega*ckt->CKTomega*model->LTRAinduct*
			model->LTRAinduct));
		y0_r = mag*cos(theta);
		y0_i = mag*sin(theta);

		theta = M_PI/2 - theta;
		mag *= sqrt(model->LTRAresist*model->LTRAresist +
			ckt->CKTomega*ckt->CKTomega*model->LTRAinduct*
			model->LTRAinduct);
		lambda_r = mag*cos(theta);
		lambda_i = mag*sin(theta);
		break;

	case LTRA_MOD_RC:

		y0_r = y0_i = sqrt(0.5*ckt->CKTomega*model->LTRAcByR);
		lambda_r = lambda_i =
			sqrt(0.5*ckt->CKTomega*model->LTRAresist*model->LTRAcapac);
		break;
		
	case LTRA_MOD_RG:

		savemode = ckt->CKTmode;
		ckt->CKTmode |= MODEDC;
		error = LTRAload(inModel,ckt);
		ckt->CKTmode = savemode;
		return(error);
		break;

	default: return(E_BADPARM);
}

		exparg_r = -lambda_r*model->LTRAlength;
		exparg_i = -lambda_i*model->LTRAlength;
		explambda_r = exp(exparg_r) * cos(exparg_i);
		explambda_i = exp(exparg_r) * sin(exparg_i);
		y0exp_r = y0_r*explambda_r - y0_i*explambda_i;
		y0exp_i = y0_r*explambda_i + y0_i*explambda_r;

        /* loop through all the instances of the model */
        for (here = model->LTRAinstances; here != NULL ;
                here=here->LTRAnextInstance) {

			
			*(here->LTRAibr1Pos1Ptr + 0) += y0_r;
			*(here->LTRAibr1Pos1Ptr + 1) += y0_i;
			*(here->LTRAibr1Neg1Ptr + 0) -= y0_r;
			*(here->LTRAibr1Neg1Ptr + 1) -= y0_i;

			*(here->LTRAibr1Ibr1Ptr + 0) -= 1.0;

			*(here->LTRAibr1Pos2Ptr + 0) -= y0exp_r;
			*(here->LTRAibr1Pos2Ptr + 1) -= y0exp_i;
			*(here->LTRAibr1Neg2Ptr + 0) += y0exp_r;
			*(here->LTRAibr1Neg2Ptr + 1) += y0exp_i;

			*(here->LTRAibr1Ibr2Ptr + 0) -= explambda_r;
			*(here->LTRAibr1Ibr2Ptr + 1) -= explambda_i;

			
			*(here->LTRAibr2Pos2Ptr + 0) += y0_r;
			*(here->LTRAibr2Pos2Ptr + 1) += y0_i;
			*(here->LTRAibr2Neg2Ptr + 0) -= y0_r;
			*(here->LTRAibr2Neg2Ptr + 1) -= y0_i;

			*(here->LTRAibr2Ibr2Ptr + 0) -= 1.0;

			*(here->LTRAibr2Pos1Ptr + 0) -= y0exp_r;
			*(here->LTRAibr2Pos1Ptr + 1) -= y0exp_i;
			*(here->LTRAibr2Neg1Ptr + 0) += y0exp_r;
			*(here->LTRAibr2Neg1Ptr + 1) += y0exp_i;

			*(here->LTRAibr2Ibr1Ptr + 0) -= explambda_r;
			*(here->LTRAibr2Ibr1Ptr + 1) -= explambda_i;

			*(here->LTRApos1Ibr1Ptr + 0) += 1.0;
			*(here->LTRAneg1Ibr1Ptr + 0) -= 1.0;
			*(here->LTRApos2Ibr2Ptr + 0) += 1.0;
			*(here->LTRAneg2Ibr2Ptr + 0) -= 1.0;
		}
	}
return(OK);
}
