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

📄 conviso.c

📁 蒙特卡罗算法。用盟特卡罗算法模拟光在组织钟的传播
💻 C
字号:
/**** *  This files plot a series of contour lines for a 2D array of double. *  4/14/92. ****/#include <math.h>#include <stdlib.h>#include <stdio.h>#include <stddef.h>#include <time.h>#include <string.h>#include <ctype.h>#ifndef PI#define PI 3.1415926#endif/**** *	Return true is val is between Z[i][j] and Z[i+1][j]. ****/#define INTERSECTI(val, Z, i, j) \  (Z[i][j] <= val && val <= Z[i+1][j] || \   Z[i][j] >= val && val >= Z[i+1][j])/**** *	Return true is val is between Z[i][j] and Z[i][j+1]. ****/#define INTERSECTJ(val, Z, i, j) \  (Z[i][j] <= val && val <= Z[i][j+1] || \   Z[i][j] >= val && val >= Z[i][j+1])FILE       *GetWriteFile(char *Ext);	/* in conho.c. */struct XY {  double      x, y;};struct XYpairs {  double      x, y;  struct XYpairs *next;};typedef struct XYpairs *PairList;/* set up a que for printing the pairs. */typedef PairList QDATA;struct Qlinked_list {  QDATA       d;  struct Qlinked_list *next;};typedef struct Qlinked_list QELEMENT;typedef QELEMENT *QLINK;typedef struct {		/* a que of pairs. */  QLINK       front, rear;}           QUE;/* end of que definition. */struct Isolines {  double      iso_val;		/* z value of the contour line. */  PairList    pairs;  struct Isolines *next;};typedef struct Isolines *IsoList;double ZMin(double **Z,     long IXmax,     long IYmax,     double Dx,     double Dy,     struct XY * Pmin_Ptr){  double      zmin;  long        i, j;  zmin = Z[0][0];  for (i = 0; i < IXmax; i++)    for (j = 0; j < IYmax; j++)      if (Z[i][j] < zmin) {	zmin = Z[i][j];	Pmin_Ptr->x = i * Dx;	Pmin_Ptr->y = j * Dy;      }  return (zmin);}double ZMax(double **Z,     long IXmax,     long IYmax,     double Dx,     double Dy,     struct XY * Pmax_Ptr){  double      zmax;  long        i, j;  zmax = Z[0][0];  for (i = 0; i < IXmax; i++)    for (j = 0; j < IYmax; j++)      if (Z[i][j] > zmax) {	zmax = Z[i][j];	Pmax_Ptr->x = i * Dx;	Pmax_Ptr->y = j * Dy;      }  return (zmax);}/* Get the isovalues from user. */IsoList GetIsoValues(double Z_Min, double Z_Max){  IsoList     head;  char        in_str[256];  printf("Input an isovalue or . to stop: ");  scanf("%s", in_str);  if (strlen(in_str) == 1 && in_str[0] == '.')    return (NULL);  head = (IsoList) malloc(sizeof(struct Isolines));  if (head == NULL)    return (NULL);  /* get the elements for the node. */  sscanf(in_str, "%lf", &head->iso_val);  if (head->iso_val < Z_Min)    head->iso_val = Z_Min;  else if (head->iso_val > Z_Max)    head->iso_val = Z_Max;  head->pairs = NULL;  head->next = GetIsoValues(Z_Min, Z_Max);  return (head);}/**** *  The isoposition is between [i][j] & [i+1][j] * *  Linear interpolation is used to locate the y component of *  the iso position. ****/void IsoPositionI(PairList pair,	     double iso_val, double **Z,	     long i, long j,	     double Dx, double Dy){  pair->y = (j + 0.5) * Dy;  if (Z[i][j] != Z[i + 1][j])    pair->x = (i + 0.5) * Dx + Dx * (iso_val - Z[i][j]) / (Z[i + 1][j] - Z[i][j]);  else    pair->x = (i + 1) * Dx;	/* take the mid point. */}/**** *  The isoposition is between [i][j] & [i][j+1] * *  Linear interpolation is used to locate the y component of *  the iso position. ****/void IsoPositionJ(PairList pair,	     double iso_val, double **Z,	     long i, long j,	     double Dx, double Dy){  pair->x = (i + 0.5) * Dx;  if (Z[i][j + 1] != Z[i][j])    pair->y = (j + 0.5) * Dy + Dy * (iso_val - Z[i][j]) / (Z[i][j + 1] - Z[i][j]);  else    pair->y = (j + 1) * Dy;	/* take the mid point. */}void IsoPosition(PairList pair,	    double iso_val, double **Z,	    long i, long j,	    double Dx, double Dy){  if (INTERSECTI(iso_val, Z, i, j))    IsoPositionI(pair, iso_val, Z, i, j, Dx, Dy);  else if (INTERSECTJ(iso_val, Z, i, j))    IsoPositionJ(pair, iso_val, Z, i, j, Dx, Dy);}PairList AllocPair(void){  PairList    pair;  pair = (PairList) malloc(sizeof(struct XYpairs));  if (pair == NULL)    puts("...malloc error. Contour lines are not complete");  return (pair);}void GetAnIsoLine(IsoList IsoNode, double **Z,	     long IXmax, long IYmax,	     double Dx, double Dy){  long        i, j;  double      ival = IsoNode->iso_val;  PairList    pair_tail;  for (j = 0; j < IYmax - 1; j++)    for (i = 0; i < IXmax - 2; i++)      if (INTERSECTI(ival, Z, i, j) ||	  INTERSECTJ(ival, Z, i, j)) {	/* found a pair. */	if (IsoNode->pairs == NULL) {	/* 1st pair. */	  if (!(IsoNode->pairs = AllocPair()))	    return;	  pair_tail = IsoNode->pairs;	} else {		/* subsequent  pairs. */	  if (!(pair_tail->next = AllocPair()))	    return;	  pair_tail = pair_tail->next;	}	IsoPosition(pair_tail, ival, Z, i, j, Dx, Dy);      }  pair_tail->next = NULL;	/* end of the pair list. */}/**** *	Return the quadrant. *	For Frz or Arz, the peak point is usually on z axis which is *	y here. We want start the isoline from the 4th quadrant. *	Therefore, we use -1 for the 4th quadrant instead of 4. ****/short GetQuadrant(double x, double y){  if (x > 0 && y >= 0)    return (1);			/* Include +x-axis. */  else if (x <= 0 && y > 0)    return (2);			/* Include +y-axis. */  else if (x < 0 && y <= 0)    return (3);			/* Include -x-axis. */  else if (x >= 0 && y < 0)    return (-1);		/* Include -y-axis. */}/**** *  Compare the angle wrt Pmax.  If the angle of "This" is larger *  than that of the "Next", return 1.  Otherwise, return 0. * *  Although atan2 returns value in the range -pi to pi, we want *	to avoid it because it is slow.  We compare the quadrants of *	the two points first.  If they are in the same quadrant, we *	compare the relative positions. ****/char OutOfOrder(PairList This,	/* current pair. */	   PairList Next,	   struct XY Pmax){  double      x0, y0, x1, y1;  short       q0, q1;		/* Quadrants. */  char        out_order;  if (This == NULL || Next == NULL)    return (0);			/* This shouldn't happen. */  x0 = This->x - Pmax.x;  y0 = This->y - Pmax.y;  q0 = GetQuadrant(x0, y0);  x1 = Next->x - Pmax.x;  y1 = Next->y - Pmax.y;  q1 = GetQuadrant(x1, y1);  if (q0 < q1)    out_order = 0;  else if (q0 > q1)    out_order = 1;  else {			/* In the same quadrant. */    if (y0 * x1 < y1 * x0)      out_order = 0;    else      out_order = 1;  }  return (out_order);}/**** *  Sort the isopositions according to the angle with respect to *  the position of the maximum value. ****/void SortAnIsoLine(PairList * PairHeadPtr,	      struct XY Pmax){  char        sorted = 0;  PairList    this, last;	/* this=the pair being compared w/ the				 * next one. */  PairList    sorted_head = NULL;	/* the head to the sublist of					 * sorted pairs. */  while (!sorted && sorted_head != *PairHeadPtr) {    sorted = 1;			/* assume sublist is sorted. */    last = NULL;    this = *PairHeadPtr;	/* sublist starts at *PairHeadPtr, ends at				 * sorted_head. */    while (this->next != sorted_head) {	/* traverse the sublist. */      if (OutOfOrder(this, this->next, Pmax)) {	/* swap and move to next. */	sorted = 0;	if (last == NULL)	  *PairHeadPtr = this->next;	else	  last->next = this->next;	last = this->next;	this->next = last->next;	last->next = this;      } else {			/* move to next. */	last = this;	this = this->next;      }    }				/* end of sublist traversing. */    sorted_head = this;  }				/* end of big while. */}#if 0/**** *	Repeat the first pair of the isoline at the end of the list *	so that the isoline is a loop. *	Sometimes this may not be desired. ****/void LoopAnIsoLine(PairList * PairHeadPtr){  PairList    tail;  tail = *PairHeadPtr;  while (tail->next != NULL)    tail = tail->next;  tail->next = (PairList) malloc(sizeof(struct XYpairs));  if (tail->next == NULL)    return;  tail = tail->next;  tail->x = (*PairHeadPtr)->x;  tail->y = (*PairHeadPtr)->y;  tail->next = NULL;}#endifvoid GetIsoLines(IsoList isos,	    double **Z,	    long IXmax,	    long IYmax,	    double Dx,	    double Dy,	    struct XY Pmax){  IsoList     node = isos;  while (node != NULL) {    GetAnIsoLine(node, Z, IXmax, IYmax, Dx, Dy);    SortAnIsoLine(&node->pairs, Pmax);    /* LoopAnIsoLine(&node->pairs); */    node = node->next;  }}char IsEmpty(QUE q){  return (q.front == NULL);}void Deque(QUE * q, QDATA * x){  QLINK       temp = q->front;  if (!IsEmpty(*q)) {    *x = temp->d;    q->front = temp->next;    free(temp);  } else    printf("Empty que.\n");}void Enque(QUE * q, QDATA x){  QLINK       temp;  temp = (QLINK) malloc(sizeof(QELEMENT));  temp->d = x;  temp->next = NULL;  if (IsEmpty(*q))    q->front = q->rear = temp;  else {    q->rear->next = temp;    q->rear = temp;  }}void WriteIsoLines(FILE * Isofile,	      IsoList IsoHead){  QUE         qprint = {NULL, NULL};	/* que to be printed. */  QUE         qsave = {NULL, NULL};  QDATA       p;		/* QDATA is PairList. */  char        all_nulls;  while (IsoHead != NULL) {    fprintf(Isofile, "X%-8lG\tY%-8lG\t", IsoHead->iso_val, IsoHead->iso_val);    Enque(&qprint, IsoHead->pairs);    IsoHead = IsoHead->next;  }  fprintf(Isofile, "\n");  do {    all_nulls = 1;    while (!IsEmpty(qprint)) {      Deque(&qprint, &p);      if (p != NULL) {	fprintf(Isofile, "%9.2lE\t%9.2lE\t", p->x, p->y);	Enque(&qsave, p->next);	/* add the next to a new que for a new				 * row. */	if (all_nulls == 1)	  all_nulls = 0;      } else {	/* fprintf(Isofile, "%9s\t%9s\t", " ", " "); */	fprintf(Isofile, "\t\t");	Enque(&qsave, p);	/* add a null to the new que. */      }    }    fprintf(Isofile, "\n");    qprint = qsave;    qsave.front = NULL;    qsave.rear = NULL;  } while (!all_nulls);}void FreePairs(PairList Pairs){  PairList    this_pair;  while (Pairs != NULL) {    this_pair = Pairs;    Pairs = Pairs->next;    free(this_pair);  }}void FreeIsoLines(IsoList IsoHead){  IsoList     this_iso;  PairList    pair_head;  while (IsoHead != NULL) {    FreePairs(IsoHead->pairs);    this_iso = IsoHead;    IsoHead = IsoHead->next;    free(this_iso);  }}void IsoPlot(double **Z,		/* the 2D array Z[i][j]. */	long int IXmax,	long int IYmax,		/* the 0<=i<=IXmax, 0<=j<=IYmax. */	double Dx,	double Dy){				/* the gridline separations. */  FILE       *isofile;		/* send isolines to this file. */  struct XY   pmin, pmax;	/* the xy positions of the min & max. */  double      zmin, zmax;  IsoList     isos;  char        fname[128] = "iso";  /* Locate the min & max. */  zmin = ZMin(Z, IXmax, IYmax, Dx, Dy, &pmin);  zmax = ZMax(Z, IXmax, IYmax, Dx, Dy, &pmax);  if (zmin == zmax || IXmax * IYmax < 4) {    printf("...Not enough data for contour plot\n");    return;  }  isofile = GetWriteFile(fname);  if (isofile == NULL)    return;  printf("The range of the value is %lf to %lf.\n", zmin, zmax);  isos = GetIsoValues(zmin, zmax);  GetIsoLines(isos, Z, IXmax, IYmax, Dx, Dy, pmax);  WriteIsoLines(isofile, isos);  FreeIsoLines(isos);  fclose(isofile);}

⌨️ 快捷键说明

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