void
pgPrintCurLPObjFunc(Circuit *ckt, FILE *fp)
{

  double    cst, vdrop;
  char     name[128];
  Branches *daux;
  int count = 0;

  assert(ckt->theDeviceList);

  fprintf(fp,"MIN: ");
  for(daux = ckt->theDeviceList; daux; daux = daux->next)
    {

      if(daux->stat != sNormal) 
	continue;

      if(daux->type != dRES) 
	continue;

      /* ignore branch with very small current */
      if(fabs(daux->current) <= MIN_CURRENT ||
	 fabs(ckt->theNodeArray[daux->n1].voltage -
	      ckt->theNodeArray[daux->n2].voltage) <= MIN_VOLTAGE )
	{
	  sprintf(buf,"branch %s: current or voltage drop is close to 0, ignored.\n", 
		  daux->name);
	  print_mesg(buf);
	  daux->stat = sAbnormal;
	  continue;
	}

      count++;
      assert(daux->n1 < (ckt->nMatrixSize+1));
      assert(daux->n2 < (ckt->nMatrixSize+1));
      vdrop = ckt->theNodeArray[daux->n1].voltage -
	      ckt->theNodeArray[daux->n2].voltage;
      cst = daux->length*daux->length*daux->lay->unitRes/(vdrop + FTINY);
        
      /* variable must be positive */
      if(daux->current < 0)
	{
	  cst = -cst;
	  sprintf(name,"IN_%d",daux->index);
	}
      else
	{
	  sprintf(name,"I_%d",daux->index);
	}

      if(cst >= 0)
	fprintf(fp,"+%1.10g %s ", cst, name);
      else
	fprintf(fp,"%1.10g %s ", cst, name);
      if(count%3 == 0)
	fprintf(fp,"\n");
    }
  fprintf(fp,";\n");
}
Пример #2
0
/*
 * Announce an invitation to talk.  If the user is
 * accepting messages, announce that a talk is requested.
 */
int
announce(CTL_MSG *request, char *remote_machine)
{
	char full_tty[MAXPATHLEN];
	FILE *tf;
	struct stat stbuf;

	(void)snprintf(full_tty, sizeof(full_tty), "%s/%s", _PATH_DEV,
	    request->r_tty);
	if (access(full_tty, 0) != 0)
		return (FAILED);
	if ((tf = fopen(full_tty, "w")) == NULL)
		return (PERMISSION_DENIED);
	if (fstat(fileno(tf), &stbuf) < 0) {
		fclose(tf);
		return (PERMISSION_DENIED);
	}
	if ((stbuf.st_mode & S_IWGRP) == 0) {
		fclose(tf);
		return (PERMISSION_DENIED);
	}
	print_mesg(tf, request, remote_machine);
	fclose(tf);
	return (SUCCESS);
}
Пример #3
0
/*
 * See if the user is accepting messages. If so, announce that
 * a talk is requested.
 */
int
announce(CTL_MSG *request, const char *remote_machine)
{
    char full_tty[32];
    struct stat stbuf;

    (void)snprintf(full_tty, sizeof(full_tty),
                   "%s%s", _PATH_DEV, request->r_tty);
    if (stat(full_tty, &stbuf) < 0 || (stbuf.st_mode&020) == 0)
        return (PERMISSION_DENIED);
    return (print_mesg(request->r_tty, request, remote_machine));
}
Пример #4
0
void
main_menu_select(int value)
{
  char title[512];

  switch(value) {
  case 1:
    face_reset ( face ) ;
    glutPostRedisplay();
    break;
  case 2:
    print_mesg();
    break;
  case 3:
    face->muscle[m]->mstat += 0.25 ;
    activate_muscle ( face, 
      face->muscle[m]->head, 
      face->muscle[m]->tail, 
      face->muscle[m]->fs,
      face->muscle[m]->fe,
      face->muscle[m]->zone,
      +0.25 ) ;
    glutPostRedisplay();
    break;
  case 4:
    face->muscle[m]->mstat -= 0.25 ;
    activate_muscle ( face, 
      face->muscle[m]->head, 
      face->muscle[m]->tail, 
      face->muscle[m]->fs,
      face->muscle[m]->fe,
      face->muscle[m]->zone,
      -0.25 ) ;
    glutPostRedisplay();
    break;
  case 5:
    m++ ;
    if ( m >= face->nmuscles ) m = 0 ;
    sprintf(title, "geoface (%s)", face->muscle[m]->name);
    glutSetWindowTitle(title);
    break;
  case 666:
    exit(0);
    break;
  }
}
double pgComputeIntConstValue(IntConst * icp)
{
  Products *paux;
  double     dsum = 0, diff;

  if(!icp)
    return 0;
    
  for(paux = icp->prod_list; paux; paux = paux->next)
    {
      if(paux->branch)/* current variable */
	dsum += paux->sign*paux->coeff*paux->branch->current;
      else if(paux->node) /* voltage variable */
	dsum += paux->sign*paux->coeff*paux->node->voltage;
      else
	{
	  error_mesg(FAT_ERROR,"No variable in product."); 
	  continue;
	}
    }

  dsum += icp->cst;

  if(icp->type == GE && dsum >= 0.0)
    icp->stat = csSatisfied;
  else if((icp->type == GE) && (dsum < 0) && 
	  (fabs(dsum/icp->cst) > 1e-6) )
    {
      icp->stat = csViolated;
      pgPrintIntConst(stdout,icp);
      sprintf(buf," is violated (%g) vol: %g.\n",dsum,
	      icp->prod_list->node->voltage);
      print_mesg(buf);
    }
  else if(icp->type == EQ)
      icp->stat = csSatisfied;    
  else
    {
      /*
	pgPrintIntConst(stdout,icp);
	print_mesg(" is not supported.\n");
      */
      return 0;
    }
  return dsum;
}
Пример #6
0
/* ARGSUSED1 */
static void Key ( unsigned char key, int x, int y )
{
  char title[512];
  
    switch ( key ) {
      case 27 :
      case 'q' :
      case 'Q' :
	exit (0) ;

      case 'r' :
      case 'R' :
	printf ("Rereading expression file\n");
        read_expressions();
	e = 0; /* reset the expression count variable */
	glutPostRedisplay();
	break;

      case 'a' :
	printf ("increment muscle: %s\n", face->muscle[m]->name ) ;

	/* set the muscle activation */
	face->muscle[m]->mstat += 0.1 ;
	
	activate_muscle ( face, 
			 face->muscle[m]->head, 
			 face->muscle[m]->tail, 
			 face->muscle[m]->fs,
			 face->muscle[m]->fe,
			 face->muscle[m]->zone,
			 0.1 ) ;
	glutPostRedisplay();
	break;

      case 'A' :
	printf ("decrement muscle: %s\n", face->muscle[m]->name ) ;
	face->muscle[m]->mstat -= 0.1 ;

	activate_muscle ( face, 
			 face->muscle[m]->head, 
			 face->muscle[m]->tail, 
			 face->muscle[m]->fs,
			 face->muscle[m]->fe,
			 face->muscle[m]->zone,
			 -0.1 ) ;
	glutPostRedisplay();
	break;

      case 'b' :
	DRAW_MODE++ ;

	if ( DRAW_MODE >= 3 ) DRAW_MODE = 0 ;
	printf ("draw mode: %d\n", DRAW_MODE ) ;
	glutPostRedisplay();
	break;

      case 'c' :
	face_reset ( face ) ;
	glutPostRedisplay();
	break;
	
      case 'n' :
	m++ ;
	if ( m >= face->nmuscles ) m = 0 ;
        sprintf(title, "geoface (%s)", face->muscle[m]->name);
        glutSetWindowTitle(title);
	break;

      case 'e' :
	if (face->expression) {
	face_reset  ( face ) ;
	expressions ( face, e ) ;

	e++ ;
	if ( e >= face->nexpressions ) e = 0 ;
	glutPostRedisplay();
	}
	break;

      case 'h' :
	
	print_mesg();
	
    }
}
void
pgBuildCurLPConst(Circuit *ckt, ExtConst *ext_const, OptMode mode)
{
  long      index = 1;
  ExtConst  *etaux;
  IntConst  *itaux;
  Nodes     *naux;
  int       i,sign;
  Products  *paux;
  Branches  *daux, *bch1 = NULL, *bch2=NULL;
  BranchLink *blaux;
  double    coeff, cst;
  double    vdrop;

  assert(ext_const);
  assert(ckt->theNodeArray);
  assert(ckt->theDeviceList);

  if(ckt->LPIntConstList)
    {
      pgFreeIntConst(ckt->LPIntConstList);
      ckt->LPIntConstList = NULL;
    }

  /* 
   * constraints due to KCL law
   */
  for( i = 1; i <= ckt->nNumNode; i++)
    {

      /* ignore the dangling node */
      if(ckt->theNodeArray[i].stat != nNormal ||
	 ckt->theNodeArray[i].isVDD )
	continue;
      /*
	if(ckt->theNodeArray[i].stat != nNormal)
	continue;
      */

      /* each node has a constraint */
      itaux = pgNewIntConst(EQ,index++);
      pgAddIntConst(&(ckt->LPIntConstList),itaux);

      for(blaux = ckt->theNodeArray[i].blist; blaux; blaux = blaux->next)
	{

	  /* the sign is positive if the current direction
	     of the branch is toward node i.
	  */
	  if(blaux->dev->type == dCUR && blaux->dev->n1 == i)
	    {
	      cst = -1*blaux->dev->value;  
	      pgAddNumConst(itaux,cst);
	    }
	  else if(blaux->dev->type == dCUR && blaux->dev->n2 == i)
	    {
	      cst = blaux->dev->value;  
	      pgAddNumConst(itaux,cst);
	    }

	  /* the sign is positive if the current direction
	     of the branch is toward node i.
	  */    
	  else if(blaux->dev->type == dRES && blaux->dev->n1 == i)
	    {
	      paux = pgNewProductByBranch(-1, 1.0,blaux->dev);
	      pgAddProduct(itaux,paux);
	    }
	  else if(blaux->dev->type == dRES && blaux->dev->n2 == i)
	    {
	      paux = pgNewProductByBranch(1, 1.0,blaux->dev);
	      pgAddProduct(itaux,paux);
	    }
	  else
	    {
	      sprintf(buf, "Irrelevant branch: %s for node %d.", 
		      blaux->dev->name, i);
	      error_mesg(INT_ERROR,buf);
	      continue;
	    }
	}
    }

  /* 
   *    minimum width constraints
   *    1/(Vi2 - Vi1)*Ii - Wmin/(Resistivity*Li) >= 0
   */

  for(daux = ckt->theDeviceList; daux; daux = daux->next)
    {

      if(daux->stat != sNormal) 
	continue;

      if(daux->type != dRES) 
	continue;

      /* ignore branch with very small current */
      /*
	if(fabs(daux->current) <= MIN_CURRENT ||
	fabs(ckt->theNodeArray[daux->n1].voltage -
	ckt->theNodeArray[daux->n2].voltage) <= MIN_VOLTAGE )
	{
	sprintf(buf,"branch %s: current or voltage drop is close to 0, ignored.\n", 
	daux->name);
	print_mesg(buf);
	daux->stat = sAbnormal;
	continue;
	}
      */

      /* make sure current is not zero */
      if(daux->current != 0.0)
	{

	  itaux = pgNewIntConst( GE,index++ );
	  pgAddIntConst(&(ckt->LPIntConstList),itaux);
            
	  /* we creat a product terms and a constant */
	  /* the product */
	  assert(daux->n1 < (ckt->nMatrixSize+1));
	  assert(daux->n2 < (ckt->nMatrixSize+1));

	  vdrop = ckt->theNodeArray[daux->n1].voltage -
	          ckt->theNodeArray[daux->n2].voltage;
	  if(vdrop == 0)
	    {
	      printf("n%d (%g) -> n%d (%g)", 
		     daux->n1,  ckt->theNodeArray[daux->n1].voltage,
		     daux->n2,  ckt->theNodeArray[daux->n2].voltage);
	      
	      printf("current %g", daux->current);
	      assert(vdrop != 0.0);
	    }
	    
	  coeff = 1/(vdrop+FTINY);

	  paux = pgNewProductByBranch(1, coeff, daux);
	  pgAddProduct(itaux,paux);

	  /* the constant */
	  if(mode == optConjugate)
	    cst = 0 - (daux->lay->minWidth*EPSILON)/(daux->length*
						     daux->lay->unitRes);
	  else
	    cst = 0 - (daux->lay->minWidth)/(daux->length*
						     daux->lay->unitRes);

	  pgAddNumConst(itaux,cst);

	}
      else
	{
	  sprintf(buf,"%s(Linear): current=0, ignored.\n", daux->name);
	  print_mesg(buf);
	}
        
    }

  /*
   *  Equivalence-width constraint
   *  (li*Ii)/(Vi1-Vi2) - (lj*Ij)/(Vj1-Vj2) = 0
   */
  for( etaux = ext_const; etaux; etaux = etaux->next )
    {
      if( etaux->topic == cWIDTH )
	{

	  if(etaux->type != EQ )
	    {
	      sprintf(buf,"Invalid width constraint: v(%d).", etaux->node1);
	      error_mesg(PARSE_ERROR,buf);
	      continue;
	    }

	  itaux = pgNewIntConst(EQ, index++);
	  pgAddIntConst(&(ckt->LPIntConstList),itaux);

	  daux = pgFindBranchByName(ckt,etaux->bname1);
	  assert(daux);
	  vdrop = ckt->theNodeArray[daux->n1].voltage -
	          ckt->theNodeArray[daux->n2].voltage;
	  assert(vdrop != 0.0);

	  coeff = daux->length/(vdrop+FTINY);
	  paux = pgNewProductByBranch(1, coeff, daux);
	  pgAddProduct(itaux, paux);

	  daux = pgFindBranchByName(ckt, etaux->bname2);
	  assert(daux);
	  vdrop = ckt->theNodeArray[daux->n1].voltage -
	          ckt->theNodeArray[daux->n2].voltage;
	  assert(vdrop != 0.0);

	  coeff = daux->length/(vdrop + FTINY);
	  paux = pgNewProductByBranch(-1, coeff, daux);
	  pgAddProduct(itaux, paux);
	}
    }
}
void
pgBuildNLPConst(Circuit *ckt, ExtConst *ext_const)
{
  long      index = 1;
  ExtConst  *etaux;
  IntConst  *itaux;
  Nodes       *naux;
  int      sign;
  Products  *paux;
  Branches  *daux, *bch1 = NULL, *bch2=NULL;
  double      cst;

  assert(ext_const);
  assert(ckt->theNodeArray);
  assert(ckt->theDeviceList);

  if(ckt->NLPIntConstList){
    pgFreeIntConst(ckt->NLPIntConstList);
    ckt->NLPIntConstList = NULL;
  }

  /* 
  ** build all the constraints for minimum width
  ** and also reserve current direction 
  */
  for(daux = ckt->theDeviceList; daux; daux = daux->next)
    {

      if(daux->stat != sNormal) 
	continue;

      if(daux->type != dRES) 
	continue;

      /* ignore branch with very small current */
      /*
      if(fabs(daux->current) <= MIN_CURRENT ||
	 fabs(theNodeArray[daux->n1].voltage -
	      theNodeArray[daux->n2].voltage) <= MIN_VOLTAGE ){
	sprintf(buf,"branch %s: current or voltage drop is close to 0, ignored.\n", 
		daux->name);
	print_mesg(buf);
	daux->stat = sAbnormal;
	continue;
      }
      */

      assert(daux->n1 < (ckt->nMatrixSize+1));
      assert(daux->n2 < (ckt->nMatrixSize+1));

      /* first constraint */
      if(daux->current != 0.0 )
	{
	  itaux = pgNewIntConst(GE,index++);
	  pgAddIntConst(&(ckt->NLPIntConstList),itaux);

	  naux = &(ckt->theNodeArray[daux->n1]);
	  paux = pgNewProductByNode(-1, 1/(daux->current),naux);
	  pgAddProduct(itaux,paux);

	  naux = &(ckt->theNodeArray[daux->n2]);
	  paux = pgNewProductByNode(1, 1/(daux->current),naux);
	  pgAddProduct(itaux,paux);

	  cst = (daux->lay->unitRes*daux->length/
		 (daux->lay->minWidth));
	  pgAddNumConst(itaux,cst);

	  /* second constraint */
	  itaux = pgNewIntConst(GE,index++);
	  pgAddIntConst(&(ckt->NLPIntConstList),itaux);

	  /* second constraint */
	  naux = &(ckt->theNodeArray[daux->n1]);
	  paux = pgNewProductByNode(1,1/daux->current, naux);
	  pgAddProduct(itaux,paux);

	  naux = &(ckt->theNodeArray[daux->n2]);
	  paux = pgNewProductByNode(-1,1/daux->current, naux);
	  pgAddProduct(itaux,paux);

	}
      else{
	sprintf(buf,"%s(nonlinear): current=0, ignored.\n", daux->name);
	print_mesg(buf);
      }

    }
        
  /* the internal constrain related to the user defined
     external constraints.
  */
  for( etaux = ext_const; etaux; etaux = etaux->next )
    {
      if(etaux->topic == cVOL)
	{ /* voltage constraint */    

	  /* create a new internal constraints and
	     add it into the constraint list 
	  */ 

	  assert(etaux->node1 <= ckt->nMatrixSize);

	  /* ignore the abnormal case */
	  if(ckt->theNodeArray[etaux->node1].stat != nNormal)
	    continue;

	  naux = &(ckt->theNodeArray[etaux->node1]);

	  if(etaux->type == GT || etaux->type == GE )
	    {
	      itaux = pgNewIntConst(GE,index++);
	      sign = 1;
	    }
	  else if(etaux->type == LE  || etaux->type == LS)
	    {
	      itaux = pgNewIntConst(GE,index++);
	      sign = -1;
	    }
	  else{
	    sprintf(buf, "Invalid voltage constraint: v(%d).", etaux->node1);
	    error_mesg(PARSE_ERROR,buf);
	    continue;
	  }
	  paux = pgNewProductByNode(sign,1/(etaux->value+FTINY),
				    naux);
	  pgAddProduct(itaux,paux);
	  pgAddNumConst(itaux, (-1)*sign);
	  pgAddIntConst(&(ckt->NLPIntConstList),itaux);
	}

      if(etaux->topic == cWIDTH)
	{
	  /*
	   *  Equivalence-width constraint
	   *  (1/(li*Ii))(Vi1-Vi2) - (1/(lj*Ij))*(Vj1-Vj2) = 0
	   */
	  if(etaux->type == EQ) 
	    {
	      naux = &(ckt->theNodeArray[etaux->node1]);

	      /* we only deal with equival width constraint here */
	      if(etaux->type != EQ )
		{
		  sprintf(buf, "Invalid width constraint: v(%d).", etaux->node1);
		  error_mesg(PARSE_ERROR,buf);
		  continue;
		}

	      itaux = pgNewIntConst(EQ,index++);
	      pgAddIntConst(&(ckt->NLPIntConstList),itaux);

	      daux = pgFindBranchByName(ckt,etaux->bname1);
	      assert(daux);
	      cst = (daux->length*daux->current);
            
	      if(daux->n1)
		{
		  naux = &(ckt->theNodeArray[daux->n1]);
		  paux = pgNewProductByNode(1, 1/cst,naux);
		  pgAddProduct(itaux,paux);
		}

	      if(daux->n2)
		{
		  naux = &(ckt->theNodeArray[daux->n2]);
		  paux = pgNewProductByNode(-1, 1/cst,naux);
		  pgAddProduct(itaux,paux);
		}

	      daux = pgFindBranchByName(ckt,etaux->bname2);
	      assert(daux);
	      cst = (daux->length*daux->current);
            
	      if(daux->n1)
		{
		  naux = &(ckt->theNodeArray[daux->n1]);
		  paux = pgNewProductByNode(-1, 1/cst,naux);
		  pgAddProduct(itaux,paux);
		}

	      if(daux->n2)
		{
		  naux = &(ckt->theNodeArray[daux->n2]);
		  paux = pgNewProductByNode(1, 1/cst,naux);
		  pgAddProduct(itaux,paux);
		}
	    }
	}
    }   
}
void
pgBuildVolLPConst(Circuit *ckt, ExtConst *ext_const)
{
  long      i,index = 1;
  ExtConst  *etaux;
  IntConst  *itaux;
  Nodes     *naux;
  int       sign;
  Products  *paux;
  Branches  *daux, *bch1 = NULL, *bch2=NULL;
  double    cst;
  double    vdrop;
  char      pgiBname[128];

  assert(ext_const);
  assert(ckt->theNodeArray);
  assert(ckt->theDeviceList);

  if(ckt->NLPIntConstList)
    {
      pgFreeIntConst(ckt->NLPIntConstList);
      ckt->NLPIntConstList = NULL;
    }

  for(i=0; i<=ckt->nMatrixSize; i++)
    {
      ckt->theNodeArray[i].coeff = 0.0;
    }

  /*
   * We then begin to build the constraints
   */
  for(daux = ckt->theDeviceList; daux; daux = daux->next)
    {

      if(daux->stat != sNormal) 
	continue;

      if(daux->type != dRES  && daux->type != dVOL) 
	continue;

      /* ignore branch with very small current */
      /*
	if(fabs(daux->current) <= MIN_CURRENT ||
	fabs(ckt->theNodeArray[daux->n1].voltage -
	ckt->theNodeArray[daux->n2].voltage) <= MIN_VOLTAGE )
	{
	sprintf(buf,"branch %s: current or voltage drop is close to 0, ignored.\n", 
	daux->name);
	print_mesg(buf);
	daux->stat = sAbnormal;
	continue;
	}
      */
      /* 
       * For power network, the power pin should be 
       * restricted to the power supply voltage.
       */
      if(daux->type == dVOL)
	{
	  itaux = pgNewIntConst(EQ,index++);
	  pgAddIntConst(&(ckt->NLPIntConstList),itaux);

	  if(daux->n1)
	    naux = &(ckt->theNodeArray[daux->n1]);
	  else
	    naux = &(ckt->theNodeArray[daux->n2]);

	  paux = pgNewProductByNode(1, 1.0,naux);
	  pgAddProduct(itaux,paux);
	  pgAddNumConst(itaux,-daux->value);
	  continue;
	}

      /* ignore branch with very small current */
      assert(daux->n1 < (ckt->nMatrixSize+1));
      assert(daux->n2 < (ckt->nMatrixSize+1));

      daux->vdrop = ckt->theNodeArray[daux->n1].voltage -
	            ckt->theNodeArray[daux->n2].voltage;
      if(fabs(daux->current) <= MIN_CURRENT || fabs(daux->vdrop) <= MIN_VOLTAGE )
	{
	  sprintf(buf,"branch %s: current or voltage close to 0, ignored.\n", 
		  daux->name);
	  print_mesg(buf);
	  daux->stat = sAbnormal;
	  continue;
	}

      /* Compute the cost or objective function: calculate the
       * coefficient of each node voltage in the objective function.  */

      /* daux->vdrop = ckt->theNodeArray[daux->n1].voltage -
	 ckt->theNodeArray[daux->n2].voltage; */

      cst = -(daux->current*daux->length*daux->length*
	      daux->lay->unitRes)/(daux->vdrop*daux->vdrop +FTINY);
        
      ckt->theNodeArray[daux->n1].coeff += cst;
      ckt->theNodeArray[daux->n2].coeff += -cst;

      /* 
       * minimum width constraint:
       *  -(Vi1 - Vi2)/I1 + Resistivity*Ii/Wmin >= 0 
       */

      if(daux->current != 0.0 )
	{
	  itaux = pgNewIntConst(GE,index++);
	  pgAddIntConst(&(ckt->NLPIntConstList),itaux);

	  if(daux->n1)
	    {
	      naux = &(ckt->theNodeArray[daux->n1]);
	      paux = pgNewProductByNode(-1, 1/(daux->current),naux);
	      pgAddProduct(itaux,paux);
	    }

	  if(daux->n2)
	    {
	      naux = &(ckt->theNodeArray[daux->n2]);
	      paux = pgNewProductByNode(1, 1/(daux->current),naux);
	      pgAddProduct(itaux,paux);
	    }

	  cst = (daux->lay->unitRes*daux->length/
		 daux->lay->minWidth);
	  pgAddNumConst(itaux,cst);

	  /* 
	   * Linearizaton companion constraint: 
	   * (Vi1-Vi2)/(xi * (Vi1^0-Vi2^0)) -1 >= 0.
	   */

	  itaux = pgNewIntConst(GE,index++);
	  pgAddIntConst(&(ckt->NLPIntConstList),itaux);

	  if(daux->n1)
	    {
	      naux = &(ckt->theNodeArray[daux->n1]);
	      paux = pgNewProductByNode(1,1/((daux->vdrop+FTINY)*RestrFactor), naux);
	      pgAddProduct(itaux,paux);
	    }

	  if(daux->n2)
	    {
	      naux = &(ckt->theNodeArray[daux->n2]);
	      paux = pgNewProductByNode(-1,1/((daux->vdrop+FTINY)*RestrFactor), naux);
	      pgAddProduct(itaux,paux);
	    }
	  pgAddNumConst(itaux,-1.0);
	}
      else
	{
	  sprintf(buf,"%s(nonlinear): current=0, ignored.\n", daux->name);
	  print_mesg(buf);
	}

    }

  for( etaux = ext_const; etaux; etaux = etaux->next )
    {
      assert(etaux->node1 <= ckt->nMatrixSize);

      /*
       *    Voltage IR drop constraint: 
       *    Vi >= Vmin or Vi <= Vmax
       */
      if(etaux->topic == cVOL)
	{ 

	  /* skip ground node which has 0 index */
	  if(etaux->node1 == 0)
	    continue;

	  /* ignore the abnormal case */
	  if(ckt->theNodeArray[etaux->node1].stat != nNormal)
	    continue;

	  if(ckt->theNodeArray[etaux->node1].coeff == 0.0)
	    continue;

	  naux = &(ckt->theNodeArray[etaux->node1]);

	  if(etaux->type == GT || etaux->type == GE )
	    {
	      itaux = pgNewIntConst(GE,index++);
	      sign = 1;
	    }
	  else if(etaux->type == LE  || etaux->type == LS)
	    {
	      itaux = pgNewIntConst(GE,index++);
	      sign = -1;
	    }
	  else
	    {
	      sprintf(buf, "Invalid voltage constraint: v(%d).", etaux->node1);
	      error_mesg(PARSE_ERROR,buf);
	      continue;
	    }
	  paux = pgNewProductByNode(sign,1/(etaux->value+FTINY), naux);
	  pgAddProduct(itaux,paux);

	  pgAddNumConst(itaux, (-1)*sign);
	  pgAddIntConst(&(ckt->NLPIntConstList),itaux);
	}

      /*
       *  Equivalence-width constraint
       *  1/(li*Ii)(Vi1-Vi2) - 1/(lj*Ij)*(Vj1-Vj2) = 0
       */
      else if( etaux->topic == cWIDTH )
	{

	  naux = &(ckt->theNodeArray[etaux->node1]);

	  /* we only deal with equivalence width constraint here */
	  if(etaux->type != EQ )
	    {
	      sprintf(buf, "Invalid width constraint: v(%d).", etaux->node1);
	      error_mesg(PARSE_ERROR,buf);
	      continue;
	    }

	  itaux = pgNewIntConst(EQ,index++);
	  pgAddIntConst(&(ckt->NLPIntConstList),itaux);

	  daux = pgFindBranchByName(ckt, etaux->bname1);
	  assert(daux);
	  cst = (daux->length*daux->current);
            
	  if(daux->n1)
	    {
	      naux = &(ckt->theNodeArray[daux->n1]);
	      paux = pgNewProductByNode(1, 1/cst,naux);
	      pgAddProduct(itaux,paux);
	    }

	  if(daux->n2)
	    {
	      naux = &(ckt->theNodeArray[daux->n2]);
	      paux = pgNewProductByNode(-1, 1/cst,naux);
	      pgAddProduct(itaux,paux);
	    }

	  daux = pgFindBranchByName(ckt,etaux->bname2);
	  assert(daux);
	  cst = (daux->length*daux->current);
            
	  if(daux->n1)
	    {
	      naux = &(ckt->theNodeArray[daux->n1]);
	      paux = pgNewProductByNode(-1, 1/cst,naux);
	      pgAddProduct(itaux,paux);
	    }

	  if(daux->n2)
	    {
	      naux = &(ckt->theNodeArray[daux->n2]);
	      paux = pgNewProductByNode(1, 1/cst,naux);
	      pgAddProduct(itaux,paux);
	    }
	}
    }
  /* node 0 is bounded to zero */
  /*
    itaux = pgNewIntConst(LE,index++);
    pgAddIntConst(&(ckt->NLPIntConstList),itaux);
    paux = pgNewProductByNode(1, 1, &(ckt->theNodeArray[0]));
    pgAddProduct(itaux,paux);
    pgAddNumConst(itaux, 0);
  */
    
}