예제 #1
0
/* "calc_blessian_mem" calculates the block Hessian. */
int calc_blessian_mem(PDB_File *PDB,dSparse_Matrix *PP1,int nres,int nblx,
		      int elm,double **HB,double cut,double gam,double scl,
		      double mlo,double mhi)
{
  dSparse_Matrix *PP2;
  double **HR,***HT;
  int **CT,*BST1,*BST2;
  int ii,i,j,k,p,q,q1,q2,ti,tj,bi,bj,sb,nc,out;


  /* ------------------- INITIALIZE LOCAL VARIABLES ------------------- */

  /* HR holde three rows (corresponding to 1 residue) of the full Hessian */
  HR=zero_dmatrix(1,3*nres,1,3);

  /* CT is an array of contacts between blocks */
  CT=unit_imatrix(0,nblx);

  /* Copy PP1 to PP2 and sort by second element */
  PP2=(dSparse_Matrix *)malloc((size_t)sizeof(dSparse_Matrix));
  PP2->IDX=imatrix(1,elm,1,2);
  PP2->X=dvector(1,elm);
  copy_dsparse(PP1,PP2,1,elm);
  dsort_PP2(PP2,elm,2);

  /* BST1: for all j: BST1[i]<=j<BST[i+1], PP1->IDX[j][1]=i */
  /* BST2: for all j: BST2[i]<=j<BST2[i+1], PP2->IDX[j][2]=i */
  BST1=ivector(1,3*nres+1);
  BST2=ivector(1,6*nblx+1);
  init_bst(BST1,PP1,elm,3*nres+1,1);
  init_bst(BST2,PP2,elm,6*nblx+1,2);
  /* ------------------- LOCAL VARIABLES INITIALIZED ------------------ */



  /* ------------- FIND WHICH BLOCKS ARE IN CONTACT --------------- */
  nc=find_contacts1(CT,PDB,nres,nblx,cut);


  /* Allocate a tensor for the block Hessian */
  HT=zero_d3tensor(1,nc,1,6,1,6);


  /* Calculate each super-row of the full Hessian */
  for(ii=1;ii<=nres;ii++){

    if(PDB->atom[ii].model!=0){

      /* ----------------- FIND SUPER-ROW OF FULL HESSIAN --------------- */
      hess_superrow_mem(HR,CT,PDB,nres,ii,cut,gam,scl,mlo,mhi);


      /* Update elements of block hessian */
      q1=BST1[3*(ii-1)+2];
      q2=BST1[3*(ii-1)+3];
      /* Sum over elements of projection matrix corresponding to residue ii:
	 for each k in the following loop, PP1->IDX[k][1]==3*ii + 0,1,2 */
      for(k=BST1[3*ii-2];k<BST1[3*ii+1];k++){
	if(k<q1) q=1;
	else if(k<q2) q=2;
	else q=3;
	i=PP1->IDX[k][2];
	bi=(i-1)/6+1;
	ti=i-6*(bi-1);
	/* Sum over all elements of projection matrix with column j>=i */
	for(p=BST2[i];p<=elm;p++){
	  j=PP2->IDX[p][2];
	  bj=(j-1)/6+1;
	  sb=CT[bi][bj];
	  if(i<=j && sb!=0){  /* the first condition should ALWAYS hold */
	    tj=j-6*(bj-1);
	    HT[sb][ti][tj]+=(PP1->X[k]*PP2->X[p]*HR[PP2->IDX[p][1]][q]);
	  }
	}
      }
    }
  }


  /* Print the block Hessian in sparse format */
  out=bless_from_tensor(HB,HT,CT,nblx);

  /* Free up memory */
  free_dmatrix(HR,1,3*nres,1,3);
  free_d3tensor(HT,1,nc,1,6,1,6);
  free_imatrix(CT,0,nblx,0,nblx);
  free_ivector(BST1,1,3*nres+1);
  free_ivector(BST2,1,6*nblx+1);
  free_imatrix(PP2->IDX,1,elm,1,2);
  free_dvector(PP2->X,1,elm);
  return out;
}
/* creates matrices  B and invB: BT = Power in the steady state.
 * NOTE: EXTRA nodes: 4 heat spreader peripheral nodes, 4 heat
 * sink inner peripheral nodes, 4 heat sink outer peripheral
 * nodes(north, south, east and west) and 1 ambient node.
 */
void populate_R_model_block(block_model_t *model, flp_t *flp)
{
	/*	shortcuts	*/
	double **b = model->b;
	double *gx = model->gx, *gy = model->gy;
	double *gx_int = model->gx_int, *gy_int = model->gy_int;
	double *gx_sp = model->gx_sp, *gy_sp = model->gy_sp;
	double *gx_hs = model->gx_hs, *gy_hs = model->gy_hs;
	double *g_amb = model->g_amb;
	double **len = model->len, **g = model->g, **lu = model->lu;
	int **border = model->border;
	int *p = model->p;
	double t_chip = model->config.t_chip;
	double r_convec = model->config.r_convec;
	double s_sink = model->config.s_sink;
	double t_sink = model->config.t_sink;
	double s_spreader = model->config.s_spreader;
	double t_spreader = model->config.t_spreader;
	double t_interface = model->config.t_interface;
	double k_chip = model->config.k_chip;
	double k_sink = model->config.k_sink;
	double k_spreader = model->config.k_spreader;
	double k_interface = model->config.k_interface;

	int i, j, n = flp->n_units;
	double gn_sp=0, gs_sp=0, ge_sp=0, gw_sp=0;
	double gn_hs=0, gs_hs=0, ge_hs=0, gw_hs=0;
	double r_amb;

	double w_chip = get_total_width (flp);	/* x-axis	*/
	double l_chip = get_total_height (flp);	/* y-axis	*/

	/* sanity check on floorplan sizes	*/
	if (w_chip > s_sink || l_chip > s_sink ||
		w_chip > s_spreader || l_chip > s_spreader) {
		//print_flp(flp);
		//print_flp_fig(flp);
		//fatal("inordinate floorplan size!\n");
	}
	if(model->flp != flp || model->n_units != flp->n_units ||
	   model->n_nodes != NL * flp->n_units + EXTRA)
	   fatal("mismatch between the floorplan and the thermal model\n");

	/* gx's and gy's of blocks	*/
	for (i = 0; i < n; i++) {
		/* at the silicon layer	*/
		if (model->config.block_omit_lateral) {
			gx[i] = gy[i] = 0;
		}
		else {
			gx[i] = 1.0/getr(k_chip, flp->units[i].width / 2.0, flp->units[i].height * t_chip);
			gy[i] = 1.0/getr(k_chip, flp->units[i].height / 2.0, flp->units[i].width * t_chip);
		}

		/* at the interface layer	*/
		gx_int[i] = 1.0/getr(k_interface, flp->units[i].width / 2.0, flp->units[i].height * t_interface);
		gy_int[i] = 1.0/getr(k_interface, flp->units[i].height / 2.0, flp->units[i].width * t_interface);

		/* at the spreader layer	*/
		gx_sp[i] = 1.0/getr(k_spreader, flp->units[i].width / 2.0, flp->units[i].height * t_spreader);
		gy_sp[i] = 1.0/getr(k_spreader, flp->units[i].height / 2.0, flp->units[i].width * t_spreader);

		/* at the heatsink layer	*/
		gx_hs[i] = 1.0/getr(k_sink, flp->units[i].width / 2.0, flp->units[i].height * t_sink);
		gy_hs[i] = 1.0/getr(k_sink, flp->units[i].height / 2.0, flp->units[i].width * t_sink);
	}

	/* shared lengths between blocks	*/
	for (i = 0; i < n; i++)
		for (j = i; j < n; j++)
			len[i][j] = len[j][i] = get_shared_len(flp, i, j);

	/* package R's	*/
	populate_package_R(&model->pack, &model->config, w_chip, l_chip);

	/* short the R's from block centers to a particular chip edge	*/
	for (i = 0; i < n; i++) {
		if (eq(flp->units[i].bottomy + flp->units[i].height, l_chip)) {
			gn_sp += gy_sp[i];
			gn_hs += gy_hs[i];
			border[i][2] = 1;	/* block is on northern border 	*/
		} else
			border[i][2] = 0;

		if (eq(flp->units[i].bottomy, 0)) {
			gs_sp += gy_sp[i];
			gs_hs += gy_hs[i];
			border[i][3] = 1;	/* block is on southern border	*/
		} else
			border[i][3] = 0;

		if (eq(flp->units[i].leftx + flp->units[i].width, w_chip)) {
			ge_sp += gx_sp[i];
			ge_hs += gx_hs[i];
			border[i][1] = 1;	/* block is on eastern border	*/
		} else
			border[i][1] = 0;

		if (eq(flp->units[i].leftx, 0)) {
			gw_sp += gx_sp[i];
			gw_hs += gx_hs[i];
			border[i][0] = 1;	/* block is on western border	*/
		} else
			border[i][0] = 0;
	}

	/* initialize g	*/
	zero_dmatrix(g, NL*n+EXTRA, NL*n+EXTRA);
	zero_dvector(g_amb, n+EXTRA);

	/* overall Rs between nodes */
	for (i = 0; i < n; i++) {
		double area = (flp->units[i].height * flp->units[i].width);
		/* amongst functional units	in the various layers	*/
		for (j = 0; j < n; j++) {
			double part = 0, part_int = 0, part_sp = 0, part_hs = 0;
			if (is_horiz_adj(flp, i, j)) {
				part = gx[i] / flp->units[i].height;
				part_int = gx_int[i] / flp->units[i].height;
				part_sp = gx_sp[i] / flp->units[i].height;
				part_hs = gx_hs[i] / flp->units[i].height;
			}
			else if (is_vert_adj(flp, i,j))  {
				part = gy[i] / flp->units[i].width;
				part_int = gy_int[i] / flp->units[i].width;
				part_sp = gy_sp[i] / flp->units[i].width;
				part_hs = gy_hs[i] / flp->units[i].width;
			}
			g[i][j] = part * len[i][j];
			g[IFACE*n+i][IFACE*n+j] = part_int * len[i][j];
			g[HSP*n+i][HSP*n+j] = part_sp * len[i][j];
			g[HSINK*n+i][HSINK*n+j] = part_hs * len[i][j];
		}
		/* the 2.0 factor in the following equations is
		 * explained during the calculation of the B matrix
		 */
 		/* vertical g's in the silicon layer	*/
		g[i][IFACE*n+i]=g[IFACE*n+i][i]=2.0/getr(k_chip, t_chip, area);
 		/* vertical g's in the interface layer	*/
		g[IFACE*n+i][HSP*n+i]=g[HSP*n+i][IFACE*n+i]=2.0/getr(k_interface, t_interface, area);
		/* vertical g's in the spreader layer	*/
		g[HSP*n+i][HSINK*n+i]=g[HSINK*n+i][HSP*n+i]=2.0/getr(k_spreader, t_spreader, area);
		/* vertical g's in the heatsink core layer	*/
		/* vertical R to ambient: divide r_convec proportional to area	*/
		r_amb = r_convec * (s_sink * s_sink) / area;
		g_amb[i] = 1.0 / (getr(k_sink, t_sink, area) + r_amb);

		/* lateral g's from block center (spreader layer) to peripheral (n,s,e,w) spreader nodes	*/
		g[HSP*n+i][NL*n+SP_N]=g[NL*n+SP_N][HSP*n+i]=2.0*border[i][2] /
							  ((1.0/gy_sp[i])+model->pack.r_sp1_y*gn_sp/gy_sp[i]);
		g[HSP*n+i][NL*n+SP_S]=g[NL*n+SP_S][HSP*n+i]=2.0*border[i][3] /
							  ((1.0/gy_sp[i])+model->pack.r_sp1_y*gs_sp/gy_sp[i]);
		g[HSP*n+i][NL*n+SP_E]=g[NL*n+SP_E][HSP*n+i]=2.0*border[i][1] /
							  ((1.0/gx_sp[i])+model->pack.r_sp1_x*ge_sp/gx_sp[i]);
		g[HSP*n+i][NL*n+SP_W]=g[NL*n+SP_W][HSP*n+i]=2.0*border[i][0] /
							  ((1.0/gx_sp[i])+model->pack.r_sp1_x*gw_sp/gx_sp[i]);

		/* lateral g's from block center (heatsink layer) to peripheral (n,s,e,w) heatsink nodes	*/
		g[HSINK*n+i][NL*n+SINK_C_N]=g[NL*n+SINK_C_N][HSINK*n+i]=2.0*border[i][2] /
									((1.0/gy_hs[i])+model->pack.r_hs1_y*gn_hs/gy_hs[i]);
		g[HSINK*n+i][NL*n+SINK_C_S]=g[NL*n+SINK_C_S][HSINK*n+i]=2.0*border[i][3] /
									((1.0/gy_hs[i])+model->pack.r_hs1_y*gs_hs/gy_hs[i]);
		g[HSINK*n+i][NL*n+SINK_C_E]=g[NL*n+SINK_C_E][HSINK*n+i]=2.0*border[i][1] /
									((1.0/gx_hs[i])+model->pack.r_hs1_x*ge_hs/gx_hs[i]);
		g[HSINK*n+i][NL*n+SINK_C_W]=g[NL*n+SINK_C_W][HSINK*n+i]=2.0*border[i][0] /
									((1.0/gx_hs[i])+model->pack.r_hs1_x*gw_hs/gx_hs[i]);
	}

	/* g's from peripheral(n,s,e,w) nodes	*/
	/* vertical g's between peripheral spreader nodes and center peripheral heatsink nodes */
	g[NL*n+SP_N][NL*n+SINK_C_N]=g[NL*n+SINK_C_N][NL*n+SP_N]=2.0/model->pack.r_sp_per_y;
	g[NL*n+SP_S][NL*n+SINK_C_S]=g[NL*n+SINK_C_S][NL*n+SP_S]=2.0/model->pack.r_sp_per_y;
	g[NL*n+SP_E][NL*n+SINK_C_E]=g[NL*n+SINK_C_E][NL*n+SP_E]=2.0/model->pack.r_sp_per_x;
	g[NL*n+SP_W][NL*n+SINK_C_W]=g[NL*n+SINK_C_W][NL*n+SP_W]=2.0/model->pack.r_sp_per_x;
	/* lateral g's between peripheral outer sink nodes and center peripheral sink nodes	*/
	g[NL*n+SINK_C_N][NL*n+SINK_N]=g[NL*n+SINK_N][NL*n+SINK_C_N]=2.0/(model->pack.r_hs + model->pack.r_hs2_y);
	g[NL*n+SINK_C_S][NL*n+SINK_S]=g[NL*n+SINK_S][NL*n+SINK_C_S]=2.0/(model->pack.r_hs + model->pack.r_hs2_y);
	g[NL*n+SINK_C_E][NL*n+SINK_E]=g[NL*n+SINK_E][NL*n+SINK_C_E]=2.0/(model->pack.r_hs + model->pack.r_hs2_x);
	g[NL*n+SINK_C_W][NL*n+SINK_W]=g[NL*n+SINK_W][NL*n+SINK_C_W]=2.0/(model->pack.r_hs + model->pack.r_hs2_x);
	/* vertical g's between inner peripheral sink nodes and ambient	*/
	g_amb[n+SINK_C_N] = g_amb[n+SINK_C_S] = 1.0 / (model->pack.r_hs_c_per_y+model->pack.r_amb_c_per_y);
	g_amb[n+SINK_C_E] = g_amb[n+SINK_C_W] = 1.0 / (model->pack.r_hs_c_per_x+model->pack.r_amb_c_per_x);
	/* vertical g's between outer peripheral sink nodes and ambient	*/
	g_amb[n+SINK_N] = g_amb[n+SINK_S] = g_amb[n+SINK_E] =
					  g_amb[n+SINK_W] = 1.0 / (model->pack.r_hs_per+model->pack.r_amb_per);

	/* calculate matrix B such that BT = POWER in steady state */
	/* non-diagonal elements	*/
	for (i = 0; i < NL*n+EXTRA; i++)
		for (j = 0; j < i; j++)
			if ((g[i][j] == 0.0) || (g[j][i] == 0.0))
				b[i][j] = b[j][i] = 0.0;
			else
				/* here is why the 2.0 factor comes when calculating g[][]	*/
				b[i][j] = b[j][i] = -1.0/((1.0/g[i][j])+(1.0/g[j][i]));
	/* diagonal elements	*/
	for (i = 0; i < NL*n+EXTRA; i++) {
		/* functional blocks in the heat sink layer	*/
		if (i >= HSINK*n && i < NL*n)
			b[i][i] = g_amb[i%n];
		/* heat sink peripheral nodes	*/
		else if (i >= NL*n+SINK_C_W)
			b[i][i] = g_amb[n+i-NL*n];
		/* all other nodes that are not connected to the ambient	*/
		else
			b[i][i] = 0.0;
		/* sum up the conductances	*/
		for(j=0; j < NL*n+EXTRA; j++)
			if (i != j)
				b[i][i] -= b[i][j];
	}

	/* compute the LUP decomposition of B and store it too	*/
	copy_dmatrix(lu, b, NL*n+EXTRA, NL*n+EXTRA);
	/*
	 * B is a symmetric positive definite matrix. It is
	 * symmetric because if a node A is connected to B,
	 * then B is also connected to A with the same R value.
	 * It is positive definite because of the following
	 * informal argument from Professor Lieven Vandenberghe's
	 * lecture slides for the spring 2004-2005 EE 103 class
	 * at UCLA: http://www.ee.ucla.edu/~vandenbe/103/chol.pdf
	 * x^T*B*x = voltage^T * (B*x) = voltage^T * current
	 * = total power dissipated in the resistors > 0
	 * for x != 0.
	 */
	lupdcmp(lu, NL*n+EXTRA, p, 1);

	/* done	*/
	model->flp = flp;
	model->r_ready = TRUE;
}