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

📄 cmutil.c

📁 ngspice又一个电子CAD仿真软件代码.功能更全
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ===========================================================================FILE    CMutil.cMEMBER OF process XSPICECopyright 1991Georgia Tech Research CorporationAtlanta, Georgia 30332All Rights ReservedPROJECT A-8503AUTHORS    9/12/91  Jeff MurrayMODIFICATIONS    <date> <person name> <nature of modifications>SUMMARY    This file contains functions callable from user code models.    These functions were written to support code models in the    XSPICE library, but may be useful in general.INTERFACES    cm_smooth_corner()    cm_smooth_discontinuity()    cm_smooth_pwl()    cm_climit_fcn()    cm_complex_set()    cm_complex_add()    cm_complex_subtract()    cm_complex_multiply()    cm_complex_divide()    REFERENCED FILES    None.NON-STANDARD FEATURES    None.=========================================================================== */#include <stdio.h>#include <math.h>#include "cm.h" /* Corner Smoothing Function *************************************                                                               ** The following function smooths the transition between two     ** slopes into a quadratic (parabolic) curve. The calling        ** function passes an x,y coordinate representing the            ** "breakpoint", a smoothing domain value (d), and the slopes at ** both endpoints, and the x value itself. The situation is      ** shown below:              B     C                             **                     A     |<-d->|            ^ y              **            ---------*-----*     |            |                **     lower_slope-^   |<-d->|\    |            |                **                             \   |            |                **                              \  |            *------>x        **  At A<x<C, cm_smooth_corner   \ |                             **  returns a "y" value which     \|                             **  smoothly transitions from      *__                           **  f(A) to f(C) in a parabolic     \ | upper_slope              **  fashion...the slope of the new   \|                          **  function is also returned.        \                          **                                                               ******************************************************************/void cm_smooth_corner(    double x_input,        /* The value of the x input */    double x_center,       /* The x intercept of the two slopes */    double y_center,       /* The y intercept of the two slopes */    double domain,         /* The smoothing domain */    double lower_slope,    /* The lower slope */    double upper_slope,    /* The upper slope */    double *y_output,      /* The smoothed y output */    double *dy_dx)         /* The partial of y wrt x */{    double x_upper,y_upper,a,b,c,dy_dx_temp;    /* Set up parabolic constants */    x_upper = x_center + domain;    y_upper = y_center + (upper_slope * domain);    a = ((upper_slope - lower_slope) / 4.0) * (1 / domain);    b = upper_slope - (2.0 * a * x_upper);    c = y_upper - (a * x_upper * x_upper) - (b * x_upper);    /* Calculate y value & derivative */    dy_dx_temp = 2.0*a*x_input + b;  /* Prevents reassignment problems */                                     /* for x-limiting cases.          */    *y_output = a*x_input*x_input + b*x_input + c;    *dy_dx = dy_dx_temp;}/* Discontinuity Smoothing Function ******************************                                                               ** The following function smooths the transition between two     ** values using an x^2 function. The calling function            ** function passes an x1,y1 coordinate representing the          ** starting point, an x2,y2 coordinate representing an ending    ** point, and the x value itself. The situation is shown below:  **                                                               **            ^ y                        (xu,yu)                 **            |                       ---*-----------            **            |                   ---    |                       **            |                 --                               **            |                -         |                       **            |               -                                  **            |              -           |                       **            |            --                                    **            | (xl,yl) ---              |                       **        ----|----*---                                          **            |    |                     |                       **            O------------------------------------->x           ******************************************************************/void cm_smooth_discontinuity(    double x_input,           /* The x value at which to compute y */    double x_lower,           /* The x value of the lower corner */    double y_lower,           /* The y value of the lower corner */    double x_upper,           /* The x value of the upper corner */    double y_upper,           /* The y value of the upper corner */    double *y_output,         /* The computed smoothed y value */    double *dy_dx)            /* The partial of y wrt x */{    double x_center,y_center,a,b,c,center_slope;    /* Derive x_center, y_center & center_slope values */    x_center = (x_upper + x_lower) / 2.0;    y_center = (y_upper + y_lower) / 2.0;    center_slope = 2.0 * (y_upper - y_lower) / (x_upper - x_lower);    if (x_input < x_lower) {    /* x_input @ lower level */        *y_output = y_lower;        *dy_dx = 0.0;    }    else {        if (x_input < x_center) {   /*  x_input in lower transition */            a = center_slope / (x_upper - x_lower);             b = center_slope - 2.0 * a * x_center;            c = y_center - a * x_center * x_center - b * x_center;            *y_output = a * x_input * x_input + b * x_input + c;            *dy_dx = 2.0 * a * x_input + b;        }        else {                      /*  x_input in upper transition */            if (x_input < x_upper) {                a = -center_slope / (x_upper - x_lower);                 b = -2.0 * a * x_upper;                c = y_upper - a * x_upper * x_upper - b * x_upper;                *y_output = a * x_input * x_input + b * x_input + c;                *dy_dx = 2.0 * a * x_input + b;            }            else {       /* x_input @ upper level */                *y_output = y_upper;                *dy_dx = 0.0;            }        }    }}/* Controlled Limiter Function (modified CLIMIT) *//*This is a special function created for use with the CLIMITcontrolled limiter model.*/void cm_climit_fcn(    double in,                      /* The input value */    double in_offset,               /* The input offset */    double cntl_upper,              /* The upper control input value */    double cntl_lower,              /* The lower control input value */    double lower_delta,             /* The delta from control to limit value */    double upper_delta,             /* The delta from control to limit value */    double limit_range,             /* The limiting range */    double gain,                    /* The gain from input to output */    int    percent,                 /* The fraction vs. absolute range flag */    double *out_final,              /* The output value */    double *pout_pin_final,         /* The partial of output wrt input */    double *pout_pcntl_lower_final, /* The partial of output wrt lower control input */    double *pout_pcntl_upper_final) /* The partial of output wrt upper control input */{/* Define error message string constants */char *climit_range_error = "\n**** ERROR ****\n* CLIMIT function linear range less than zero. *\n";double threshold_upper,threshold_lower,linear_range,           out_lower_limit,out_upper_limit,limited_out,           out,pout_pin,pout_pcntl_lower,pout_pcntl_upper,junk;        /* Find Upper & Lower Limits */    out_lower_limit = cntl_lower + lower_delta;    out_upper_limit = cntl_upper - upper_delta;    if (percent == TRUE)     /* Set range to absolute value */        limit_range = limit_range *               (out_upper_limit - out_lower_limit);    threshold_upper = out_upper_limit -   /* Set Upper Threshold */                         limit_range;    threshold_lower = out_lower_limit +   /* Set Lower Threshold */                         limit_range;    linear_range = threshold_upper - threshold_lower;        /* Test the linear region & make sure there IS one... */    if (linear_range < 0.0) {        printf("%s\n",climit_range_error);                   /*        limited_out = 0.0;        pout_pin = 0.0;          pout_pcntl_lower = 0.0;        pout_pcntl_upper = 0.0;        return;*/    }    /* Compute Un-Limited Output */    out = gain * (in_offset + in);     if (out < threshold_lower) {       /* Limit Out @ Lower Bound */        pout_pcntl_upper= 0.0;        if (out > (out_lower_limit - limit_range)) {  /* Parabolic */            cm_smooth_corner(out,out_lower_limit,out_lower_limit,                        limit_range,0.0,1.0,&limited_out,                        &pout_pin);                     pout_pin = gain * pout_pin;            cm_smooth_discontinuity(out,out_lower_limit,1.0,threshold_lower,                           0.0,&pout_pcntl_lower,&junk);                         }        else {                             /* Hard-Limited Region */            limited_out = out_lower_limit;            pout_pin = 0.0;            pout_pcntl_lower = 1.0;

⌨️ 快捷键说明

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