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

📄 calcp.c

📁 很经典的电磁计算(电容计算)软件 MIT90年代开发
💻 C
📖 第 1 页 / 共 2 页
字号:
  result_vector[XI] = vector1[YI]*vector2[ZI] - vector1[ZI]*vector2[YI];  result_vector[YI] = vector1[ZI]*vector2[XI] - vector1[XI]*vector2[ZI];  result_vector[ZI] = vector1[XI]*vector2[YI] - vector1[YI]*vector2[XI];}/*Computes the potential at x, y, z due to a unit source on paneland due to a dipole is returned in pfd.Note, the code is subtle because there are 5 cases depending onthe placement of the collocation point    CASE1: evaluation point projection strictly outside of panel (happens most      of the time).    CASE2: eval pnt proj. strictly inside panel (happens >= #panels times,      at least for the self terms)    CASE3: eval pnt proj. on a panel side, not on a corner (happens      when paneled faces meet at right angles, also possible other ways)    CASE4: eval pnt proj. on a panel corner (happens rarely to never)    CASE5: eval pnt proj. on side extension (happens when paneled       faces meet at right angles, also possible other ways).*/double calcp(panel, x, y, z, pfd)charge *panel;double x, y, z, *pfd;{  double r[4], fe[4], xmxv[4], ymyv[4];  double xc, yc, zc, zsq, xn, yn, zn, znabs, xsq, ysq, rsq, diagsq, dtol;  double v, arg, st, ct, length, s1, c1, s2, c2, s12, c12, val;  double *s;  double rInv, r2Inv, r3Inv, r5Inv, r7Inv, r9Inv, zr2Inv;  double ss1, ss3, ss5, ss7, ss9;  double s914, s813, s411, s512, s1215;  double fs, fd, fdsum;  int okay, i, next;  struct edge *edge;  double *corner;  /* Put the evaluation point into this panel's coordinates. */  xc = x - panel->x;  yc = y - panel->y;  zc = z - panel->z;  xn = DotP_Product(panel->X, xc, yc, zc);  yn = DotP_Product(panel->Y, xc, yc, zc);  zn = DotP_Product(panel->Z, xc, yc, zc);  zsq = zn * zn;  xsq = xn * xn;  ysq = yn * yn;  rsq = zsq + xsq + ysq;  diagsq = panel->max_diag * panel->max_diag;  if(rsq > (LIMITFOURTH * diagsq)) {    fs = 0.0; fd = 0.0;    s = panel->moments;    /* First, second moments. */    r2Inv = 1.0 / rsq;    rInv = sqrt(r2Inv);    r3Inv = r2Inv * rInv;    r5Inv = r3Inv * r2Inv;    zr2Inv = zn * r2Inv;    ss1 = s[1] * rInv;    ss3 = -(s[3] + s[10]) * r3Inv;    ss5 = (xsq * s[10] + (xn * yn * s[7]) + ysq * s[3]) * r5Inv;    fs = ss1 + ONE3 * ss3 + ss5;    fdsum = ss1 + ss3 + 5.0 * ss5;    fd = zr2Inv * fdsum;    if(rsq < (LIMITSECOND * diagsq)) {    /* Third and fourth moments added for diagsq/r2 between 40 and 150. */      s914 = s[9] + s[14];      s813 = s[8] + s[13];      s411 = s[4] + s[11];      s512 = s[5] + s[12];      s1215 = s[12] + s[15];      r7Inv = r5Inv * r2Inv;      r9Inv = r7Inv * r2Inv;      ss5 = (-xn * s813 - yn * s411 + 0.1 * (s512 + s1215)) * r5Inv;      ss7 = (FIVE3 *((xn * xsq * s[13] + yn * ysq * s[4]) 		     + 3.0 * xn * yn * (xn * s[11]  +  yn * s[8]))		     - xsq * s1215 - ysq * s512 - xn * yn * s914) * r7Inv;      ss9 = (7.0 * (ONE6 * (xsq * xsq * s[15] + ysq * ysq * s[5])		    + xsq * ysq * s[12])	     + SEVEN3 * xn * yn * (xsq * s[14] + ysq * s[9])) * r9Inv;      fs += ss5 + ss7 + ss9;      fdsum = 5.0 * ss5 + 7.0 * ss7 + 9.0 * ss9;      fd += zr2Inv * fdsum;      num4th++;    }    else num2nd++;  }  else {    dtol = EQUIV_TOL * panel->min_diag;    znabs = fabs(zn);    /* Always move the evaluation point a little bit off the panel. */    if(znabs < dtol) {       zn = 0.5 * dtol;  /* Half of dtol insures detection for zero dipole. */      znabs = 0.5 * dtol;    }    /* Once per corner computations. */    for(okay = TRUE, i=0; i < panel->shape; i++) {      corner = panel->corner[i];       xmxv[i] = xc = xn - corner[XI];      ymyv[i] = yc = yn - corner[YI];      zc = zn - corner[ZI];      fe[i] = xc * xc + zc * zc;      r[i] = sqrt(yc * yc + fe[i]);      if(r[i] < (1.005 * znabs)) {  /* If r almost z, on vertex normal. */	okay = FALSE;      }    }    /* Once per edge computations. */    fs = 0.0; fd = 0.0;    for(i=0; i < panel->shape; i++) {      if(i == (panel->shape - 1)) next = 0;      else next = i + 1;      /* Now calculate the edge contributions to a panel. */      length = panel->length[i];      ct = (panel->corner[next][XI] - panel->corner[i][XI]) / length;      st = (panel->corner[next][YI] - panel->corner[i][YI]) / length;      /* v is projection of eval-i edge onto perpend to next-i edge. */      /* Exploits the fact that corner points in panel coordinates. */      v = xmxv[i] * st - ymyv[i] * ct;      /* arg == zero if eval on next-i edge, but then v = 0. */      arg = (r[i] + r[next] - length)/(r[i] + r[next] + length);      if(arg > 0.0) fs -= v * log(arg);      /* Okay means eval not near a vertex normal, Use Hess-Smith. */      if(okay) {	s1 = v * r[i];	c1 = znabs * (xmxv[i] * ct + ymyv[i] * st);	s2 = v * r[next];	c2 = znabs * (xmxv[next] * ct + ymyv[next] * st);      }      /* Near a vertex normal, use Newman. */      else {	s1 = (fe[i] * st) - (xmxv[i] * ymyv[i] * ct);	c1 = znabs * r[i] * ct;	s2 = (fe[next] * st) - (xmxv[next] * ymyv[next] * ct);	c2 = znabs * r[next] * ct;      }          s12 = (s1 * c2) - (s2 * c1);      c12 = (c1 * c2) + (s1 * s2);      val = atan2(s12, c12);      fd += val;    }    /* Adjust the computed values. */    if(fd < 0.0) fd += TWOPI;    if(zn < 0.0) fd *= -1.0;    if(znabs < dtol) fd = 0.0;    fs -= zn * fd;    numexact++;  }  /* Return values of the source and dipole, normalized by area. */  fs /= panel->area;  fd /= panel->area;  if(pfd != NULL) *pfd = fd;  if(fs < 0.0) {    fprintf(stderr, 	    "\ncalcp: panel potential coeff. less than zero = %g\n", fs);    fprintf(stderr, "Okay = %d Evaluation Point = %g %g %g\n", okay, x, y, z);    fprintf(stderr, "Evaluation Point in local coords = %g %g %g\n",xn,yn, zn);    fprintf(stderr, "Panel Description Follows\n");    dp(panel);    /*exit(1);*/  }  return (fs);}dumpnums(flag, size)int flag, size;{  double total;  if(flag == ON) {		/* if first call */    num2ndsav = num2nd;    num4thsav = num4th;    numexactsav = numexact;  }  else {    total = num2ndsav + num4thsav + numexactsav;#if MULDAT == ON    fprintf(stdout, "Potential coefficient counts\n multipole only:\n");    fprintf(stdout, 	    "  2nd order: %d %.3g%%; 4th: %d %.3g%%; Integral: %d %.3g%%\n",	    num2nd, 100*(num2ndsav/total), num4th, 100*(num4thsav/total), 	    numexact, 100*(numexactsav/total));#endif    total = num2nd + num4th + numexact;#if MULDAT == ON    fprintf(stdout, " multipole plus adaptive:\n");    fprintf(stdout, 	    "  2nd order: %d %.3g%%; 4th: %d %.3g%%; Integral: %d %.3g%%\n",	    num2nd, 100*(num2nd/total), num4th, 100*(num4th/total), 	    numexact, 100*(numexact/total));#endif    fprintf(stdout, "Percentage of multiplies done by multipole: %.3g%%\n",	    100*(size*size - total)/(size*size));    if(size*size == total) 	fprintf(stdout, "Warning: no multipole acceleration\n");  }}double tilelength(nq)charge *nq;{  return nq->max_diag;}/*Evaluation of moments of quadrilateral surface relative tolocal system, array S(15).  First initialize arrayNote that S(2)=S(6)=0 due to transfer above*/ComputeMoments(pp)charge *pp;{  int order=MAXORDER;  int i, j, nside,  N, M, N1, M1, M2, MN1, MN2;  double dx, dy, dxdy, dydx, x, y, z, SI, *xp, *yp, *xpn, *ypn;  double ypp[3];  static double *XP[4], *YP[4], **I;  static int maxorder = 0;  static double CS[16] = { 0.0, 1.0, 1.0, 1.5, 1.5, 3.75, 1.0, 3.0, 			   1.5, 7.5, 1.5, 1.5, 3.75, 1.5, 7.5, 3.75 };  double *multi, sumc, sums, sign, **createBinom(), **createPmn();  int m, n, r, halfn, flrm, ceilm, numterms, rterms;    /* Allocate temporary storage and initialize arrays. */  if(order > maxorder) {    for(i = 0; i < 4; i++) {      CALLOC(XP[i], (order+3), double, ON, AQ2P);      CALLOC(YP[i], (order+3), double, ON, AQ2P);    }    /* Allocate the euclidean moments matrix, Imn. */    CALLOC(I, (order+1), double*, ON, AQ2P);    for(i = 0; i <= order; i++) CALLOC(I[i], (order+1), double, ON, AQ2P);    maxorder = order;  }  /* First zero out the Moments matrix. */  for(i = 0; i <= order; i++) {    for(j = 0; j <= order; j++) {      I[i][j] = 0.0;    }  }      /* Compute powers of x and y at corner pts. */  for(i = 0; i < pp->shape; i++) {    xp = XP[i];    yp = YP[i];    xp[1] = pp->corner[i][XI];    yp[1] = pp->corner[i][YI];    for(j = 2; j <= order+2; j++) {      xp[j] = xp[j-1] * xp[1];      yp[j] = yp[j-1] * yp[1];    }  }  /* First moment, easy, just the panel area. */  I[0][0] = pp->area;  /* By using centroid, (1,0) and (0,1) are zero, so begin with (2,0). */  for(nside = 0; nside < pp->shape; nside++) {    xp = XP[nside];    yp = YP[nside];    if(nside == (pp->shape - 1)) {      xpn = XP[0];      ypn = YP[0];      }    else {      xpn = XP[nside + 1];      ypn = YP[nside + 1];    }    dx = xpn[1] - xp[1];    dy = ypn[1] - yp[1];    if(fabs(dx) >= fabs(dy)) {      dydx = dy/dx;      for(M = 2; M <= order; M++) {	M1 = M + 1;	M2 = M + 2;	SI = ((xpn[M1] * ypn[1]) - (xp[M1] * yp[1])) / M1	     + dydx * (xp[M2] - xpn[M2]) / (M1 * M2);	I[M][0] += SI;	for(N = 1; N <= M; N++) {	  N1 = N + 1;	  MN1 = M - N + 1;	  SI = (xpn[MN1] * ypn[N1] - xp[MN1] * yp[N1]) / (MN1 * N1)		     - (dydx * N * SI) / MN1;	  I[M-N][N] += SI;	}      }    }    else {      dxdy = dx/dy;      for(M = 2; M <= order; M++) {	M1 = M + 1;	M2 = M + 2;	SI = (dxdy / (M1 * M2)) * (ypn[M2] - yp[M2]);	I[0][M] += SI;	for(N = 1; N <= M; N++) {	  MN1 = M - N + 1;	  MN2 = MN1 + 1;          SI = dxdy * ((xpn[N] * ypn[MN2] - xp[N] * yp[MN2]) / (MN1 * MN2) 			- (N * SI / MN1));	  I[N][M-N] += SI;	}      }    }  }  /* Now Create the S vector for calcp. */  for(i = 0, M = 0; M <= 4; M++) {    for(N = 0; N <= (4 - M); N++) {      i++;      pp->moments[i] = I[M][N] * CS[i];    }  }}/* Debugging Print Routines follow. */dp(panel)charge *panel;{  int i;  double c[4][3];  printf("shape=%d maxdiag=%g mindiag=%g area=%g\n", 	 panel->shape, 	 panel->max_diag, panel->min_diag, panel->area);  fprintf(stdout, "surface: `%s'\n", panel->surf->name);  printf("x=%g y=%g z=%g\n", panel->x, panel->y, panel->z);  printf("X= %g %g %g\n", panel->X[0], panel->X[1], panel->X[2]);  printf("Y= %g %g %g\n", panel->Y[0], panel->Y[1], panel->Y[2]);  printf("Z= %g %g %g\n", panel->Z[0], panel->Z[1], panel->Z[2]);  for(i=0; i < panel->shape; i++)      printf("corner%d = %g %g %g\n", 	     i, panel->corner[i][0], panel->corner[i][1], panel->corner[i][2]);  for(i = 0; i < panel->shape; i++) {    c[i][0] = panel->x + panel->corner[i][0]*panel->X[0] 	+ panel->corner[i][0]*panel->X[1] + panel->corner[i][0]*panel->X[2];    c[i][1] = panel->y + panel->corner[i][1]*panel->Y[0] 	+ panel->corner[i][1]*panel->Y[1] + panel->corner[i][1]*panel->Y[2];    c[i][2] = panel->z + panel->corner[i][2]*panel->Z[0] 	+ panel->corner[i][2]*panel->Z[1] + panel->corner[i][2]*panel->Z[2];    printf("absolute corner%d = %g %g %g\n", i, c[i][0], c[i][1], c[i][2]);  }  for(i=0; i < panel->shape; i++)      printf("length%d = %g\n", i, panel->length[i]);  printf("multipole coeffs:  ");  for(i=0; i < 16; i++) {    printf("%g  ", panel->moments[i]);    if( (i % 6) == 0) printf("\n");  }  printf("\n");}#define DIS 2#define SCALE 5testCalcp(pp)charge *pp;{  double offx, offy, offz, x, y, z, mult;  int i, j, k;  offx = pp->x;  offy = pp->y;  offz = pp->z;  mult = 0.5 * pp->min_diag;  printf("\n\nCenter Point %g %g %g\n", offx, offy, offz);  for(i=0; i < DIS; i++) {    for(j=0; j < DIS; j++) {      for(k=0; k < DIS; k++) {	x = offx + i * mult * SCALE;	y = offy + j * mult * SCALE;	z = offz + k * mult * SCALE;	printf("Eval pt = %g %g %g\n", x, y, z);        calcp(pp, x, y, z, NULL);      }    }  }}fileCorners(pp, f)FILE *f;charge *pp;{  int i;  for(i=0; i < pp->shape; i++)      fprintf(f, "%g %g\n", pp->corner[i][0], pp->corner[i][1]);}/* Test the moment code. */calcpm(multi, x, y, z, origorder, order)double *multi, x, y, z;int order;{  charge panel, *ppanel;  double **mat, **mulMulti2P(), potential;  int i, numterms;  /* Create a temporary panel which has evaluation point as centroid. */  panel.x = x;  panel.y = y;  panel.z = z;  ppanel = &panel;  mat = mulMulti2P(0.0, 0.0, 0.0, &ppanel, 1, origorder);  numterms = multerms(origorder);  /* Calculate the potential. */  for(potential = 0.0, i = 0; i < numterms; i++) {    potential += mat[0][i] * multi[i];  }}/*dismat(mat, size)double **mat;int size;{  int i, j;  for(i=0; i <= size; i++) {    printf("\nrow i = ");    for(j=0; j <= size; j++) {      printf("%g  ", mat[i][j]);    }  }  printf("\n");}*/

⌨️ 快捷键说明

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