Exemple #1
0
int
main(int argc, char **argv)
{
	int nt;		/* number of samples on output trace	*/
	float dt;	/* sample rate on outpu trace		*/
	int min;		/* min time shift (samples) */
	int max;		/* max time shift (samples) */
	unsigned int seed;      /* random number seed */
	int it;			/* time sample counter */
	int itr;		/* trace counter */
	int its=0;		/* local shift in time samples */
	int sits;		/* sign of local shift */
	int fldr;		/* fldr use flag		*/
	int ishot;		/* shot counter (based on tr.fldr) */
	int ishotold;
	int pon;		/* flag for pos or neg shift */


	/* Hook up getpar */
	initargs(argc, argv);
	requestdoc(1);

	/* Get information from first trace */
	if (!gettr(&tr)) err("can't get first trace");
	nt   = tr.ns;
	ishotold = tr.fldr;
	dt   = ((double) tr.dt)/1000000.0;
	
	/* Get parameters */
	if (!getparint("min", &min))    min = 1;
	if (!getparint("max", &max))    max = 1;
	if (!getparint("pon", &pon))    pon = 1;
	if (!getparint("fldr", &fldr))  fldr = 0;

	if (min>max) err("min>max... exit");

	/* Set seed */
	if (!getparuint("seed", &seed)) { /* if not supplied, use clock */
		if (-1 == (seed = (unsigned int) time((time_t *) NULL))) {
			err("time() failed to set seed");
		}
	}
	sranuni(seed);

	/* Loop on traces */	
	itr = 1;
	do {

		/* get fldr (shot) number */
		ishot = tr.fldr;

		if (itr==1) {
			/* initial shift for shot 1 
			   (used if fldr==1) */	
	       		its = min + (max-min)*franuni();
			if (pon==1) {
				/* include random sign to shift */
				sits = SGN(franuni()-0.5);
				its = its * sits;
			}
		}
		
		if (fldr==0) {
			/* each trace gets random shift */
	       		its = min + (max-min)*franuni();
			if (pon==1) {
				/* include random sign to shift */
				sits = SGN(franuni()-0.5);
				its = its * sits;
			}
		}

		if (fldr==1 && ishot!=ishotold) {
			/* new shot needs new shift */
	       		its = min + (max-min)*franuni();
			if (pon==1) {
				/* include random sign to shift */
				sits = SGN(franuni()-0.5);
				its = its * sits;
			}
			ishotold = ishot;
		}

		/* apply shift and output trace */
		if (its <= 0 ) {
			/* loop over output times */
			for (it=0; it<nt-its; ++it) {
				tr.data[it] = tr.data[it-its];	
			}
		} else {
			/* loop over output times */
			for (it=nt; it>its; --it) {
				tr.data[it] = tr.data[it-its];	
			}

		}
		puttr(&tr);

		itr += 1;

	} while (gettr(&tr));


	return(CWP_Exit());
}
Exemple #2
0
main(int argc, char **argv)
{
	int nt;			/* number of points on trace		*/
	int databytes;		/* ... in bytes 			*/
	int ntr;		/* number of traces			*/
	string stype;		/* noise type (gauss, flat) as string	*/
	int itype;		/* ... as integer (for use in switch)	*/
	float sn;		/* signal to noise ratio		*/
	unsigned int seed;	/* random number seed			*/
	FILE *hdrfp;		/* fp for header storage file		*/
	FILE *sigfp;		/* fp for data ("signal")		*/
	int nfloats;		/* number of floats in "signal"		*/
	float *noise;		/* noise vector				*/
	float noiscale;		/* scale for noise			*/
	float absmaxsig;	/* absolute maximum in signal		*/
	float noipow;		/* a measure of noise power		*/
	float f1;		/* left lower corner frequency		*/
	float f2;		/* left upper corner frequency		*/
	float f4;		/* right lower corner frequency		*/
	float f3;		/* right upper corner frequency		*/
        char * scrdir;          /* scratch dir to put temporary data set */

	/* Initialize */
	initargs(argc, argv);
	askdoc(1);


	/* Get noise type */
	if (!getparstring("noise", &stype))	stype = "gauss";

	if      (STREQ(stype, "gauss")) itype = GAUSS;
	else if (STREQ(stype, "flat"))  itype = FLAT;
	else     err("noise=\"%s\", must be gauss or flat", stype);


	/* Get signal to noise ratio */
	if (!getparfloat("sn", &sn))	sn = SN;
	if (sn <= 0) err("sn=%d must be positive", sn);


	/* Set seed */
	if (!getparuint("seed", &seed)) { /* if not supplied, use clock */
		if (-1 == (seed = (uint) time((time_t *) NULL))) {
			err("time() failed to set seed");
		}
	}
	(itype == GAUSS) ? srannor(seed) : sranuni(seed);

        if( !getparstring("scrdir",&scrdir) ) {
            scrdir = getenv("SU_SCRATCHDIR") ;
        }


	/* Prepare temporary files to hold headers and data */
	/*
	hdrfp = etmpfile();
	sigfp = etmpfile();
	*/
	hdrfp = etempfile(NULL);
	sigfp = etempfile(NULL);


	/* Get info from first trace */
	if (!gettr(&tr)) err("can't get first trace");
	nt = tr.ns;
	databytes = nt * FSIZE;


	/* Loop over input traces & write headers and data to tmp files */
	ntr = 0;
	do {
		++ntr;
		efwrite(&tr, 1, HDRBYTES, hdrfp);
		efwrite(tr.data, 1, databytes, sigfp);
	} while (gettr(&tr));
	nfloats = ntr * nt;


	/* Compute absmax of signal over entire data set */
	rewind(sigfp);
	absmaxsig = 0.0;
	{ register int i;
	  for (i = 0; i < nfloats; ++i) {
		float sigval;
		efread(&sigval, FSIZE, 1, sigfp);
		absmaxsig = MAX(absmaxsig, ABS(sigval));
	  }
	}


	/* Compute noise vector elements in [-1, 1] */
	noise = ealloc1float(nfloats);
	switch (itype) {
		register int i;
	case GAUSS: /* frannor gives elements in N(0,1)--ie. pos & negs */
		for (i = 0; i < nfloats; ++i)  noise[i] = frannor();
	break;
	case FLAT: /* franuni gives elements in [0, 1] */
		for (i = 0; i < nfloats; ++i)  noise[i] = 2.0*franuni() - 1.0;
	break;
	default:	/* defensive programming */
		err("%d: mysterious itype = %d", __LINE__, itype);
	}


	/* Band limit noise traces if user getpars any of the f's */
	if (getparfloat("f1", &f1) || getparfloat("f2", &f2) ||
	    getparfloat("f3", &f3) || getparfloat("f4", &f4) ) {

		/* Set up call to suband */
		char cmdbuf[BUFSIZ];	    /* build suband command	*/
		FILE *bandinfp;		    /* fp for input file	*/
		FILE *fp;                   /* fp for pipe to suband	*/
		int nsegy = HDRBYTES + databytes;
		char *segybuf = ealloc1(nsegy, 1);


		/* Trap signals so can remove tmpnam file */
		signal(SIGINT,  (void *) trapsig);
		signal(SIGQUIT, (void *) trapsig);
		signal(SIGHUP,  (void *) trapsig);
		signal(SIGTERM, (void *) trapsig);

		/* Prepare temporary files to hold traces */
		/*bandinfp  = etmpfile();*/
		bandinfp  = etempfile(NULL);
		/*bandoutfp = efopen(etmpnam(bandoutfile), "w+");*/
		bandoutfile = etempnam(scrdir,NULL) ;
		bandoutfp = efopen(bandoutfile, "w+");

		/* Paste headers on noise traces and put in tmpfile */
		rewind(hdrfp);
		{ register int itr;
		  for (itr = 0; itr < ntr; ++itr) {
			efread(&tr, 1, HDRBYTES, hdrfp);
			memcpy(tr.data, noise + itr*nt, databytes); 
			fputtr(bandinfp, &tr);
		  }
		}

		/* Pipe to suband - suband handles the getpars */
		sprintf(cmdbuf, "suband >%s", bandoutfile);
		fp = epopen(cmdbuf, "w");
		rewind (bandinfp);
		{ register int itr;
		  for (itr = 0; itr < ntr; ++itr) {
			efread(segybuf, 1, nsegy, bandinfp);
			efwrite(segybuf, 1, nsegy, fp);
		  }
		}
		efclose(bandinfp);
		epclose(fp);

		/* Load bandlimited traces back into noise vector */
		rewind(bandoutfp);
		{ register int itr;
		  for (itr = 0; itr < ntr; ++itr) {
			fgettr(bandoutfp, &tr);
			memcpy(noise + itr*nt, tr.data, databytes); 
		  }
		}
		efclose(bandoutfp);
		eremove(bandoutfile);

	} /* End optional bandlimiting */
		


	/* Compute noise power */
	noipow = 0.0;
	{ register int i;
	  for (i = 0; i < nfloats; ++i) {
		register float noiseval = noise[i];
		noipow += noiseval * noiseval;
	  }
	}


	/* Compute noise scale for desired noise/signal ratio */
	absmaxsig /= sqrt(2.0);  /* make it look like a rmsq value   */
	noipow /= nfloats;	 /* make it the square of rmsq value */
	noiscale = absmaxsig / (sn * sqrt(noipow));


	/* Add scaled noise to trace and output sum */
	rewind(hdrfp);
	rewind(sigfp);
	{ register int itr;
	  for (itr = 0; itr < ntr; ++itr) {
		register int trshift = itr*nt;
		register int i;

		efread(&tr, 1, HDRBYTES, hdrfp);
		efread(tr.data, 1, databytes, sigfp);
		for (i = 0; i < nt; ++i)
			tr.data[i] += noiscale * noise[trshift + i];

		puttr(&tr);
	  }
	}


	return EXIT_SUCCESS;
}
Exemple #3
0
int
main(int argc,char **argv)
{
 
	int  n1, n2, n3, depth, iter,  slowness;
	int nn1, nn2, nn3, nrvl,mode;
	float ***v2, pdv;
	float r1, r2, r3, ***vel, mu, vminc, vmaxc;
	int i1beg, i1end, i2beg, i2end, i3beg, i3end;
	int i1, i2, i3;
	int j1, j2, j3, ih, ilay, j;
	float vlsd, tmp, vorig;
	int add, how;
	unsigned int seed; 	/* random number seed */
	float cvel;
 
	FILE *invp=stdin, *outvp=stdout;


	/* initialization */
	initargs(argc,argv) ;
	requestdoc(0);


	/*-----------get required parameters-----------*/
	if( !getparint("n1",&n1) ) n1 = 0 ;
	if( n1 <= 0 ) err("sample number of 1st dimension invalid" ) ;
	if( !getparint("n2",&n2) ) n2 = 0 ;
	if( n2 <= 0 ) err("sample number of 2nd dimension invalid" ) ;


	/*-----------get optional parameters-----------*/

	if( !getparint("n3",&n3) ) n3 = 1 ;

	/*   get mode from user    */
	if( !getparint("mode",&mode) ) mode = 1 ;
	if( mode < 1  || mode > 2 ) err("mode must be 1 or 2" ) ;

	/* Set seed */
	if (!getparuint("seed", &seed)) { /* if not supplied, use clock */
		if (-1 == (seed = (unsigned int) time((time_t *) NULL))) {
			err("time() failed to set seed");
		}
	}
	sranuni(seed);
	if (mode==2) warn("Random seed for layers = %i",seed);


	/*   single RVL geometry    */
	if( !getparint("i1beg",&i1beg) ) i1beg = 0 ;
	if( !getparint("i1end",&i1end) ) i1end = n1/5 ;
	if( !getparint("i2beg",&i2beg) ) i2beg = 0 ;
	if( !getparint("i2end",&i2end) ) i2end = n2 ;
	if( !getparint("i3beg",&i3beg) ) i3beg = 0 ;
	if( !getparint("i3end",&i3end) ) i3end = n3 ;

	/*   constant velocity layer */
	if( !getparfloat("cvel",&cvel ) ) cvel = 0. ;

	/*   smoothing parameters    */
	if( !getparfloat("r1",&r1) || n1<4) r1 = 0. ;
	if( !getparfloat("r2",&r2) || n2<4) r2 = 0. ;
	if( !getparfloat("r3",&r3) || n3<4) r3 = 0. ;

	/*   many layers     */
	if( !getparint("nrvl",&nrvl) ) nrvl = n1/10 ;
	if( nrvl > n1-1 ) err("nrvl cannot be greater than n1" ) ;
	if( !getparfloat("pdv",&pdv) ) pdv = 10. ;

	/* scale smoothing parameters	*/
	r1 = 0.5*r1*r1 ;
	r2 = 0.5*r2*r2 ;
	r3 = 0.5*r3*r3 ;
 	 
	/*   get iteration number for smoothing operator */
	iter = 2;

	/*   description for vertical dimension    */
	depth = 1;
 
	/*   relative weight at bottom     */
	mu = 1.0;

	/*   smoothing on velocity or slowness     */
	if(!getparint("slowness",&slowness) ) slowness = 0;

	/*   clips of velocity before smoothing     */
	vminc = 0;
	vmaxc = 99999;

     	/*   allocate input file    */
	vel  = alloc3float(n1,n2,n3) ;

	/*   read input velocity file     */
	efseeko(invp,(off_t) 0,SEEK_SET);
	fread((char *)vel[0][0],sizeof(float),n1*n2*n3,invp);

	/*  get layer random velocity std deviation    */
	i1 = (i1beg + i1end)/2;
	vorig = vel[0][0][i1];
	if( !getparfloat("vlsd",&vlsd) ) vlsd = 0.3*vorig;

	/*  get add and how params     */
	if( !getparint("add",&add) ) add = 1 ;
	if( add < 0  || add > 1 ) err("add must be 0 or 1" ) ;
	if( !getparint("how",&how) ) how = 0 ;
	if( how < 0  || how > 2 ) err("how must be 0,1, or 2" ) ;


	/* single layer with point-to-point random velocities */
	if (mode==1) {
		/* dimensions of RVL */
		nn1 = i1end - i1beg;
		nn2 = i2end - i2beg;
		nn3 = i3end - i3beg;

	     	/*   allocate RVL memory    */
		v2 = alloc3float(nn1,nn2,nn3) ;

		/* make the single RVL ... 
		   loop over axis 3 (y) */
		for (i3=0; i3<nn3; ++i3) {

			/* loop over axis 2 (x) */
			for (i2=0; i2<nn2; ++i2) {

				/* loop over axis 1 (z) */ 
				for (i1=0; i1<nn1; ++i1) {

					if (how==0) {
						tmp = vlsd*(0.5-franuni());
					} else if (how==1) {
						tmp = - vlsd*franuni();
					} else if (how==2) {
						tmp = vlsd*franuni();
					}

					if (cvel>0.) {
						vel[i3][i2][i1] = cvel;
					} else { 

						vel[i3][i2][i1] += tmp;
					}

				}
			}
		}
 
		/*   perform smoothing operation    */
		vsm3d(v2,nn3,nn2,nn1,iter,depth,r3,r2,r1,mu,slowness,vminc,vmaxc);

		/* add in, or replace with, the random velocity layer... 
		   loop over axis 3 (y) */
		for (i3=i3beg; i3<i3end; ++i3) {

			j3 = i3 - i3beg;

			/* loop over axis 2 (x) */
			for (i2=i2beg; i2<i2end; ++i2) {

				j2 = i2 - i2beg;

				/* loop over axis 1 (z) */ 
				for (i1=i1beg; i1<i1end; ++i1) {

					j1 = i1 - i1beg;

					if (add==1) {
						if (how==1) {
						  vel[i3][i2][i1] -= v2[j3][j2][j1];
						} else {
						  vel[i3][i2][i1] += v2[j3][j2][j1];
						}
					} else if (add==0) {
						if (how==1) {
						  vel[i3][i2][i1] = vorig - v2[j3][j2][j1];
						} else {
						  vel[i3][i2][i1] = vorig + v2[j3][j2][j1];
						}
					}
					if (cvel>0.) {
						vel[i3][i2][i1] = cvel;
					}

				}
			}
		}	

	}

	/* many constant (random) velocity layers with random thickness */
	if (mode==2) {

		/* axis 1 (z) index */
		i1 = 0;

		/* loop over layers */
		for (ilay=0; ilay<nrvl; ++ilay) {

			/* set addative vel for this layer */
			if (n3>2) {
				i3 = n3/2;
			} else { 
				i3 = 0;
			}
			i2 = n2/2;
			tmp = (0.5-franuni())*pdv*vel[i3][i2][i1]/100;

			/* set thickness of this layer (depth samples) */
			ih = franuni()*n1/(nrvl-ilay) + 1;

			/* loop over depth samples in layer */
			for (j=0; j<ih; ++j) {

				/* loop over axis 3 (y) */
				for (i3=0; i3<n3; ++i3) {

					/* loop over axis 2 (x) */
					for (i2=0; i2<n2; ++i2) {

						vel[i3][i2][i1] += tmp;

					}

				}
				i1 += 1;
			}
		}
 
	}

	/*   write output velocity file     */
	fwrite((char *)vel[0][0],sizeof(float),n1*n2*n3,outvp);  

	/*   close input and output files    */
	fclose(invp) ;
	fclose(outvp) ; 

	return(CWP_Exit());
}
Exemple #4
0
main (int argc, char **argv)
{
/*
    declaration of variables
*/    
       	int master;                  /* master_id                            */
       	int ncpu;                    /* size of population & # of cities     */
       	int pop_city;                /* number of members / city             */
       	int i,j,icity,ibegin,iend,iw;/* counters                             */ 	int ievolution;
	int random_gnr;		     /* read or not trial models from a file */
	float auxf;		     /* """""""" """""			     */
	
       	float wallcpu;		     /* wall clock time			     */
/*
    Variables related to the execution of the GAs
*/ 
       	int population, ncities;    /* pop. size and # of processors        */
       	int genes;		    /* # of genes 		            */
       	int numevol;		    /* # of evolutions			    */
       	int Seed;		    /* Seed for # generation 		    */
	int IS_CONVERGING_FLAG = 0; /* flag for convergence		    */
	int icritical;		    /* next vars are related to convergence */
	int other_city;
	int ihistory;
	int max_stat_evol;
	int verbose;
       	double mmin, mmax;          /* max & min value of a gene	    */
       	char extension[40];         /* extension of the GENESIS files       */
	char workdir[50];	    /* working directory 		    */
        char msg[80];		    /* message purposes		            */	
       	double *vector;		    /* store parameters of trial solution   */
	double *Best_perf;	    /* for the best performance @ city	    */
	double **best_guys;	    /* best_guy of each processor	    */
	double *dist_current;	    /* for convergence			    */
	double offset; 		    /* """ """""""""""                      */
	FILE *fp;		    /* for reading models		    */
/*
    DEBUG
*/
       	int vdebug, jdebug;
/*   
    getting parameters

    At this point the setup files for the execution of the GAs will be done.
    Note that the same file is used by all cities that are part of the
    optimization
*/
       	setup(argc,argv,extension,workdir,&population,&ncities,&genes,&mmin,&mmax,&Seed,&numevol,&offset,&max_stat_evol,&random_gnr,&verbose);

       	sranuni(Seed);		    /* initializing # generator */
       	population *= ncities;      /* that's the total population */

	if (verbose)
	{
       		printf("\n");
       		printf("%d members will be spread among %d populations\n",population,ncities);
	}
/* 
    used for floating representation of chromosomes 
*/
       	vector = (double *) calloc((unsigned) genes, sizeof(double));

/*
    used in convergence analysis
*/
	dist_current = alloc1double(ncities);
	Best_perf = alloc1double(ncities);
/*
    just to be safe safe safe
*/
	for (icity = 0; icity < ncities; icity++)
		dist_current[icity] = 0.;

	best_guys = alloc2double(genes,ncities);
/*
    Starting now the PVM protocol. The aim is to distribute evenly the
    members of the population among the cities
*/
	if (verbose)
       		printf("Starting communication with PVM\n");

       	master = pvmEnroll(CMASTER);
/*
    Create ncities instances of cities
*/
       	for (icity = 0; icity < ncities; icity++) 
	{
          	if (pvmInitiate(CITIES,NULL)<0) 
		{
          		printf("Cannot initiate city %d\n",iw);
          		pvmLeave();
          		exit(-1);
        	}
        	else   
		{
			if (verbose)	
				printf("Process %d started ok\n", icity);
		}
        }
/*
    Sending master instance to all cities
*/
       	pvmBeginMessage();
       	pvmPutNInt(1,&master);
       	pvmSend(MASTER,CITIES,-1);
/*
    Sending for each city the suffix of the data file
*/
       	pvmBeginMessage();
       	pvmPutString(extension);
       	pvmSend(INPUT_FILE,CITIES,-1);
/*
    Sending for each city the working directory 
*/
        pvmBeginMessage();
        pvmPutString(workdir);
        pvmSend(DIRECTORY,CITIES,-1);
/*
    Sending # of processors used in the evolution 
*/
       	pvmBeginMessage();
       	pvmPutNInt(1,&ncities);
       	pvmSend(NCITIES,CITIES,-1);
/*
    Sending # of evolutions that will be performed 
*/
       	pvmBeginMessage();
       	pvmPutNInt(1,&numevol);
       	pvmSend(EVOLVE,CITIES,-1);
/*
    Starting sending members to different cities. Maybe it were better to 
    shuffle them first. Information about members should be sent parameter
    by parameter due to limitation of PVM
*/
	if (!random_gnr)
	{
    		if ((fp = fopen("models", "r")) == NULL)
        	{
	                sprintf(msg, "Cannot open the file MODELS !!!");
                	Error(msg);
        	}
       		printf("Reading %d trial models from file MODELS\n",population);
	}
	else
	{
		if (verbose)
       			printf("Random generation of %d trial models\n",population);
	}

       	ncpu = ncities;
       	while(ncpu > 0) { 
/*   
    Cities are requesting members
*/
          	pvmReceive(SEND_MEMBERS);
          	pvmMessageInfo(NULL,NULL,NULL,&icity);
/*  
    Limits of the population to be allocated to the city
*/          
          	ibegin = (ncpu - 1) * population / ncities;
          	iend = ncpu * population / ncities;

          	for (i = ibegin; i < iend; i++) {
/*
    Will send current member to that city
*/
             		for(j = 0; j < genes; j++)
            	 	{
				if (!random_gnr)
				{
					fscanf(fp,"%f\n",&auxf);	
					vector[j] = (double) auxf;
				}
				else
       	        			vector[j] = Randdouble(mmin,mmax);
	     		}

             	pvmBeginMessage();
	     	pvmPutNDouble(genes, vector);
/*
    Performance and Need_evaluation don't have to be sent
*/
             	pvmSend(MEMBER,CITIES,icity);
          	}
          	ncpu--;
        }
/*
    Checking convergence of the algorithm. The whole process can be
    stopped here if the convergence is not satisfactory

    but 1st ...wall clock time
*/
        wallcpu = wallsec();

	if (verbose)
	{
       		printf("\nMaster will begin convergence analysis:\n");
       		printf("%d low variance evolutions in a row are allowed\n",max_stat_evol);
       		printf("This analysis just applies to distributed runs. If only one\n"); 
		printf("subpopulation is effective the stopping criterion is\n");
		printf("the number of evolutions.\n\n");
	}

 	ievolution = 0;	
       	do 
       	{
       		ncpu = ncities;
       		while(ncpu > 0) { 

          		pvmReceive(IS_IT_CONVERGING);
          		pvmMessageInfo(NULL,NULL,NULL,&icity);
			pvmGetNDouble(genes,&best_guys[icity][0]);
			pvmGetNDouble(1,&Best_perf[icity]);

			ncpu--;
		}
/*
    Checking the change of distance in the model space of the best 
    individuals within each sub-population. This distance is just measured
    for adjacent processors
*/
		icritical = 0;
/* 
    icritical is used to store the # of processors that have their 
    best member without appreciable change since the next generation
*/

		for (icity = 0; icity < ncities; icity++)
		{
			dist_current[icity] = 0.; 
        		other_city = (icity + 1) % ncities;
			for (j = 0; j < genes; j++)
			{
/*
    Calculating the average offset between icity and other_city for this
    generation
*/ 
				dist_current[icity] += ABS(best_guys[icity][j] - best_guys[other_city][j]);
			}
			dist_current[icity] /= (double) genes;

			if (dist_current[icity] < offset) 
				icritical++;
			if (verbose)
				printf("Best stacking power at subpopulation %d is %.3f at evolution %d\n", icity, ABS(Best_perf[icity]), ievolution+1);
/*
     dist_current[icity] refers to the average offset to a neighbour processor 
     in this generation. if this quantity is smaller than the user-specified
     offset, icritical will be incremented
*/
		}

		if (icritical > NINT(ncities/2)) ihistory ++;
		else ihistory = 0; 
		if (ncities == 1) ihistory = 0;

		if (verbose)
			printf("%d evolutions with low variance at evolution %d\n",ihistory,ievolution+1);

/*  
    last statement means that if more than half of the precessors have
    the best member without modifications from the last evolution, ihistory
    will be incremented
*/

		if (ihistory > max_stat_evol) IS_CONVERGING_FLAG = 0;
		else IS_CONVERGING_FLAG = 1;
	
/* 
    max_stat_evol states the tolerable # of evolutions where the half of
    the # of processors can present lack of change in their best members
*/

/*
    broadcasting this information to all processors 
*/
		pvmBeginMessage();
		pvmPutNInt(1,&IS_CONVERGING_FLAG);
		pvmSend(ABOUT_THE_CONVERGENCE,CITIES,-1);
		ievolution ++;			/* increm. # of evol */

		if (!IS_CONVERGING_FLAG)
			printf("ATTENTION ! Low variance populations. Convergenge assumed\n");
	} 
	while(IS_CONVERGING_FLAG && ievolution < numevol);
/*
    Waiting end of GLOBAL evolution 
*/
        ncpu = ncities;
        while(ncpu > 0) { 
       		pvmReceive(END_GLOBAL_EVOLUTION);
	   	ncpu--;
	}

        pvmLeave();			/* Leaving PVM */
        printf("\nEnd of SUDGAST.... I hope you got accurate residual statics...\n");
	wallcpu = wallsec() - wallcpu;
	if (verbose)
		fprintf(stderr, "Wall clock time = %f\n", wallcpu);
}