Пример #1
0
/*>ProcessToolTypes(void)
   ----------------------
   Alters defaults based on icon tool types. Handles the following
   tooltypes:
   
      Size=<x> <y>                  Output dimensions
      Offset=<x> <y>                Output offset
      HPGLMargin=<x> <y>            HPGL paper margins
      Title=<Font> <Size>           Title font and size
      XTitle=<Font> <Size>          X-axis title font and size 
      YTitle=<Font> <Size>          Y-axis title font and size 
      XLabel=<Font> <Size>          X-axis label font and size 
      YLabel=<Font> <Size>          Y-axis label font and size
      Key=<Font> <Size>             Key font and size
      Extralabel=<Font> <Size>      Extra label font and size
      Hatching=ON|OFF               Use hatching or shading
      HatchControl=<thick> <space>  Thickness and spacing of hatching
      Pen0=<R> <G> <B>              Pen colours
      Pen1=<R> <G> <B>
      Pen2=<R> <G> <B>
      Pen3=<R> <G> <B>
      DIR=<directory>               Default directory
      NOSHANGHAI                    Stops editor SHANGHAI under V2.0
      AXISBOUNDS                    EPSF bounding box set to size given by paper
   
   01.07.92 Original
   02.07.92 Added pen colours. Also rebuilds windows if colours have been
            set.
   06.07.92 Added default directory.
   04.08.92 Added NOSHANGHAI
   15.09.92 Added AXISBOUNDS
*/
ProcessToolTypes(void)
{
   struct DiskObject *DiskObj = NULL;
   char   *valptr,
          string[80];
   double value,
          value2;
   int    ival1,
          ival2,
          ival3,
          redowindows = FALSE;
   
   
   if((DiskObj = (struct DiskObject *)
                 GetDiskObject(WBenchMsg->sm_ArgList->wa_Name)) != NULL)
   {
      /* Tooltype: Size=<x> <y>                       */
      if((valptr = FindToolType(DiskObj->do_ToolTypes,"Size")) != NULL)
         if(sscanf(valptr,"%lf %lf",&value,&value2) == 2)
         {
            output.xsize   = value;
            output.ysize   = value2;
         }
      
      /* Tooltype: Offset=<x> <y>                     */
      if((valptr = FindToolType(DiskObj->do_ToolTypes,"Offset")) != NULL)
         if(sscanf(valptr,"%lf %lf",&value,&value2) == 2)
         {
            output.xoffset = value;
            output.yoffset = value2;
         }
      
      /* Tooltype: HPGLMargin=<x> <y>                 */
      if((valptr = FindToolType(DiskObj->do_ToolTypes,"HPGLMargin")) != NULL)
         if(sscanf(valptr,"%lf %lf",&value,&value2) == 2)
         {
            output.xmargin = value;
            output.ymargin = value2;
         }

      /* Tooltype: Title=<font> <size>                */
      if((valptr = FindToolType(DiskObj->do_ToolTypes,"Title")) != NULL)
         if(sscanf(valptr,"%s %lf",string,&value) == 2) 
         {
            strcpy(GTitle.PSFont,string);
            GTitle.PSSize = value;
         }

      /* Tooltype: XAxTitle=<font> <size>             */
      if((valptr = FindToolType(DiskObj->do_ToolTypes,"XTitle")) != NULL)
         if(sscanf(valptr,"%s %lf",string,&value) == 2) 
         {
            strcpy(XTitle.PSFont,string);
            XTitle.PSSize = value;
         }

      /* Tooltype: YAxTitle=<font> <size>             */
      if((valptr = FindToolType(DiskObj->do_ToolTypes,"YTitle")) != NULL)
         if(sscanf(valptr,"%s %lf",string,&value) == 2) 
         {
            strcpy(YTitle.PSFont,string);
            YTitle.PSSize = value;
         }

      /* Tooltype: XLabel=<font> <size>               */
      if((valptr = FindToolType(DiskObj->do_ToolTypes,"XLabel")) != NULL)
         if(sscanf(valptr,"%s %lf",string,&value) == 2) 
         {
            strcpy(XLabel.PSFont,string);
            XLabel.PSSize = value;
         }

      /* Tooltype: YLabel=<font> <size>               */
      if((valptr = FindToolType(DiskObj->do_ToolTypes,"YLabel")) != NULL)
         if(sscanf(valptr,"%s %lf",string,&value) == 2) 
         {
            strcpy(YLabel.PSFont,string);
            YLabel.PSSize = value;
         }

      /* Tooltype: Key=<font> <size>                  */
      if((valptr = FindToolType(DiskObj->do_ToolTypes,"Key")) != NULL)
         if(sscanf(valptr,"%s %lf",string,&value) == 2) 
         {
            strcpy(Defaults.KeyPSFont,string);
            Defaults.KeyPSSize = value;
         }

      /* Tooltype: ExtraLabel=<font> <size>           */
      if((valptr = FindToolType(DiskObj->do_ToolTypes,"ExtraLabel")) != NULL)
         if(sscanf(valptr,"%s %lf",string,&value) == 2) 
         {
            strcpy(Defaults.LabelPSFont,string);
            Defaults.LabelPSSize = value;
         }

      /* Tooltype: Hatching=ON|OFF                    */
      if(MatchToolValue(FindToolType(DiskObj->do_ToolTypes,"Hatching"),"ON"))
         output.hatching = TRUE;
      if(MatchToolValue(FindToolType(DiskObj->do_ToolTypes,"Hatching"),"OFF"))
         output.hatching = FALSE;

      /* Tooltype: HatchControl=<thickness> <spacing> */
      if((valptr = FindToolType(DiskObj->do_ToolTypes,"HatchControl")) != NULL)
         if(sscanf(valptr,"%lf %lf",&value,&value2) == 2) 
         {
            output.hatchthick = value;
            output.hatchspace = value2;
         }

      /* Tooltype: Pen0=<R> <G> <B>                   */
      if((valptr = FindToolType(DiskObj->do_ToolTypes,"Pen0")) != NULL)
         if(sscanf(valptr,"%d %d %d",&ival1,&ival2,&ival3) == 3) 
         {
            ival1 = RANGECHECK(ival1,0,15);
            ival2 = RANGECHECK(ival2,0,15);
            ival3 = RANGECHECK(ival3,0,15);
            SetRGB4(&MyScreen->ViewPort,0,(UBYTE)ival1,(UBYTE)ival2,(UBYTE)ival3);
            redowindows = TRUE;
         }

      /* Tooltype: Pen1=<R> <G> <B>                   */
      if((valptr = FindToolType(DiskObj->do_ToolTypes,"Pen1")) != NULL)
         if(sscanf(valptr,"%d %d %d",&ival1,&ival2,&ival3) == 3) 
         {
            ival1 = RANGECHECK(ival1,0,15);
            ival2 = RANGECHECK(ival2,0,15);
            ival3 = RANGECHECK(ival3,0,15);
            SetRGB4(&MyScreen->ViewPort,1,(UBYTE)ival1,(UBYTE)ival2,(UBYTE)ival3);
            redowindows = TRUE;
         }

      /* Tooltype: Pen2=<R> <G> <B>                   */
      if((valptr = FindToolType(DiskObj->do_ToolTypes,"Pen2")) != NULL)
         if(sscanf(valptr,"%d %d %d",&ival1,&ival2,&ival3) == 3) 
         {
            ival1 = RANGECHECK(ival1,0,15);
            ival2 = RANGECHECK(ival2,0,15);
            ival3 = RANGECHECK(ival3,0,15);
            SetRGB4(&MyScreen->ViewPort,2,(UBYTE)ival1,(UBYTE)ival2,(UBYTE)ival3);
            redowindows = TRUE;
         }

      /* Tooltype: Pen3=<R> <G> <B>                   */
      if((valptr = FindToolType(DiskObj->do_ToolTypes,"Pen3")) != NULL)
         if(sscanf(valptr,"%d %d %d",&ival1,&ival2,&ival3) == 3) 
         {
            ival1 = RANGECHECK(ival1,0,15);
            ival2 = RANGECHECK(ival2,0,15);
            ival3 = RANGECHECK(ival3,0,15);
            SetRGB4(&MyScreen->ViewPort,3,(UBYTE)ival1,(UBYTE)ival2,(UBYTE)ival3);
            redowindows = TRUE;
         }

      /* Tooltype: DIR=<directory>                    */
      if((valptr = FindToolType(DiskObj->do_ToolTypes,"DIR")) != NULL)
         strcpy(Defaults.directory,valptr);

      /* Tooltype: NOSHANGHAI                         */
      if((valptr = FindToolType(DiskObj->do_ToolTypes,"NOSHANGHAI")) != NULL)
         display.shanghai = FALSE;

      /* Tooltype: AXISBOUNDS                         */
      if((valptr = FindToolType(DiskObj->do_ToolTypes,"AXISBOUNDS")) != NULL)
         output.fixbounds = FALSE;

      FreeDiskObject(DiskObj);

/*
//      if(redowindows)
//      {
//         FreeAllGadgets();
//         BuildAllWindows();
//      }
*/
   }
   return(0);
}
Пример #2
0
/* Checks that the guessed balls in the state match up with the real balls
 * for all possible lasers (i.e. not just the ones that the player might
 * have already guessed). This is required because any layout with >4 balls
 * might have multiple valid solutions. Returns non-zero for a 'correct'
 * (i.e. consistent) layout. */
static int check_guesses(game_state *state, int cagey)
{
    game_state *solution, *guesses;
    int i, x, y, n, unused, tmp;
    int ret = 0;

    if (cagey) {
	/*
	 * First, check that each laser the player has already
	 * fired is consistent with the layout. If not, show them
	 * one error they've made and reveal no further
	 * information.
	 *
	 * Failing that, check to see whether the player would have
	 * been able to fire any laser which distinguished the real
	 * solution from their guess. If so, show them one such
	 * laser and reveal no further information.
	 */
	guesses = dup_game(state);
	/* clear out BALL_CORRECT on guess, make BALL_GUESS BALL_CORRECT. */
	for (x = 1; x <= state->w; x++) {
	    for (y = 1; y <= state->h; y++) {
		GRID(guesses, x, y) &= ~BALL_CORRECT;
		if (GRID(guesses, x, y) & BALL_GUESS)
		    GRID(guesses, x, y) |= BALL_CORRECT;
	    }
	}
	n = 0;
	for (i = 0; i < guesses->nlasers; i++) {
	    if (guesses->exits[i] != LASER_EMPTY &&
		guesses->exits[i] != laser_exit(guesses, i))
		n++;
	}
	if (n) {
	    /*
	     * At least one of the player's existing lasers
	     * contradicts their ball placement. Pick a random one,
	     * highlight it, and return.
	     *
	     * A temporary random state is created from the current
	     * grid, so that repeating the same marking will give
	     * the same answer instead of a different one.
	     */
	    random_state *rs = random_new((char *)guesses->grid,
					  (state->w+2)*(state->h+2) *
					  sizeof(unsigned int));
	    n = random_upto(rs, n);
	    random_free(rs);
	    for (i = 0; i < guesses->nlasers; i++) {
		if (guesses->exits[i] != LASER_EMPTY &&
		    guesses->exits[i] != laser_exit(guesses, i) &&
		    n-- == 0) {
		    state->exits[i] |= LASER_WRONG;
		    tmp = laser_exit(state, i);
		    if (RANGECHECK(state, tmp))
			state->exits[tmp] |= LASER_WRONG;
		    state->justwrong = TRUE;
		    free_game(guesses);
		    return 0;
		}
	    }
	}
	n = 0;
	for (i = 0; i < guesses->nlasers; i++) {
	    if (guesses->exits[i] == LASER_EMPTY &&
		laser_exit(state, i) != laser_exit(guesses, i))
		n++;
	}
	if (n) {
	    /*
	     * At least one of the player's unfired lasers would
	     * demonstrate their ball placement to be wrong. Pick a
	     * random one, highlight it, and return.
	     *
	     * A temporary random state is created from the current
	     * grid, so that repeating the same marking will give
	     * the same answer instead of a different one.
	     */
	    random_state *rs = random_new((char *)guesses->grid,
					  (state->w+2)*(state->h+2) *
					  sizeof(unsigned int));
	    n = random_upto(rs, n);
	    random_free(rs);
	    for (i = 0; i < guesses->nlasers; i++) {
		if (guesses->exits[i] == LASER_EMPTY &&
		    laser_exit(state, i) != laser_exit(guesses, i) &&
		    n-- == 0) {
		    fire_laser(state, i);
		    state->exits[i] |= LASER_OMITTED;
		    tmp = laser_exit(state, i);
		    if (RANGECHECK(state, tmp))
			state->exits[tmp] |= LASER_OMITTED;
		    state->justwrong = TRUE;
		    free_game(guesses);
		    return 0;
		}
	    }
	}
	free_game(guesses);
    }

    /* duplicate the state (to solution) */
    solution = dup_game(state);

    /* clear out the lasers of solution */
    for (i = 0; i < solution->nlasers; i++) {
        tmp = range2grid(solution, i, &x, &y, &unused);
        assert(tmp);
        GRID(solution, x, y) = 0;
        solution->exits[i] = LASER_EMPTY;
    }

    /* duplicate solution to guess. */
    guesses = dup_game(solution);

    /* clear out BALL_CORRECT on guess, make BALL_GUESS BALL_CORRECT. */
    for (x = 1; x <= state->w; x++) {
        for (y = 1; y <= state->h; y++) {
            GRID(guesses, x, y) &= ~BALL_CORRECT;
            if (GRID(guesses, x, y) & BALL_GUESS)
                GRID(guesses, x, y) |= BALL_CORRECT;
        }
    }

    /* for each laser (on both game_states), fire it if it hasn't been fired.
     * If one has been fired (or received a hit) and another hasn't, we know
     * the ball layouts didn't match and can short-circuit return. */
    for (i = 0; i < solution->nlasers; i++) {
        if (solution->exits[i] == LASER_EMPTY)
            fire_laser(solution, i);
        if (guesses->exits[i] == LASER_EMPTY)
            fire_laser(guesses, i);
    }

    /* check each game_state's laser against the other; if any differ, return 0 */
    ret = 1;
    for (i = 0; i < solution->nlasers; i++) {
        tmp = range2grid(solution, i, &x, &y, &unused);
        assert(tmp);

        if (solution->exits[i] != guesses->exits[i]) {
            /* If the original state didn't have this shot fired,
             * and it would be wrong between the guess and the solution,
             * add it. */
            if (state->exits[i] == LASER_EMPTY) {
                state->exits[i] = solution->exits[i];
                if (state->exits[i] == LASER_REFLECT ||
                    state->exits[i] == LASER_HIT)
                    GRID(state, x, y) = state->exits[i];
                else {
                    /* add a new shot, incrementing state's laser count. */
                    int ex, ey, newno = state->laserno++;
                    tmp = range2grid(state, state->exits[i], &ex, &ey, &unused);
                    assert(tmp);
                    GRID(state, x, y) = newno;
                    GRID(state, ex, ey) = newno;
                }
		state->exits[i] |= LASER_OMITTED;
            } else {
		state->exits[i] |= LASER_WRONG;
	    }
            ret = 0;
        }
    }
    if (ret == 0 ||
	state->nguesses < state->minballs ||
	state->nguesses > state->maxballs) goto done;

    /* fix up original state so the 'correct' balls end up matching the guesses,
     * as we've just proved that they were equivalent. */
    for (x = 1; x <= state->w; x++) {
        for (y = 1; y <= state->h; y++) {
            if (GRID(state, x, y) & BALL_GUESS)
                GRID(state, x, y) |= BALL_CORRECT;
            else
                GRID(state, x, y) &= ~BALL_CORRECT;
        }
    }

done:
    /* fill in nright and nwrong. */
    state->nright = state->nwrong = state->nmissed = 0;
    for (x = 1; x <= state->w; x++) {
        for (y = 1; y <= state->h; y++) {
            int bs = GRID(state, x, y) & (BALL_GUESS | BALL_CORRECT);
            if (bs == (BALL_GUESS | BALL_CORRECT))
                state->nright++;
            else if (bs == BALL_GUESS)
                state->nwrong++;
            else if (bs == BALL_CORRECT)
                state->nmissed++;
        }
    }
    free_game(solution);
    free_game(guesses);
    state->reveal = 1;
    return ret;
}
Пример #3
0
static game_state *execute_move(game_state *from, char *move)
{
    game_state *ret = dup_game(from);
    int gx = -1, gy = -1, rangeno = -1;

    if (ret->justwrong) {
	int i;
	ret->justwrong = FALSE;
	for (i = 0; i < ret->nlasers; i++)
	    if (ret->exits[i] != LASER_EMPTY)
		ret->exits[i] &= ~(LASER_OMITTED | LASER_WRONG);
    }

    if (!strcmp(move, "S")) {
        check_guesses(ret, FALSE);
        return ret;
    }

    if (from->reveal) goto badmove;
    if (!*move) goto badmove;

    switch (move[0]) {
    case 'T':
        sscanf(move+1, "%d,%d", &gx, &gy);
        if (gx < 1 || gy < 1 || gx > ret->w || gy > ret->h)
            goto badmove;
        if (GRID(ret, gx, gy) & BALL_GUESS) {
            ret->nguesses--;
            GRID(ret, gx, gy) &= ~BALL_GUESS;
        } else {
            ret->nguesses++;
            GRID(ret, gx, gy) |= BALL_GUESS;
        }
        break;

    case 'F':
        sscanf(move+1, "%d", &rangeno);
        if (ret->exits[rangeno] != LASER_EMPTY)
            goto badmove;
        if (!RANGECHECK(ret, rangeno))
            goto badmove;
        fire_laser(ret, rangeno);
        break;

    case 'R':
        if (ret->nguesses < ret->minballs ||
            ret->nguesses > ret->maxballs)
            goto badmove;
        check_guesses(ret, TRUE);
        break;

    case 'L':
        {
            int lcount = 0;
            if (strlen(move) < 2) goto badmove;
            switch (move[1]) {
            case 'B':
                sscanf(move+2, "%d,%d", &gx, &gy);
                if (gx < 1 || gy < 1 || gx > ret->w || gy > ret->h)
                    goto badmove;
                GRID(ret, gx, gy) ^= BALL_LOCK;
                break;

#define COUNTLOCK do { if (GRID(ret, gx, gy) & BALL_LOCK) lcount++; } while (0)
#define SETLOCKIF(c) do {                                       \
    if (lcount > (c)) GRID(ret, gx, gy) &= ~BALL_LOCK;          \
    else              GRID(ret, gx, gy) |= BALL_LOCK;           \
} while(0)

            case 'C':
                sscanf(move+2, "%d", &gx);
                if (gx < 1 || gx > ret->w) goto badmove;
                for (gy = 1; gy <= ret->h; gy++) { COUNTLOCK; }
                for (gy = 1; gy <= ret->h; gy++) { SETLOCKIF(ret->h/2); }
                break;

            case 'R':
                sscanf(move+2, "%d", &gy);
                if (gy < 1 || gy > ret->h) goto badmove;
                for (gx = 1; gx <= ret->w; gx++) { COUNTLOCK; }
                for (gx = 1; gx <= ret->w; gx++) { SETLOCKIF(ret->w/2); }
                break;

#undef COUNTLOCK
#undef SETLOCKIF

            default:
                goto badmove;
            }
        }
        break;

    default:
        goto badmove;
    }

    return ret;

badmove:
    free_game(ret);
    return NULL;
}
Пример #4
0
int HSM2temp(
     GENmodel *inModel,
     CKTcircuit *ckt)
{
  HSM2model *model = (HSM2model *)inModel ;
  HSM2instance *here ;
  HSM2binningParam *pParam ;
  HSM2modelMKSParam *modelMKS ;
  HSM2hereMKSParam  *hereMKS ;
  double mueph ;
  double Leff, dL , LG, Weff, dW , WG , WL , Lgate , Wgate;
  double Nsubpp, Nsubps, Nsub, q_Nsub, Nsubb, Npext ;
  double Lod_half, Lod_half_ref ;
  double MUEPWD = 0.0 ;
  double MUEPLD = 0.0 ;
  double GDLD = 0.0 ;
  double T1, T2, T3 ;
  const double small = 1.0e-50 ;
  /* temperature-dependent variables */
  double Eg ,TTEMP, beta, Nin;
  double js, jssw, js2, jssw2 ;
  double Tratio ;
  int i;

  /* declarations for the sc3 clamping part */
  double A, beta_inv, c_eox, cnst0, cnst1, Cox, Cox_inv;
  double Denom, dPpg, dVth, dVthLP, dVthLP_dVb, dVthSC, dVthW;
  double dVth0, dVth0_dVb, fac1, limVgp_dVbs, Pb20, Ps0, Ps0_dVbs;
  double Ps0_min, Qb0, sc3lim, sc3Vbs, sc3Vgs, term1, term2, term3, term4;
  double Tox, T0, T3_dVb, T4, T5, T6, T6_dVb, T8, T8_dVb;
  double T9, T9_dVb, Vgp, Vgs_min, Vfb, Vthp, Vth0;


  for ( ;model ;model = HSM2nextModel(model)) {

    modelMKS = &model->modelMKS ;

    for ( here = HSM2instances(model); here; here = HSM2nextInstance(here)) {
      pParam = &here->pParam ;
      hereMKS = &here->hereMKS ;

      Lgate = here->HSM2_lgate ;
      Wgate = here->HSM2_wgate ;

      LG = here->HSM2_lg ;
      WG = here->HSM2_wg ; 
      WL = WG * LG ;
      MUEPWD = model->HSM2_muepwd * C_m2um ;
      MUEPLD = model->HSM2_muepld * C_m2um ;

      /* Band gap */
      here->HSM2_egtnom = pParam->HSM2_eg0 - model->HSM2_ktnom    
        * ( 90.25e-6 + model->HSM2_ktnom * 1.0e-7 ) ;
  
      /* C_EOX */
      here->HSM2_cecox = C_VAC * model->HSM2_kappa ;
  
      /* Vth reduction for small Vds */
      here->HSM2_msc = model->HSM2_scp22  ;

      /* Poly-Si Gate Depletion */
      if ( pParam->HSM2_pgd1 == 0.0 ) {
        here->HSM2_flg_pgd = 0 ;
      } else {
        here->HSM2_flg_pgd = 1 ;
      }


      /* CLM5 & CLM6 */
      here->HSM2_clmmod = 1e0 + pow( LG , model->HSM2_clm5 ) * model->HSM2_clm6 ;

      /* Half length of diffusion */
      T1 = 1.0 / (model->HSM2_saref + 0.5 * here->HSM2_l)
         + 1.0 / (model->HSM2_sbref + 0.5 * here->HSM2_l);
      Lod_half_ref = 2.0 / T1 ;

      if (here->HSM2_sa > 0.0 && here->HSM2_sb > 0.0 &&
	  (here->HSM2_nf == 1.0 ||
           (here->HSM2_nf > 1.0 && here->HSM2_sd > 0.0))) {
        T1 = 0.0;
        for (i = 0; i < here->HSM2_nf; i++) {
          T1 = T1 + 1.0 / (here->HSM2_sa + 0.5 * here->HSM2_l
                       + i * (here->HSM2_sd + here->HSM2_l))
              + 1.0 / (here->HSM2_sb + 0.5 * here->HSM2_l
                       + i * (here->HSM2_sd + here->HSM2_l));
        }
        Lod_half = 2.0 * here->HSM2_nf / T1;
      } else {
        Lod_half = 0.0;
      }

      Npext = modelMKS->HSM2_npext * ( 1.0 + model->HSM2_npextw / pow( WG, model->HSM2_npextwp ) ); /* new */
      here->HSM2_mueph1 = pParam->HSM2_mueph1 ;
      here->HSM2_nsubp  = pParam->HSM2_nsubp ;
      here->HSM2_nsubc  = pParam->HSM2_nsubc ;

      /* DFM */
      if ( model->HSM2_codfm == 1 && here->HSM2_nsubcdfm_Given ) {
	RANGECHECK(here->HSM2_nsubcdfm,   1.0e16,   1.0e19, "NSUBCDFM") ;
 	here->HSM2_mueph1 = here->HSM2_mueph1 * ( here->HSM2_mphdfm
	   * ( log(hereMKS->HSM2_nsubcdfm) - log(here->HSM2_nsubc) ) + 1.0 ) ;
	here->HSM2_nsubp  = here->HSM2_nsubp + hereMKS->HSM2_nsubcdfm - here->HSM2_nsubc ;
 	Npext = Npext + hereMKS->HSM2_nsubcdfm - here->HSM2_nsubc ;
 	here->HSM2_nsubc = hereMKS->HSM2_nsubcdfm ;
      }

	/* WPE */
        T0 = modelMKS->HSM2_nsubcwpe *
              ( here->HSM2_sca
                + model->HSM2_web * here->HSM2_scb
                + model->HSM2_wec * here->HSM2_scc ) ;
        here->HSM2_nsubc  = here->HSM2_nsubc + T0 ;
        Fn_SLtemp( here->HSM2_nsubc , here->HSM2_nsubc , Nsubmin , Nsubmin_dlt ) ;
        T0 = modelMKS->HSM2_nsubpwpe *
              ( here->HSM2_sca
                + model->HSM2_web * here->HSM2_scb
                + model->HSM2_wec * here->HSM2_scc ) ;
        here->HSM2_nsubp  = here->HSM2_nsubp + T0 ;
        Fn_SLtemp( here->HSM2_nsubp , here->HSM2_nsubp , Nsubmin , Nsubmin_dlt ) ;
        T0 = modelMKS->HSM2_npextwpe *
              ( here->HSM2_sca
                + model->HSM2_web * here->HSM2_scb
                + model->HSM2_wec * here->HSM2_scc ) ;
        Npext = Npext + T0 ;
        Fn_SLtemp( Npext , Npext , Nsubmin , Nsubmin_dlt ) ;
	/* WPE end */

      /* Coulomb Scattering */
      here->HSM2_muecb0 = pParam->HSM2_muecb0 * pow( LG, model->HSM2_muecb0lp );
      here->HSM2_muecb1 = pParam->HSM2_muecb1 * pow( LG, model->HSM2_muecb1lp );

      /* Phonon Scattering (temperature-independent part) */
      mueph = here->HSM2_mueph1  
        * (1.0e0 + (model->HSM2_muephw / pow( WG + MUEPWD , model->HSM2_muepwp))) 
        * (1.0e0 + (model->HSM2_muephl / pow( LG + MUEPLD , model->HSM2_mueplp))) 
        * (1.0e0 + (model->HSM2_muephw2 / pow( WG, model->HSM2_muepwp2))) 
        * (1.0e0 + (model->HSM2_muephl2 / pow( LG, model->HSM2_mueplp2))) 
        * (1.0e0 + (model->HSM2_muephs / pow( WL, model->HSM2_muepsp)));  
      if (Lod_half > 0.0) {
        T1 = 1.0e0 / (1.0e0 + pParam->HSM2_muesti2) ;
        T2 = pow (pParam->HSM2_muesti1 / Lod_half, pParam->HSM2_muesti3) ;
        T3 = pow (pParam->HSM2_muesti1 / Lod_half_ref, pParam->HSM2_muesti3) ;
        here->HSM2_mueph = mueph * (1.0e0 + T1 * T2) / (1.0e0 + T1 * T3); 
      } else {
        here->HSM2_mueph = mueph;
      }
      
      /* Surface Roughness Scattering */
      here->HSM2_muesr = model->HSM2_muesr0 
        * (1.0e0 + (model->HSM2_muesrl / pow (LG, model->HSM2_mueslp))) 
        * (1.0e0 + (model->HSM2_muesrw / pow (WG, model->HSM2_mueswp))) ;

      /* Coefficients of Qbm for Eeff */
      T1 = pow( LG, model->HSM2_ndeplp ) ;
      T2 = pow( WG, model->HSM2_ndepwp ) ; /* new */
      T3 = T1 + model->HSM2_ndepl ;
      T4 = T2 + model->HSM2_ndepw ;
      if( T3 < 1e-8 ) { T3 = 1e-8; } 
      if( T4 < 1e-8 ) { T4 = 1e-8; } 
      here->HSM2_ndep_o_esi = ( pParam->HSM2_ndep * T1 ) / T3  * T2 / T4
	/ C_ESI ;
      here->HSM2_ninv_o_esi = pParam->HSM2_ninv / C_ESI ;

      /* LG dependence of NINVD */
      here->HSM2_ninvd = model->HSM2_ninvd * ( 1.0 + (model->HSM2_ninvdl / pow( LG, model->HSM2_ninvdlp)));

      /* Metallurgical channel geometry */
      dL = model->HSM2_xld 
        + (modelMKS->HSM2_ll / pow (Lgate + model->HSM2_lld, model->HSM2_lln)) ;
      dW = model->HSM2_xwd 
        + (modelMKS->HSM2_wl / pow (Wgate + model->HSM2_wld, model->HSM2_wln)) ;  
    
      Leff = Lgate - 2.0e0 * dL ;
      if ( Leff <= 1.0e-9 ) {   
        SPfrontEnd->IFerrorf
          ( 
           ERR_FATAL, 
           "HiSIM2: MOSFET(%s) MODEL(%s): effective channel length is smaller than 1nm", 
           model->HSM2modName, here->HSM2name);
        return (E_BADPARM);
      }
      here->HSM2_leff = Leff ;

      /* Wg dependence for short channel devices */
      here->HSM2_lgatesm = Lgate + model->HSM2_wl1 / pow( WL , model->HSM2_wl1p ) ;
      here->HSM2_dVthsm = pParam->HSM2_wl2 / pow( WL , model->HSM2_wl2p ) ;

      /* Lg dependence of wsti */
      T1 = 1.0e0 + model->HSM2_wstil / pow( here->HSM2_lgatesm * C_m2um , model->HSM2_wstilp ) ;
      T2 = 1.0e0 + model->HSM2_wstiw / pow( WG , model->HSM2_wstiwp ) ;
      here->HSM2_wsti = pParam->HSM2_wsti * T1 * T2 ;

      here->HSM2_weff = Weff = Wgate - 2.0e0 * dW ;
      if ( Weff <= 0.0 ) {   
        SPfrontEnd->IFerrorf
          ( 
           ERR_FATAL, 
           "HiSIM2: MOSFET(%s) MODEL(%s): effective channel width is negative or 0", 
           model->HSM2modName, here->HSM2name);
        return (E_BADPARM);
      }
      here->HSM2_weff_nf = Weff * here->HSM2_nf ;

      /* Surface impurity profile */
      /* Nsubp */
      if(model->HSM2_nsubpfac < 1.0) {
      T1 = 2.0 * ( 1.0 - model->HSM2_nsubpfac ) / model->HSM2_nsubpl * LG + 2.0 * model->HSM2_nsubpfac - 1.0 ;
      Fn_SUtemp( T1 , T1 , 1 , model->HSM2_nsubpdlt ) ;
      Fn_SLtemp( T1 , T1 , model->HSM2_nsubpfac  , model->HSM2_nsubpdlt ) ;
      here->HSM2_nsubp = here->HSM2_nsubp * T1 ;
      }

      /* Note: Sign Changed --> */
      Nsubpp = here->HSM2_nsubp  
        * (1.0e0 + (model->HSM2_nsubpw / pow (WG, model->HSM2_nsubpwp))) ;
      /* <-- Note: Sign Changed */

      if (Lod_half > 0.0) {
        T1 = 1.0e0 / (1.0e0 + pParam->HSM2_nsubpsti2) ;
        T2 = pow (pParam->HSM2_nsubpsti1 / Lod_half, pParam->HSM2_nsubpsti3) ;
        T3 = pow (pParam->HSM2_nsubpsti1 / Lod_half_ref, pParam->HSM2_nsubpsti3) ;
        Nsubps = Nsubpp * (1.0e0 + T1 * T2) / (1.0e0 + T1 * T3) ;
      } else {
        Nsubps = Nsubpp ;
      }

      T2 = 1.0e0 + ( model->HSM2_nsubcw / pow ( WG, model->HSM2_nsubcwp )) ;
      T2 = T2 * ( 1.0e0 + ( model->HSM2_nsubcw2 / pow ( WG, model->HSM2_nsubcwp2 )) ) ;
      T3 = modelMKS->HSM2_nsubcmax / here->HSM2_nsubc ;

      Fn_SUtemp( T1 , T2 , T3 , 0.01 ) ;
      here->HSM2_nsubc = here->HSM2_nsubc * T1 ;

      if (Lod_half > 0.0) {
        T1 = 1.0e0 / (1.0e0 + pParam->HSM2_nsubcsti2) ;
        T2 = pow (pParam->HSM2_nsubcsti1 / Lod_half, pParam->HSM2_nsubcsti3) ;
        T3 = pow (pParam->HSM2_nsubcsti1 / Lod_half_ref, pParam->HSM2_nsubcsti3) ;
        here->HSM2_nsubc = here->HSM2_nsubc * (1.0e0 + T1 * T2) / (1.0e0 + T1 * T3) ;
      }

      if(model->HSM2_coerrrep && (here->HSM2_nsubc <= 0.0)) {
        fprintf ( stderr , "*** warning(HiSIM): actual NSUBC value is negative -> reset to 1E+15.\n" ) ;
        fprintf ( stderr , "    The model parameter  NSUBCW/NSUBCWP and/or NSUBCW2/NSUBCW2P might be wrong.\n" ) ;
        here->HSM2_nsubc = 1e15 / C_cm2m_p3 ;
      }
      if( (model->HSM2_codep==0) && model->HSM2_coerrrep && (Npext < here->HSM2_nsubc || Npext > here->HSM2_nsubp)) {
        fprintf ( stderr , "*** warning(HiSIM): actual NPEXT value is smaller than NSUBC and/or greater than NSUBP.\n" ) ;
        fprintf ( stderr , "    ( Npext = %e , NSUBC = %e , NSUBP = %e ) \n",Npext,here->HSM2_nsubc,here->HSM2_nsubp);
        fprintf ( stderr , "    The model parameter  NPEXTW and/or NPEXTWP might be wrong.\n" ) ;
      }

      if( Lgate > model->HSM2_lp ){
        Nsub = (here->HSM2_nsubc * (Lgate - model->HSM2_lp) 
                +  Nsubps  * model->HSM2_lp) / Lgate ;
      } else {
        Nsub = Nsubps
          + (Nsubps - here->HSM2_nsubc) * (model->HSM2_lp - Lgate) 
          / model->HSM2_lp ;
      }
      T3 = 0.5e0 * Lgate - model->HSM2_lp ;
      Fn_SZtemp( T3 , T3 , lpext_dlt ) ;
      T1 = Fn_Max(0.0e0, model->HSM2_lpext ) ;
      T2 = T3 * T1 / ( T3 + T1 ) ;

      here->HSM2_nsub = 
        Nsub = Nsub + T2 * (Npext - here->HSM2_nsubc) / Lgate ;
      here->HSM2_qnsub = q_Nsub  = C_QE * Nsub ;
      here->HSM2_qnsub_esi = q_Nsub * C_ESI ;
      here->HSM2_2qnsub_esi = 2.0 * here->HSM2_qnsub_esi ;

      /* Pocket Overlap (temperature-independent part) */
      if ( Lgate <= 2.0e0 * model->HSM2_lp ) {
        Nsubb = 2.0e0 * Nsubps 
          - (Nsubps - here->HSM2_nsubc) * Lgate 
          / model->HSM2_lp - here->HSM2_nsubc ;
        here->HSM2_ptovr0 = log (Nsubb / here->HSM2_nsubc) ;
      } else {
        here->HSM2_ptovr0 = 0.0e0 ;
      }

      /* costi0 and costi1 for STI transistor model (temperature-independent part) */
      here->HSM2_costi00 = sqrt (2.0 * C_QE * pParam->HSM2_nsti * C_ESI ) ;
      here->HSM2_nsti_p2 = 1.0 / ( pParam->HSM2_nsti * pParam->HSM2_nsti ) ;

      /* Velocity Temperature Dependence (Temperature-dependent part will be multiplied later.) */
      here->HSM2_vmax0 = (1.0e0 + (model->HSM2_vover / pow (LG, model->HSM2_voverp)))
        * (1.0e0 + (model->HSM2_vovers / pow (WL, model->HSM2_voversp))) ;

      /* 2 phi_B (temperature-independent) */
      /* @300K, with pocket */
      here->HSM2_pb20 = 2.0e0 / C_b300 * log (Nsub / C_Nin0) ;
      /* @300K, w/o pocket */
      here->HSM2_pb2c = 2.0e0 / C_b300 * log (here->HSM2_nsubc / C_Nin0) ;


      /* constant for Poly depletion */
      here->HSM2_cnstpgd = pow ( 1e0 + 1e0 / LG , model->HSM2_pgd4 ) 
        * pParam->HSM2_pgd1 ;




      /* Gate resistance */
      if ( here->HSM2_corg == 1 ) {
        T1 = here->HSM2_xgw + Weff / (3.0e0 * here->HSM2_ngcon);
        T2 = Lgate - here->HSM2_xgl;
        here->HSM2_grg = model->HSM2_rshg * T1 / (here->HSM2_ngcon * T2 * here->HSM2_nf);
        if (here->HSM2_grg > 1.0e-3) here->HSM2_grg = here->HSM2_m / here->HSM2_grg;
        else {
          here->HSM2_grg = here->HSM2_m * 1.0e3;
          if(model->HSM2_coerrrep) 
          printf("warning(HiSIM2): The gate conductance reset to 1.0e3 mho.\n");
        }
      }

      /* Process source/drain series resistamce */
      here->HSM2_rd = 0.0;
      if ( model->HSM2_rsh > 0.0 ) {
        here->HSM2_rd = here->HSM2_rd + model->HSM2_rsh * here->HSM2_nrd ;
      } 
      if ( model->HSM2_rd > 0.0 ) {
       here->HSM2_rd = here->HSM2_rd + model->HSM2_rd / here->HSM2_weff_nf ;
     }

      here->HSM2_rs = 0.0;
      if ( model->HSM2_rsh > 0.0 ) {
        here->HSM2_rs = here->HSM2_rs + model->HSM2_rsh * here->HSM2_nrs ;
      }
      if ( model->HSM2_rs > 0.0 ) {
        here->HSM2_rs = here->HSM2_rs + model->HSM2_rs / here->HSM2_weff_nf ; 
      }

      if (model->HSM2_corsrd < 0) {
        if ( here->HSM2_rd > 0.0 ) {
          here->HSM2drainConductance = here->HSM2_m / here->HSM2_rd ;
        } else {
          here->HSM2drainConductance = 0.0;
        }
        if ( here->HSM2_rs > 0.0 ) {
          here->HSM2sourceConductance = here->HSM2_m / here->HSM2_rs ;
        } else {
          here->HSM2sourceConductance = 0.0;
        }
      } else if (model->HSM2_corsrd > 0) {
        here->HSM2drainConductance = 0.0 ;
        here->HSM2sourceConductance = 0.0 ;
        if ( here->HSM2_rd > 0.0 && model->HSM2_cothrml != 0 ) {
          here->HSM2internalGd = here->HSM2_m / here->HSM2_rd ;
        } else {
          here->HSM2internalGd = 0.0;
        }
        if ( here->HSM2_rs > 0.0 && model->HSM2_cothrml != 0 ) {
          here->HSM2internalGs = here->HSM2_m / here->HSM2_rs ;
        } else {
          here->HSM2internalGs = 0.0;
        }
      } else {
        here->HSM2drainConductance = 0.0 ;
        here->HSM2sourceConductance = 0.0 ;
      }


      /* Body resistance */
      if ( here->HSM2_corbnet == 1 ) {
        if (here->HSM2_rbdb < 1.0e-3) here->HSM2_grbdb = here->HSM2_m * 1.0e3 ; /* in mho */
        else here->HSM2_grbdb = here->HSM2_m * ( model->HSM2_gbmin + 1.0 / here->HSM2_rbdb ) ;

        if (here->HSM2_rbpb < 1.0e-3) here->HSM2_grbpb = here->HSM2_m * 1.0e3 ;
        else here->HSM2_grbpb = here->HSM2_m * ( model->HSM2_gbmin + 1.0 / here->HSM2_rbpb ) ;

        if (here->HSM2_rbps < 1.0e-3) here->HSM2_grbps = here->HSM2_m * 1.0e3 ;
        else here->HSM2_grbps = here->HSM2_m * ( model->HSM2_gbmin + 1.0 / here->HSM2_rbps ) ;

        if (here->HSM2_rbsb < 1.0e-3) here->HSM2_grbsb = here->HSM2_m * 1.0e3 ;
        else here->HSM2_grbsb = here->HSM2_m * ( model->HSM2_gbmin + 1.0 / here->HSM2_rbsb ) ;

        if (here->HSM2_rbpd < 1.0e-3) here->HSM2_grbpd = here->HSM2_m * 1.0e3 ;
        else here->HSM2_grbpd = here->HSM2_m * ( model->HSM2_gbmin + 1.0 / here->HSM2_rbpd ) ;
      }

      /* Vdseff */
      if ( model->HSM2_coddlt == 0 ) {
        T1 = model->HSM2_ddltslp * LG + model->HSM2_ddltict ;
        here->HSM2_ddlt = T1 * model->HSM2_ddltmax / ( T1 + model->HSM2_ddltmax ) + 1.0 ;
      } else { /* fix in version 2.80 */ 
        T1 = model->HSM2_ddltslp * LG ;
        here->HSM2_ddlt = T1 * model->HSM2_ddltmax / ( T1 + model->HSM2_ddltmax ) + model->HSM2_ddltict + small ;
      }

      /* Isub */
      T2 = pow( Weff , model->HSM2_svgswp ) ;
      here->HSM2_vg2const = pParam->HSM2_svgs
         * ( 1.0e0
           + modelMKS->HSM2_svgsl / pow( here->HSM2_lgate , model->HSM2_svgslp ) )
         * ( T2 / ( T2 + modelMKS->HSM2_svgsw ) ) ; 

      here->HSM2_xvbs = pParam->HSM2_svbs 
         * ( 1.0e0
           + modelMKS->HSM2_svbsl / pow( here->HSM2_lgate , model->HSM2_svbslp ) ) ;
      here->HSM2_xgate = modelMKS->HSM2_slg  
         * ( 1.0
         + modelMKS->HSM2_slgl / pow( here->HSM2_lgate , model->HSM2_slglp ) ) ;

      here->HSM2_xsub1 = pParam->HSM2_sub1 
         * ( 1.0 
         + modelMKS->HSM2_sub1l / pow( here->HSM2_lgate , model->HSM2_sub1lp ) ) ;

      here->HSM2_xsub2 = pParam->HSM2_sub2
         * ( 1.0 + modelMKS->HSM2_sub2l / here->HSM2_lgate ) ;

      /* Fringing capacitance */
      here->HSM2_cfrng = C_EOX / ( C_Pi / 2.0e0 ) * here->HSM2_weff_nf 
         * log( 1.0e0 + model->HSM2_tpoly / model->HSM2_tox ) ; 

      /* Additional term of lateral-field-induced capacitance */
      here->HSM2_cqyb0 = C_m2um * here->HSM2_weff_nf
	* model->HSM2_xqy1 / pow( LG , model->HSM2_xqy2 ) ;

      /* Parasitic component of the channel current */
      GDLD = model->HSM2_gdld * C_m2um ;
      here->HSM2_ptl0 = model->HSM2_ptl * pow( LG        , - model->HSM2_ptlp ) ;
      here->HSM2_pt40 = model->HSM2_pt4 * pow( LG        , - model->HSM2_pt4p ) ;
      here->HSM2_gdl0 = model->HSM2_gdl * pow( LG + GDLD , - model->HSM2_gdlp ) ;


      /*-----------------------------------------------------------*
       * Temperature dependent constants. 
       *-----------------*/
        TTEMP = ckt->CKTtemp ;
        if ( here->HSM2_temp_Given ) TTEMP = here->HSM2_ktemp ;
        if ( here->HSM2_dtemp_Given ) {
          TTEMP = TTEMP + here->HSM2_dtemp ;
          here->HSM2_ktemp = TTEMP ;
        }

        /* Band gap */
        T1 = TTEMP - model->HSM2_ktnom ;
        T2 = TTEMP * TTEMP - model->HSM2_ktnom * model->HSM2_ktnom ;
        here->HSM2_eg = Eg = here->HSM2_egtnom - pParam->HSM2_bgtmp1 * T1
          - pParam->HSM2_bgtmp2 * T2 ;
        here->HSM2_sqrt_eg = sqrt( Eg ) ;


	T1 = 1.0 / TTEMP ;
	T2 = 1.0 / model->HSM2_ktnom ;
	T3 = here->HSM2_egtnom + model->HSM2_egig
	  + model->HSM2_igtemp2 * ( T1 - T2 )
	  + model->HSM2_igtemp3 * ( T1 * T1 - T2 * T2 ) ;
 	here->HSM2_egp12 = sqrt ( T3 ) ;
 	here->HSM2_egp32 = T3 * here->HSM2_egp12 ;

        
        /* Inverse of the thermal voltage */
        here->HSM2_beta = beta = C_QE / (C_KB * TTEMP) ;
        here->HSM2_beta_inv = 1.0 / beta ;
        here->HSM2_beta2 = beta * beta ;
        here->HSM2_betatnom = C_QE / (C_KB * model->HSM2_ktnom) ;

        Tratio =   TTEMP / model->HSM2_ktnom ;

        /* Intrinsic carrier concentration */
        here->HSM2_nin = Nin = C_Nin0 * pow (Tratio, 1.5e0) 
          * exp (- Eg / 2.0e0 * beta + here->HSM2_egtnom / 2.0e0 * here->HSM2_betatnom) ;


        /* Phonon Scattering (temperature-dependent part) */
        T1 =  pow (Tratio, pParam->HSM2_muetmp) ;
        here->HSM2_mphn0 = T1 / here->HSM2_mueph ;
        here->HSM2_mphn1 = here->HSM2_mphn0 * model->HSM2_mueph0 ;


        /* Pocket Overlap (temperature-dependent part) */
        here->HSM2_ptovr = here->HSM2_ptovr0 / beta ;


        /* Velocity Temperature Dependence */
        here->HSM2_vmax = here->HSM2_vmax0 * pParam->HSM2_vmax 
          / (1.8 + 0.4 * Tratio + 0.1 * Tratio * Tratio - pParam->HSM2_vtmp * (1.0e0 - Tratio)) ;


        /* Coefficient of the F function for bulk charge */
        /* Depletion mode MOSFET  */
        if( model->HSM2_codep ) {
          T3 = pow(here->HSM2_lg,model->HSM2_ndepmlp) ;
          here->HSM2_ndepm = modelMKS->HSM2_ndepm * ( 1.0 + model->HSM2_ndepml / T3 );
          if ( here->HSM2_ndepm < 1e+21 ) { here->HSM2_ndepm = 1e+21 ; }
          here->HSM2_Pb2n = 2.0/beta*log(here->HSM2_ndepm/Nin) ;
          here->HSM2_Vbipn = 1.0/beta*log(here->HSM2_ndepm*here->HSM2_nsub/Nin/Nin) ;
          here->HSM2_cnst0 = sqrt ( 2.0 * C_ESI * C_QE * here->HSM2_ndepm / beta ) ;
          here->HSM2_cnst1 = Nin*Nin/here->HSM2_ndepm/here->HSM2_ndepm ;

          T1 =  Fn_Pow(Tratio, model->HSM2_depmuetmp) ;
          here->HSM2_depmphn0 = T1 / model->HSM2_depmueph1 ;
          here->HSM2_depmphn1 = here->HSM2_depmphn0 * model->HSM2_depmueph0 ;
//        T0 = 1.8 + 0.4 * Tratio + 0.1 * Tratio * Tratio - model->HSM2_depvtmp * ( 1.0 - Tratio ) ;
          T0 = 1.0 ; // ignore DEPVTMP in HiSIM2
          here->HSM2_depvmax = model->HSM2_depvmax / T0 / C_m2cm ;

         // LG dependence DEPVMAX 
         T3 = pow( here->HSM2_lg, model->HSM2_depvmaxlp ) ;
         here->HSM2_depvmax = here->HSM2_depvmax * ( 1.0 + model->HSM2_depvmaxl / T3 ) ;
         if( here->HSM2_depvmax < 0.0 ) { here->HSM2_depvmax = 0.0; }

         // LG dependence DEPLEAK 
         T3 = pow( here->HSM2_lg, model->HSM2_depleaklp ) ;
         here->HSM2_depleak = model->HSM2_depleak * ( 1.0 + model->HSM2_depleakl / T3 ) ;
         if( here->HSM2_depleak < 0.0 ) { here->HSM2_depleak = 0.0; }

         // LG dependence DEPMUE0 & DEPMUE1
         T3 = pow( here->HSM2_lg, model->HSM2_depmue0lp ) ;
         here->HSM2_depmue0 = model->HSM2_depmue0 * ( 1.0 + model->HSM2_depmue0l / T3 ) ;
         if( here->HSM2_depmue0 < 1.0 ) { here->HSM2_depmue0 = 1.0; }
         T3 = pow( here->HSM2_lg, model->HSM2_depmue1lp ) ;
         here->HSM2_depmue1 = model->HSM2_depmue1 * ( 1.0 + model->HSM2_depmue1l / T3 ) ;
         if( here->HSM2_depmue1 < 0.0 ) { here->HSM2_depmue1 = 0.0; }

         // LG dependence DEPMUEBACK0 & DEPMUEBACK1
         T3 = pow( here->HSM2_lg, model->HSM2_depmueback0lp ) ;
         here->HSM2_depmueback0 = model->HSM2_depmueback0 * ( 1.0 + model->HSM2_depmueback0l / T3 ) ;
         if( here->HSM2_depmueback0 < 0.0 ) { here->HSM2_depmueback0 = 0.0; }
         T3 = pow( here->HSM2_lg, model->HSM2_depmueback1lp ) ;
         here->HSM2_depmueback1 = model->HSM2_depmueback1 * ( 1.0 + model->HSM2_depmueback1l / T3 ) ;
         if( here->HSM2_depmueback1 < 0.0 ) { here->HSM2_depmueback1 = 0.0; }

         // LG dependence DEPVDSEF1 & DEPVDSEF2
         T3 = pow( here->HSM2_lg, model->HSM2_depvdsef1lp ) ;
         here->HSM2_depvdsef1 = model->HSM2_depvdsef1 * ( 1.0 + model->HSM2_depvdsef1l / T3 ) ;
         if( here->HSM2_depvdsef1 < 0.0 ) { here->HSM2_depvdsef1 = 0.0; }
         T3 = pow( here->HSM2_lg, model->HSM2_depvdsef2lp ) ;
         here->HSM2_depvdsef2 = model->HSM2_depvdsef2 * ( 1.0 + model->HSM2_depvdsef2l / T3 ) ;
         if( here->HSM2_depvdsef2 < 0.1 ) { here->HSM2_depvdsef2 = 0.1; }

        } else {
        /* Normal mode MOSFET  */
          here->HSM2_cnst0 = sqrt ( 2.0 * C_ESI * C_QE * here->HSM2_nsub / beta ) ;
          /* cnst1: n_{p0} / p_{p0} */
          T1 = Nin / here->HSM2_nsub ;
          here->HSM2_cnst1 = T1 * T1 ;
        }

        /* 2 phi_B (temperature-dependent) */
        /* @temp, with pocket */
        here->HSM2_pb2 =  2.0e0 / beta * log (here->HSM2_nsub / Nin) ;
        if ( pParam->HSM2_nover != 0.0) {
	   here->HSM2_pb2over = 2.0 / beta * log( pParam->HSM2_nover / Nin ) ;
	   here->HSM2_cnst0over = sqrt ( 2.0 * C_ESI * C_QE * pParam->HSM2_nover / beta ) ;     
        }else {
           here->HSM2_pb2over = 0.0 ;
           here->HSM2_cnst0over = 0.0 ;
        }


        /* Depletion Width */
        T1 = 2.0e0 * C_ESI / C_QE ;
        here->HSM2_wdpl = sqrt ( T1 / here->HSM2_nsub ) ;
        here->HSM2_wdplp = sqrt( T1 / ( here->HSM2_nsubp ) ) ; 


        /* for substrate-source/drain junction diode. */
        js   = pParam->HSM2_js0
          * exp ((here->HSM2_egtnom * here->HSM2_betatnom - Eg * beta
                  + model->HSM2_xti * log (Tratio)) / pParam->HSM2_nj) ;
        jssw = pParam->HSM2_js0sw
          * exp ((here->HSM2_egtnom * here->HSM2_betatnom - Eg * beta 
                  + model->HSM2_xti * log (Tratio)) / model->HSM2_njsw) ;

        js2  = pParam->HSM2_js0
          * exp ((here->HSM2_egtnom * here->HSM2_betatnom - Eg * beta
                  + model->HSM2_xti2 * log (Tratio)) / pParam->HSM2_nj) ;  
        jssw2 = pParam->HSM2_js0sw
          * exp ((here->HSM2_egtnom * here->HSM2_betatnom - Eg * beta
                  + model->HSM2_xti2 * log (Tratio)) / model->HSM2_njsw) ; 
      
        here->HSM2_isbd = here->HSM2_ad * js + here->HSM2_pd * jssw ;
        here->HSM2_isbd2 = here->HSM2_ad * js2 + here->HSM2_pd * jssw2 ;
        here->HSM2_isbs = here->HSM2_as * js + here->HSM2_ps * jssw ;
        here->HSM2_isbs2 = here->HSM2_as * js2 + here->HSM2_ps * jssw2 ;

        here->HSM2_vbdt = pParam->HSM2_nj / beta 
          * log (pParam->HSM2_vdiffj * (Tratio) * (Tratio) 
                 / (here->HSM2_isbd + 1.0e-50) + 1) ;
        here->HSM2_vbst = pParam->HSM2_nj / beta 
          * log (pParam->HSM2_vdiffj * (Tratio) * (Tratio) 
                 / (here->HSM2_isbs + 1.0e-50) + 1) ;

        here->HSM2_exptemp = exp (((Tratio) - 1) * model->HSM2_ctemp) ;
        here->HSM2_jd_nvtm_inv = 1.0 / ( pParam->HSM2_nj / beta ) ;
        here->HSM2_jd_expcd = exp (here->HSM2_vbdt * here->HSM2_jd_nvtm_inv ) ;
        here->HSM2_jd_expcs = exp (here->HSM2_vbst * here->HSM2_jd_nvtm_inv ) ;

	/* costi0 and costi1 for STI transistor model (temperature-dependent part) */
	here->HSM2_costi0 = here->HSM2_costi00 * sqrt(here->HSM2_beta_inv) ;
	here->HSM2_costi0_p2 = here->HSM2_costi0 * here->HSM2_costi0 ; 
	here->HSM2_costi1 = here->HSM2_nin * here->HSM2_nin * here->HSM2_nsti_p2 ;

        /* check if SC3 is too large */
        if (pParam->HSM2_sc3 && model->HSM2_sc3Vbs < 0.0) {

          beta     = here->HSM2_beta ;
          beta_inv = here->HSM2_beta_inv ;
          Weff     = here->HSM2_weff ;
          Vfb      = pParam->HSM2_vfbc ;
          Pb20     = here->HSM2_pb20 ; 
          cnst0    = here->HSM2_cnst0 ;
          cnst1    = here->HSM2_cnst1 ;
          c_eox    = here->HSM2_cecox ;
          Tox      = model->HSM2_tox ;
          Cox      = c_eox / Tox ;
          Cox_inv  = 1.0 / Cox ;
          fac1     = cnst0 * Cox_inv ;
          Vgs_min  = model->HSM2_type * model->HSM2_Vgsmin ;
          sc3Vbs   = model->HSM2_sc3Vbs ;
          sc3Vgs   = 2.0 ;
          Ps0_min  = 2.0 * beta_inv * log(-Vgs_min/fac1) ;

          /* approximate solution of Poisson equation for large
             Vgs and negative Vbs (3 iterations!)*/
          Vgp = sc3Vgs - Vfb;
          Denom = fac1*sqrt(cnst1);
          Ps0 = 2.0 * beta_inv * log(Vgp/Denom);
          Ps0 = 2.0 * beta_inv * log((Vgp-Ps0)/Denom);
          Ps0 = 2.0 * beta_inv * log((Vgp-Ps0)/Denom);
          Ps0 = 2.0 * beta_inv * log((Vgp-Ps0)/Denom);
          Ps0_dVbs = 0.0;

          T1   = here->HSM2_2qnsub_esi ;
          Qb0  = sqrt ( T1 ) ;
          Vthp = Ps0 + Vfb + Qb0 * Cox_inv + here->HSM2_ptovr ;

          T1     = 2.0 * C_QE * here->HSM2_nsubc * C_ESI ;
          T2     = sqrt( T1 ) ;
          Vth0   = Ps0 + Vfb + T2 * Cox_inv ;
          T1     = C_ESI * Cox_inv ;
          T2     = here->HSM2_wdplp ;
          T4     = 1.0e0 / ( model->HSM2_lp * model->HSM2_lp ) ;
          T3     = 2.0 * ( model->HSM2_vbi - Pb20 ) * T2 * T4 ;
          T5     = T1 * T3 ;
          T6     = Ps0 - sc3Vbs ;
          T6_dVb = Ps0_dVbs - 1.0 ;
          dVth0  = T5 * sqrt( T6 ) ;
          dVth0_dVb = T5 * 0.5 / sqrt( T6 ) * T6_dVb;
          T1     = Vthp - Vth0 ;
          T9     = Ps0 - sc3Vbs ;
          T9_dVb = Ps0_dVbs - 1.0 ;
          T3     = pParam->HSM2_scp1 + pParam->HSM2_scp3 * T9 / model->HSM2_lp;
          T3_dVb = pParam->HSM2_scp3 * T9_dVb / model->HSM2_lp ;
          dVthLP = T1 * dVth0 * T3 ;
          dVthLP_dVb = T1 * dVth0_dVb * T3 + T1 * dVth0 * T3_dVb;

          T3 = here->HSM2_lgate - model->HSM2_parl2 ;
          T4 = 1.0e0 / ( T3 * T3 ) ;
          T0 = C_ESI * here->HSM2_wdpl * 2.0e0 * ( model->HSM2_vbi - Pb20 ) * T4 ;
          T2 = T0 * Cox_inv ;
          T5 = pParam->HSM2_sc3 / here->HSM2_lgate ;
          T6 = pParam->HSM2_sc1 + T5 * ( Ps0 - sc3Vbs ) ;
          T1 = T6 ;
          A  = T2 * T1 ;
          T9 = Ps0 - sc3Vbs + Ps0_min ;
          T9_dVb = Ps0_dVbs - 1.0 ;
          T8     = sqrt( T9 ) ;
          T8_dVb = 0.5 * T9_dVb / T8 ;
          dVthSC = A * T8 ;

          T1 = 1.0 / Cox ;
          T3 = 1.0 / ( Cox + pParam->HSM2_wfc / Weff ) ;
          T5 = T1 - T3 ;
          dVthW = Qb0 * T5 + pParam->HSM2_wvth0 / here->HSM2_wg ;

          dVth = dVthSC + dVthLP + dVthW + here->HSM2_dVthsm ;
          dPpg = 0.0 ;
          Vgp = sc3Vgs - Vfb + dVth - dPpg ;

          /* Recalculation of Ps0, using more accurate Vgp */
          Ps0 = 2.0 * beta_inv * log(Vgp/Denom);
          Ps0 = 2.0 * beta_inv * log((Vgp-Ps0)/Denom);
          Ps0 = 2.0 * beta_inv * log((Vgp-Ps0)/Denom);
          Ps0 = 2.0 * beta_inv * log((Vgp-Ps0)/Denom);

          term1 = Vgp - Ps0;
          term2 = sqrt(beta*(Ps0-sc3Vbs)-1.0);
          term3 = term1 + fac1 * term2;
          term4 = cnst1 * exp(beta*Ps0);
          limVgp_dVbs = - beta * (term3 + 0.5*fac1 * term4/term2)
                  / (2.0*term1/fac1/fac1*term3 - term4);
          T2     = T0 * Cox_inv ;
          sc3lim = here->HSM2_lgate / T2 
               * (limVgp_dVbs - dVthLP_dVb - T2*pParam->HSM2_sc1*T8_dVb)
               / ((Ps0-sc3Vbs)*T8_dVb +(Ps0_dVbs-1.0)*T8);
          if (sc3lim < 1.0e-20)
              sc3lim = 1e-20 ;
          if (sc3lim < pParam->HSM2_sc3 * 0.999) {
            pParam->HSM2_sc3 = sc3lim;
          }
        }
    } /* End of instance loop */
  }
  return(OK);
}