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

📄 mulmulti.c

📁 很经典的电磁计算(电容计算)软件 MIT90年代开发
💻 C
📖 第 1 页 / 共 2 页
字号:
      else {	cosA = vector[CINDEX(1,0)]/vector[CINDEX(1,1)]; /* cosA= -cot(theta) */	sinMA *= vector[CINDEX(1,1)]; /*(-sin(alpha))^(m-1)->(-sin(alpha))^m*/	vector[CINDEX(m, m)] = fact * sinMA;	if(m != order) {		/* do if not on last row */	  vector[CINDEX(m+1, m)] = vector[CINDEX(1, 0)]*(2*m+1)	      *vector[CINDEX(m, m)];	}      }    }    for(x = 2; x < order-m+1; x++) { /* generate row of evals recursively */      vector[CINDEX(x+m, m)] = 	  ((2*(x+m)-1)*vector[CINDEX(1, 0)]*vector[CINDEX(x+m-1, m)]	   - (x + 2*m - 1)*vector[CINDEX(x+m-2, m)])/x;    }  }}      /*   Returns a matrix which gives a cube's multipole expansion when *'d by chg vec  OPTIMIZATIONS USING is_dummy HAVE NOT BEEN COMPLETELY IMPLEMENTED*/double **mulQ2Multi(chgs, is_dummy, numchgs, x, y, z, order)double x, y, z; charge **chgs;int numchgs, order, *is_dummy;{  double **mat;  double cosA;			/* cosine of elevation coordinate */  int i, j, k, kold, n, m, start;  int cterms = costerms(order), terms = multerms(order);  /* Allocate the matrix. */  CALLOC(mat, terms, double*, ON, AQ2M);  for(i=0; i < terms; i++)       CALLOC(mat[i], numchgs, double, ON, AQ2M);  /* get Legendre function evaluations, one set for each charge */  /*  also get charge coordinates, set up for subsequent evals */  for(j = 0; j < numchgs; j++) { /* for each charge */    /* get cosA for eval; save rho, beta in rho^n and cos/sin(m*beta) arrays */    xyz2sphere(chgs[j]->x, chgs[j]->y, chgs[j]->z,	       x, y, z, &(Rho[j]), &cosA, &(Beta[j]));    Rhon[j] = Rho[j]; /* init powers of rho_i's */    Betam[j] = Beta[j];		/* init multiples of beta */    evalLegendre(cosA, tleg, order);	/* write moments to temporary array */    /* write a column of the matrix with each set of legendre evaluations */    for(i = 0; i < cterms; i++) mat[i][j] = tleg[i]; /* copy for cos terms */  }#if DALQ2M == ON  fprintf(stdout,	  "\nQ2M MATRIX BUILD:\n    AFTER LEGENDRE FUNCTION EVALUATON\n");  dumpMat(mat, terms, numchgs);#endif  /* some of this can be avoided using is_dummy to skip unused columns */  /* add the rho^n factors to the cos matrix entries. */  for(i = 1, k = kold = 2; i < cterms; i++) { /* loop on rows of matrix */    for(j = 0; j < numchgs; j++) mat[i][j] *= Rhon[j]; /* mul in factor */    k -= 1;    if(k == 0) {		/* so that effective n varys appropriately */      kold = k = kold + 1;      for(j = 0; j < numchgs; j++) Rhon[j] *= Rho[j];	/* r^n-1 -> r^n */    }  }#if DALQ2M == ON  fprintf(stdout,"    AFTER ADDITION OF RHO^N FACTORS\n");  dumpMat(mat, terms, numchgs);#endif  /* copy result to lower (sine) part of matrix */  for(n = 1; n <= order; n++) { /* loop on rows of matrix */    for(m = 1; m <= n; m++) {      for(j = 0; j < numchgs; j++) { /* copy a row */	mat[SINDEX(n, m, cterms)][j] = mat[CINDEX(n, m)][j];      }    }  }#if DALQ2M == ON  fprintf(stdout,"    AFTER COPYING SINE (LOWER) HALF\n");  dumpMat(mat, terms, numchgs);#endif  /* add factors of cos(m*beta) and sin(m*beta) to matrix entries */  for(m = 1; m <= order; m++) {	/* lp on m in Mn^m (no m=0 since cos(0)=1) */    for(n = m; n <= order; n++) { /* loop over rows with same m */      for(j = 0; j < numchgs; j++) { /* add factors to a row */	mat[CINDEX(n, m)][j] *= (2.0*cos(Betam[j]));   /* note factors of 2 */	mat[SINDEX(n, m, cterms)][j] *= (2.0*sin(Betam[j]));      }    }    for(j = 0; j < numchgs; j++) Betam[j] += Beta[j]; /* (m-1)*beta->m*beta */  }  /* THIS IS NOT VERY GOOD: zero out columns corresponding to dummy panels */  for(j = 0; j < numchgs; j++) {    if(is_dummy[j]) {      for(i = 0; i < terms; i++) {	mat[i][j] = 0.0;      }    }  }#if DISQ2M == ON  dispQ2M(mat, chgs, numchgs, x, y, z, order);#endif  return(mat);}double **mulMulti2Multi(x, y, z, xp, yp, zp, order)double x, y, z, xp, yp, zp;	/* cube center, parent cube center */int order;{  double **mat, rho, rhoPwr, cosA, beta, mBeta, temp1, temp2;   double iPwr(), fact();  int r, j, k, m, n, c;  int cterms = costerms(order), sterms = sinterms(order);  int terms = cterms + sterms;  /* Allocate the matrix (terms x terms ) */  CALLOC(mat, terms, double*, ON, AM2M);  for(r=0; r < terms; r++) CALLOC(mat[r], terms, double, ON, AM2M);  for(r = 0; r < terms; r++)      for(c = 0; c < terms; c++) mat[r][c] = 0.0;  /* get relative distance in spherical coordinates */  xyz2sphere(x, y, z, xp, yp, zp, &rho, &cosA, &beta);  /* get the requisite Legendre function evaluations */  evalLegendre(cosA, tleg, order);  /* for each new moment (Nj^k) stuff the appropriate matrix entries */  /* done completely brute force, one term at a time; uses exp in nb 12, p29 */  for(j = 0; j <= order; j++) {    for(k = 0; k <= j; k++) {      for(n = 0, rhoPwr = 1.0; n <= j; n++, rhoPwr *= rho) {	for(m = 0, mBeta = 0.0; m <= n; m++, mBeta += beta) {	  if(k == 0) {		/* figure terms for Nj^0, ie k = 0 */	    if(m <= j-n) {	/* if O moments are nonzero */	      temp1 = fact(j)*rhoPwr*iPwr(2*m)*tleg[CINDEX(n, m)];	      temp1 /= (fact(j-n+m)*fact(n+m));	      mat[CINDEX(j, k)][CINDEX(j-n, m)] += temp1*cos(mBeta);	      if(m != 0) {		/* if sin term is non-zero */		mat[CINDEX(j, k)][SINDEX(j-n, m, cterms)] += temp1*sin(mBeta);	      }	    }	  }	  else {		/* figure terms for Nj^k, k != 0 */	    temp1 = fact(j+k)*rhoPwr*tleg[CINDEX(n, m)]/fact(n+m);	    temp2 = temp1*iPwr(2*m)/fact(j-n+k+m);	    temp1 = temp1*iPwr(k-m-abs(k-m))/fact(j-n+abs(k-m));	    /* write the cos(kPhi) coeff, bar(N)j^k */	    if(m != 0) {	      if(k-m < 0 && abs(k-m) <= j-n) {	/* use conjugates here */		mat[CINDEX(j, k)][CINDEX(j-n, m-k)] += temp1*cos(mBeta);		mat[CINDEX(j, k)][SINDEX(j-n, m-k,cterms)] += temp1*sin(mBeta);	      }	      else if(k-m == 0) {	/* double to compensate for 2Re sub. */		mat[CINDEX(j, k)][CINDEX(j-n, k-m)] += 2*temp1*cos(mBeta);		/* sin term is always zero */	      }	      else if(k-m > 0 && k-m <= j-n) {		mat[CINDEX(j, k)][CINDEX(j-n, k-m)] += temp1*cos(mBeta);		mat[CINDEX(j, k)][SINDEX(j-n, k-m,cterms)] -= temp1*sin(mBeta);	      }	      if(k+m <= j-n) {		mat[CINDEX(j, k)][CINDEX(j-n, k+m)] += temp2*cos(mBeta);		mat[CINDEX(j, k)][SINDEX(j-n, k+m,cterms)] += temp2*sin(mBeta);	      }	    }			/* do if m = 0 and O moments not zero */	    else if(k <= j-n) mat[CINDEX(j, k)][CINDEX(j-n, k)] += temp2;	    /* write the sin(kPhi) coeff, dblbar(N)j^k, if it is non-zero */	    if(m != 0) {	      if(k-m < 0 && abs(k-m) <= j-n) {	/* use conjugates here */		mat[SINDEX(j, k,cterms)][CINDEX(j-n, m-k)] += temp1*sin(mBeta);		mat[SINDEX(j, k, cterms)][SINDEX(j-n, m-k, cterms)] 		    -= temp1*cos(mBeta);	      }	      else if(k-m == 0) {/* double to compensate for 2Re sub */		mat[SINDEX(j, k, cterms)][CINDEX(j-n, k-m)] 		    += 2*temp1*sin(mBeta);		/* sine term is always zero */	      }	      else if(k-m > 0 && k-m <= j-n) {		mat[SINDEX(j, k,cterms)][CINDEX(j-n, k-m)] += temp1*sin(mBeta);		mat[SINDEX(j, k, cterms)][SINDEX(j-n, k-m, cterms)] 		    += temp1*cos(mBeta);	      }	      if(k+m <= j-n) {		mat[SINDEX(j, k,cterms)][CINDEX(j-n, k+m)] -= temp2*sin(mBeta);		mat[SINDEX(j, k, cterms)][SINDEX(j-n, k+m, cterms)] 		    += temp2*cos(mBeta);	      }	    }			/* do if m = 0 and moments not zero */	    else if(k <= j-n) mat[SINDEX(j, k,cterms)][SINDEX(j-n, k, cterms)] 		+= temp2;	  }	}      }    }  }#if DISM2M == ON  dispM2M(mat, x, y, z, xp, yp, zp, order);#endif  return(mat);}/*   builds multipole evaluation matrix; used only for fake downward pass */double **mulMulti2P(x, y, z, chgs, numchgs, order)double x, y, z;			/* multipole expansion origin */charge **chgs;int numchgs, order;{  double **mat;  double cosTh;			/* cosine of elevation coordinate */  double factorial;		/* 1/factorial = (n-m)!/(n+m)! */  int i, j, k, m, n, kold, start;  int cterms = costerms(order), sterms = sinterms(order);  int terms = cterms + sterms;  CALLOC(mat, numchgs, double*, ON, AM2P);  for(i=0; i < numchgs; i++)       CALLOC(mat[i], terms, double, ON, AM2P);  /* get Legendre function evaluations, one set for each charge */  /*   also get charge coordinates to set up rest of matrix */  for(i = 0; i < numchgs; i++) { /* for each charge, do a legendre eval set */    xyz2sphere(chgs[i]->x, chgs[i]->y, chgs[i]->z,	       x, y, z, &(Ir[i]), &cosTh, &(phi[i]));    Irn[i] = Ir[i]; /* initialize (1/r)^n+1 vec. */    Mphi[i] = phi[i];		/* initialize m*phi vector */    evalLegendre(cosTh, mat[i], order);	/* wr moms to 1st (cos) half of row */  }#if DALM2P == ON  fprintf(stdout,	  "\nM2P MATRIX BUILD:\n    AFTER LEGENDRE FUNCTION EVALUATON\n");  dumpMat(mat, numchgs, terms);#endif  /* add the (1/r)^n+1 factors to the left (cos(m*phi)) half of the matrix */  for(j = 0, k = kold = 1; j < cterms; j++) { /* loop on columns of matrix */    for(i = 0; i < numchgs; i++) mat[i][j] /= Irn[i]; /* divide by r^n+1 */    k -= 1;    if(k == 0) {		/* so that n changes as appropriate */      kold = k = kold + 1;      for(i = 0; i < numchgs; i++) Irn[i] *= Ir[i]; /* r^n -> r^n+1 */    }  }#if DALM2P == ON  fprintf(stdout,	  "    AFTER ADDITION OF (1/R)^N+1 FACTORS\n");  dumpMat(mat, numchgs, terms);#endif  /* add the factorial fraction factors to the left (cos(m*phi)) part of mat */  /*  note that (n-m)!/(n+m)! = 1/(n-m+1)...(n+m) since m \leq n */  for(n = 1; n <= order; n++) {    for(m = 1; m <= n; m++) {      for(i = 0; i < numchgs; i++) mat[i][CINDEX(n, m)] /= factFac[n][m];    }  }#if DALM2P == ON  fprintf(stdout,	  "    AFTER ADDITION OF FACTORIAL FRACTION FACTORS\n");  dumpMat(mat, numchgs, terms);#endif  /* copy left half of matrix to right half for sin(m*phi) terms */  for(i = 0; i < numchgs; i++) { /* loop on rows of matrix */    for(n = 1; n <= order; n++) {       for(m = 1; m <= n; m++) {	/* copy a row */	mat[i][SINDEX(n, m, cterms)] = mat[i][CINDEX(n, m)];      }    }  }#if DALM2P == ON  fprintf(stdout,	  "    AFTER COPYING SINE (RIGHT) HALF\n");  dumpMat(mat, numchgs, terms);#endif  /* add factors of cos(m*phi) and sin(m*phi) to left and right halves resp. */  for(m = 1; m <= order; m++) {	/* lp on m in Mn^m (no m=0 since cos(0)=1) */    for(n = m; n <= order; n++) { /* loop over cols with same m */      for(i = 0; i < numchgs; i++) { /* add factors to a column */	mat[i][CINDEX(n, m)] *= cos(Mphi[i]);	mat[i][SINDEX(n, m, cterms)] *= sin(Mphi[i]);      }    }    for(i = 0; i < numchgs; i++) Mphi[i] += phi[i]; /* (m-1)*phi->m*phi */  }#if DISM2P == ON  dispM2P(mat, x, y, z, chgs, numchgs, order);#endif  return(mat);}

⌨️ 快捷键说明

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