Esempio n. 1
0
int doit( int port)
{
  fd_set needread;        /* for seeing which fds we need to read from */

    sock = getsock(sendbuf, port);

    printf("ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r\n");
    printf("º    (dialin.exe)  v0.08a   º\r\n");
    printf("º  compiled with Cset v2.1  º\r\n");
    printf("º  (c) 1995 Stephen Loomis  º\r\n");
    printf("ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ\r\n");

    while (1 == 1)
        {
         FD_ZERO(&needread);
         FD_SET(sock, &needread);

         if (select(sizeof(fd_set), &needread, (fd_set *)0,
              (fd_set *)0, (struct timeval *)0) == -1)
           {
            if (errno != EINTR)
                {
                 continue;
                }
            else
             continue; /* do it again and get it right */
           }
        if (FD_ISSET(sock, &needread))
        {
         y=0;cat=0;dog=0;total=0;
         conn = newconn(sock);
        }
 
    }
}
Esempio n. 2
0
File: ether.c Progetto: npe9/harvey
static int
fsopen(Usbfs *fs, Fid *fid, int omode)
{
	int qt;
	int64_t qid;
	Conn *c;
	Dirtab *tab;
	Ether *e;

	qid = fid->qid.path & ~fs->qid;
	e = fs->aux;
	qt = qtype(qid);
	tab = qdirtab(qid);
	omode &= 3;
	if(omode != OREAD && (tab->mode&0222) == 0){
		werrstr(Eperm);
		return -1;
	}
	switch(qt){
	case Qclone:
		c = newconn(e);
		if(c == nil){
			werrstr("no more connections");
			return -1;
		}
		fid->qid.type = QTFILE;
		fid->qid.path = mkqid(c->nb, Qnctl)|fs->qid;
		fid->qid.vers = 0;
		break;
	case Qndata:
	case Qnctl:
	case Qnifstats:
	case Qnstats:
	case Qntype:
		c = getconn(e, qnum(qid), 1);
		if(c == nil)
			sysfatal("usb: ether: fsopen bug");
		incref(c);
		break;
	}
	etherdump(e);
	return 0;
}
//int doffire(unsigned tmax=1000000, unsigned short fmatch=200, unsigned int randPlant=1, unsigned int clustPlant=0, unsigned short burnAge=1, unsigned short burnPropAge=1, int rhoRocks=0, int doSQL=1, float pImmune=0, int nnnAge=0) {
int doffire(unsigned int tmax=1000000, unsigned int fmatch=125, int doSQL=2, float pImmune=0, float kImmune=1, std::string immCode=std::string("100") ) {
	// immCode: [1]: cluster level, [2]: fire-front elements, [3]: each new element. (evaluate immunity at these times).
	//printf("test immCode: %s\n", immCode.c_str());
	if (immCode.at(2)==std::string("1")[0] ) printf("and we are not doing perim-level immunity.\n");
	bool doImPrim=0, doImFlameFront=0, doImFireElement=0;
	if (immCode.at(2)==std::string("1")[0] ) doImPrim=1;
	if (immCode.at(1)==std::string("1")[0] ) doImFlameFront=1;
	if (immCode.at(0)==std::string("1")[0] ) doImFireElement=1;
	
	
	int aveRho = 0, aveVol=0;
	int burnAge=1, burnPropAge=1;
	int nTreesOnGrid=0;
	
	std::string simName("ForestFire5c");
	std::string simPramComment("single-pass fire propagation/immunity evaluation");
	//
	unsigned short rFire = 1;
	unsigned int nBurning = 1;
	unsigned short dnBurning = 1;
	int thisXY, xFire, yFire;
//	int thisStatus;
	int * thisSquare, * fireSquare;
	unsigned int nBurnedTotal=0, nFires=0;  // number of elements burning, new Elements burning...
	float aveTreeAge=0;
	//signed int grids[(ymax+2)*(xmax+2)];
	int *grids = new int[(ymax+2)*(xmax+2)];
	//int *directions = new int[4];
	//*directions={1,-1, xmax+2, -(xmax+2)};
	int directions[4]={1,-1, xmax+2, -(xmax+2)};
	//int randDirs[4]={1,-1, xmax+2, -(xmax+2)};	// new array to be randomized
	int *newOrder = new int[4];
	// v9:
	int *fireList = new int[(ymax)*(xmax)];
	unsigned int *fcounts = new unsigned int[(ymax)*(xmax)];
	unsigned short newFireElements=0;		// [x, x, x, x, x, x[nBurning], x, x, x, x[dnBurning], x, x, x, x[newFireElements] ]: old-fire, current flame-front, new elements.
	unsigned int totalFireCount=0;
	//
	bool doQuench = 0;
	//
	float frandImmune=0;
	int randImmune = 0;
	//
	//unsigned int rhoRocks = 10;	// of 100
	// initialize?
	srand(time(NULL));	// eventually, we have to be smarter about this and use independent random sets. see Gleb's random number gens.
	for (unsigned int i=0; i<(xmax+2)*(ymax+2); i++) {
		grids[i]=0;
		// seed the grid with some trees
		if (rand()%(xmax/2)==1 and i%(xmax+2)!=0 and i%(xmax+2)!=(xmax+1) and i>(xmax+2) and i<((xmax+2)*(ymax+1)) ) {
			grids[i]=1;
			nTreesOnGrid ++;
			};
		//if (i>(xmax+2)*(ymax+1)) printf("initializing grid %d\n", i);
		//yodapause();
		};
	//printf("random grid established...\n");
	//printGrid(&grids[0], 1, xmax, ymax);
	//
	char DB[]="ForestFire";
	char HOST[]="localhost";
	char USER[]="myoder";
	char PASSWORD[]="yoda";
	mysqlpp::Connection myconn(DB, HOST, USER, PASSWORD);
	mysqlpp::Query myquery=myconn.query();
	//mysqlpp::Result res1;
	mysqlpp::StoreQueryResult res1;
	int intKey;
		
	//unsigned int fcounts[xmax*ymax];
		for (unsigned int i=0; i<xmax*ymax; i++) {
			//fcounts[i]=0;
			//fireList[i]=0;
			*(fcounts + i)=0;
			*(fireList + i)=0;
			};
	if (doSQL==1 or doSQL==5 or doSQL==25) {	
		//
		// insert a new row for this sim-run:
		myquery.reset();
		printf("insert simprams.\n");
		myquery << "insert into ForestFire.SimPrams (`SimName`, `xmax`, `ymax`, `sparkInterval`, `burnAge`, `tmax`, `nRand`, `pImmune`, `kImmune`, `Comment`) values (%0q, %1q, %2q, %3q, %4q, %5q, %6q, %7q, %8q, %9q )";
		myquery.parse();
		// note: simIndex(auto-int) and dtTime (default TIMESTAMP) set automatically.
		//myquery.execute(simName.c_str(), simName.c_str(), xmax, ymax, fmatch, burnAge, tmax, randPlant, clustPlant, kmax, simPramComment.c_str());
		 myquery.execute(simName.c_str(), xmax, ymax, fmatch, 1, tmax, 1, pImmune, kImmune, simPramComment.c_str());
		//
		// now, get the integer key for this simulation:
		// note that this could be accomplished with one call (optimal if MySQL calls have high overhead)
		// by writing a SPROC on the MySQL side.
		// also see the mysql_insert_id() (C API) and LAST_INSERT_ID() (SQL) functions, by which we should be ablt to automatically retrieve the indexID.
		myquery.reset();
		printf("fetch simIndex.\n");
		myquery << "select max(simIndex) from ForestFire.SimPrams";
		myquery.parse();
		res1 = myquery.store(simName.c_str(), simName.c_str());
		intKey = res1.at(0).at(0);
		}; // doSQL
	//
	//printf("beginnn.\n");
	//for (unsigned int i=0; i<=tmax; i++) {
	unsigned int i=0;		// just so other bits don't break...
	while (totalFireCount<=tmax) {
		i++;		// this might overflow i guess. if so... figure out something.
		//if (doSQL==5 or doSQL==6) if(i%1000000 == 0) printf("%d million\n", i/1000000);
		if (doSQL==6) if(i%1000000 == 0) printf("%d million\n", i/1000000);

		if (doSQL==16) {
			if(i%100000 == 0) {
				// printf("%d million\n", i/1000000);
				aveRho=0;
				aveVol=0;
				for (unsigned int k=0; k<(xmax+2)*(ymax+2); k++) {
					if (*(grids+k)>0 and *(grids+k)<rockAge) {
						aveRho = aveRho + 1;
						aveVol = aveVol + *(grids+k);
						};
					};
				//printf("mils,\t Rho,\t Vol,\t %d, %f, %f\n", i/1000000, float(aveRho)/float(xmax*ymax), float(aveVol)/float(xmax*ymax));
				printf("%d, %f, %f\n", i/1000000, float(aveRho)/float(xmax*ymax), float(aveVol)/float(xmax*ymax));
				};
			};
		//
		// PLANT A TREE:
		// select a grid for tree planting:
			//thisX = rand()%xmax+1;
			//thisY = rand()%ymax+1;
			//thisSquare = &grids[0] + thisX + (xmax+2)*thisY;	// point to the current square...
			// for speed, select one random number; if we land on a rock, then just skip. there aren't many rocks.
			thisXY = xmax+3 + rand()%((xmax+2)*ymax-1);
			thisSquare = grids + thisXY;
			// if (*thisSquare<rockAge) {
			if (*thisSquare==0) {
				*thisSquare = *thisSquare + 1;
				nTreesOnGrid ++;
				};

	// we've planted a tree. do we throw a match?
		// we can do this two ways. we can trow a match every M steps or set a 
		// 1/M probability every time.
		// for now, we're being super simple; throw a match every 'fmatch' steps:
		// throw a match with 1/fmatch probability. generate a random number beteen 1 and fmatch; each number appears with freq. 1/fmatch
		//ffmatch = float(i+1)/float(fmatch);
		//if (float(int(ffmatch))==ffmatch and i>xmax) {
		//if (rand()%((1+prefPlant)*fmatch)==1) {
		
		if (rand()%fmatch==1) {
			//yodapause();
			// throw a match.
			xFire = rand()%xmax+1;
			yFire = rand()%ymax+1;
			fireSquare = &grids[0] + xFire + (xmax+2)*yFire;
			//printf("match: (%d, %d) :: %d/%d\n", xFire, yFire, *fireSquare, *(&grids[0] + (xFire + (xmax+2)*yFire)));
			//yodapause();
			//
			//printf("now evaluate *fireSquare, etc. %d\n", *fireSquare);
			//if (getGridStatus(*fireSquare, i) >= burnAge and getGridStatus(*fireSquare, i) < rockAge) {
			if (*fireSquare >= burnAge and *fireSquare < rockAge) {				
				// initiate a new fire.
				// now, we have three places to test quench-immunity:
				// 1) after each new step of front propagation
				// 2) after each burning element is tested against its NN
				// 3) after each element is added.
				// when the sequence of testing is fully randomized, we can test at any level.
				//
				// use the list-method (see v9a comments at the top) to propagate the fire.
				//printf("set 0-grid...\n");
				//*fireSquare = -(*fireSquare);	// we could remove the square; we track the fire in a list (=0), but we want to be able to plot the grid...
				//*fireSquare=0;
				//printf("set fireSquare... %d, %d, %d: %d\n",xFire, yFire, xmax, (xFire + (xmax+2)*yFire));
				totalFireCount++;
				*fireSquare=-1;
				fireList[0]=(xFire + (xmax+2)*yFire);	// or should we use an array of addresses?
				//printf("set fireSquare done\n");
				//
				rFire = 1;
				dnBurning = 1;
				nBurning = 0;
				newFireElements=0;
				//
				//int yFireMin = int(yodacode::greaterOf((yFire-rFire), 1));	// we always start with a 1 squar boundary. we might, however, encounter the edges.
				//int yFireMax = int(yodacode::lesserOf((yFire+rFire), float(ymax)));
				//int xFireMin = int(yodacode::greaterOf(float(xFire-rFire), 1));
				//int xFireMax = int(yodacode::lesserOf(float(xFire+rFire), float(xmax)));
				//
				//printf("fire range: %d, %d, %d, %d\n", yFireMin, yFireMax, xFireMin, xFireMax);
				//printf("preplot\n.");
				//
				//plotGrid(&grids[0],i, xmax, ymax);
				if (doSQL==0) {
					printGrid(&grids[0], i, xmax, ymax);
					};
				//while (dnBurning > 0) {
				doQuench = 0;
				//nFireSteps=0;	// steps fire has propagated, max dist/radius from flash-point. effectively time it's been burning.
				//printf("fire started at %d. now propagate.\n", xFire + (xmax+2)*yFire);
				while (dnBurning > 0 and doQuench==0) {
					//dnBurning=0;
					// evaluate neighbors of current burn front (nBurning-1 < i < (nBurning-1)+dnBurning
					unsigned int fireIndex=nBurning;
					//unsigned int newFireIndex=0;
					unsigned int currentElementIndex;
					//printf("fire front burning. fireIndex=%d\n", fireIndex);
					int * randomFireSequence = new int[dnBurning];
					int * testSeq = new int[dnBurning];
					for (int itest=0; itest<dnBurning; itest++) {
						*(testSeq + itest) = itest;
						}
					scrambleList(testSeq, randomFireSequence, dnBurning);
					delete [] testSeq;
					//if (dnBurning>1) randomSequence(randomFireSequence, dnBurning);	// randomize order in which we evalueate fire propagation.
					//for (int ilist=0; ilist<dnBurning; ilist++) {
					//	printf("randomSequence[%d]=%d\n", ilist, randomFireSequence[ilist]);
					//	};
					//
					while (fireIndex < (nBurning+dnBurning) and doQuench==0) {
						//newFireIndex=fireIndex-nBurning;
						currentElementIndex=nBurning+randomFireSequence[fireIndex-nBurning];	// this is long-winded because i'm building it off the simpler non-randomized model.
						//printf("fire index: %d (%d, %d, %d, %d)\n", fireIndex-nBurning, fireIndex, nBurning, dnBurning, currentElementIndex);
						//printf("failing here? %d, %d, %d\n", nBurning, dnBurning, fireIndex-nBurning);
					
						//currentElementIndex=nBurning+randomFireSequence[fireIndex-nBurning];
					//	printf("nope. ");
						
						
						// check for fire:
						// to maintain symmetry, randomize directions:
						// randDirs
						//scrambleList(directions, randDirs, 4);
						//int ordr[4]={0,1,2,3};
						//int newOrder[4];
						randomSequence(newOrder,4);
						//scrambleList(ordr, newOrder, 4);	// i think this is killing the random number generator.
						//printf("newOrder: %d, %d, %d, %d\n" , newOrder[0], newOrder[1],newOrder[2],newOrder[3]);
						
						for (int idir=0; idir<4; idir++) {
							// note: this loop format may facilitate randomization of direction later on...
							// nothing randomized:
							/*
							// I.
							if (grids[fireList[fireIndex] + directions[idir]]==1) {
								grids[fireList[fireIndex] + directions[idir]]=-1;
								fireList[nBurning + dnBurning + newFireElements]=fireList[fireIndex]+directions[idir];
								newFireElements++;
								};
							*/
							// order of each element (NN) randomized:
							/*
							// II.
							if (grids[fireList[fireIndex] + directions[newOrder[idir]]]==1) {
								grids[fireList[fireIndex] + directions[newOrder[idir]]]=-1;
								fireList[nBurning + dnBurning + newFireElements]=fireList[fireIndex]+directions[newOrder[idir]];
								newFireElements++;
								};
							*/
							// III.
							// each element (NN) and order of flame-front randomized:
							//printf("currentElement: %d\n", currentElementIndex);
							//printf("grid index: %d, %d, %d\n" , fireList[currentElementIndex], directions[newOrder[idir]], newOrder[idir]);
							//printf("segmentation fault test: grid-val (%d)\n", grids[fireList[currentElementIndex] + directions[newOrder[idir]]]);
							if (grids[fireList[currentElementIndex] + directions[newOrder[idir]]]==1) {
								//
								// add an entry to fireList. at the end of fireList [nBurning+dnBurning+newFireElements], add the fire location value,
								// fireList[currentElementIndex] + direction[]
								if (doQuench==0) {
									grids[fireList[currentElementIndex] + directions[newOrder[idir]]]=-1;
									fireList[nBurning + dnBurning + newFireElements]=fireList[currentElementIndex]+directions[newOrder[idir]];
									newFireElements++;
									};
								//if (immCode[2]=="1") {
								// so, do we do this before or after we evaluate the element? by doing this after we propagate the first step (so
								// fires are always k>1; alternatively we could use 1/(k+1)^p), we can use Pimmune>1 .
								if (doImFireElement) {
									// evaluate immunity (as each new element burns):
									//if (testQuench((nBurning+dnBurning+newFireElements), pImmune, kImmune)) {
									randImmune = rand()%RAND_MAX;
									frandImmune = float(randImmune)/RAND_MAX;
									if (frandImmune < (pImmune/pow(float(nBurning+dnBurning+newFireElements), kImmune)) ) {
										idir=4;
										doQuench=1;
										
										//printf("fire quenched during element-propagation: %d/%d\n", nBurning+dnBurning+newFireElements, fireIndex+1);
										//printGrid(&grids[0], i, xmax, ymax);
										//continue;
										};
									};
								};
							//
							// MFI (after each element is tested to the fire). this is only allowed at this step for type III propagation (above). if we apply immunity
							// as each element is added and elements are added in some geometrical sequence (aka, around the fire-front), we break the symmetry and break
							// SOC between integer values of L^2. by itself, using the list method (in particular when we randomize direction) might fix this problem,
							// since it breakes down the spiral geometry of our former concentric square propagation.
								
							};
						fireIndex++;

						// evaluate immunity (as each burning (fire-front) element propagates):
						//if (testQuench((nBurning+dnBurning+newFireElements), pImmune, kImmune)) {
						//if (immCode[1]=="1") {
						if (doImFlameFront) {
							randImmune = rand()%RAND_MAX;
							frandImmune = float(randImmune)/RAND_MAX;
							if (frandImmune < (pImmune/pow(float(nBurning+dnBurning+newFireElements), kImmune)) ) {
								//printf("quenched a fire at k=%d, Pq=%f/%f\n", (nBurning+dnBurning+newFireElements), pImmune/pow((nBurning+dnBurning+newFireElements), kImmune), frandImmune);
								doQuench=1;
								};
							};
					 	//
						//
						
						};
					// this round of propagation is over (new elements have propagated to NN).
					nBurning = nBurning + dnBurning;
					dnBurning=newFireElements;
					newFireElements=0;
					delete [] randomFireSequence;
					//
					// evaluate immunity (after each full propagation step):
					//if (immCode[0]=="1") {
					if (doImPrim) {
						// at this point, the first step of propagation has occurred, so nominally we can use pImmune>1.
						// arguably, this creates a new characteristic size; maybe the omori-type immunity is a better idea?
						//if (testQuench((nBurning+dnBurning+newFireElements), pImmune, kImmune)) {
						randImmune = rand()%RAND_MAX;
						frandImmune = float(randImmune)/RAND_MAX;
						if (frandImmune < (pImmune/pow(float(nBurning+dnBurning+newFireElements), kImmune)) ) {
						//if (frandImmune < (pImmune/(1+float(nBurning+dnBurning+newFireElements)/kImmune) ) ){
							//idir=4;
							doQuench=1;
							};
						};
					//printGrid(&grids[0], i, xmax, ymax);
					// g1.plot_xy(vfireX, vfireY, "");
					};	// end fire still burining
				//
				// fire is over:
				nFires++;
				nBurnedTotal = nBurnedTotal + nBurning;
				nTreesOnGrid = nTreesOnGrid-nBurning;
				//printf("fire over; %d burned.\n", nBurning);
				fcounts[nBurning-1]++;
				// printf("fcounts[%d]: %d\n", nBurning-1, fcounts[nBurning-1]);
				//plotGrid(&grids[0], xmax, ymax);
				//printGrid(&grids[0], i, xmax, ymax);
				if (doSQL==0) {
					printGrid(&grids[0], i, xmax, ymax);
					};
				// write fire to MySQL:
				if (doSQL==1) {
					// printf("fire size, nFires, totalBurned: (%d) (%d) (%d)\n", nBurning, nFires, nBurnedTotal);
					myquery.reset();
					myquery << "insert into ForestFire.ForestFires (simIndex, t, xSpark, ySpark, nBurned, nTrees) values (%0q, %1q, %2q, %3q, %4q, %5q) ";
					myquery.parse();
					myquery.execute(intKey, i, xFire, yFire, nBurning, nTreesOnGrid);
					//yodapause();
					};
				if (doSQL==3) {
					printf("fire at time %d\n", i);
					if (nBurning>=xmax/5) plotGrid (&grids[0], i, xmax, ymax, burnPropAge);
					};
				if (doSQL==4) {
					if (nBurning>=xmax/5) plotGridImg (&grids[0], i, xmax, ymax, burnPropAge);
					};
				//
				// fires finished burning; extinguish:
				unsigned int icleanup=0;
				while (fireList[icleanup]!=0) {
				//while (icleanup<nBurning+dnBurning+newFireElements){
				//while (icleanup<(xmax*ymax)){
					grids[fireList[icleanup]]=0;
					fireList[icleanup]=0;
					icleanup++;
					};
				nBurning = 0;
				dnBurning=0;
				newFireElements=0;
				//printGrid(&grids[0], i, xmax, ymax);
				//fireIndex=0;
				}; //else printf("no tree at match point.\n");	// if match -> tree...
			}; // if match-time

		// do we initialize with 0?
		//printf("ary element 0,i: %d", grids[0][i]);
		};	// end sim-steps.

	// end simulation.
	//printf("doSQL: %d\n", doSQL);
	// doSQL's:
	// 0: 'print-grid" fires
	// 1: full SQL: insert each forest fire data-set into ForestFires
	// 2: print summary to screen. use this for direct gnuplot calls, " plot '<./ffire4...'" 
	// 3: Print each fire to screen; "plotGrid" each fire nBurning>(25) print summary to screen at end
	// 4: plotGridImg each fire nBurning>(20); print summary to screen,
	// 5: SQL: insert just summary data to SQL; prints progress by million (will screw up plotting)
	// 6: report summary, progress by million.
	// 11: return to standard-output the last grid in full. use to make an image of the final grid.
	//
	// for super long runs (10^9 steps), it looks like the mysql connection times out, so all is lost.
	// renew the connection. 
	//
//	if (myconn.connected()==0) myconn.connect(DB, HOST, USER, PASSWORD);
	mysqlpp::Connection newconn(DB, HOST, USER, PASSWORD);
	mysqlpp::Query newquery=myconn.query();
	//mysqlpp::Result res1;

	//mysqlpp::Query myquery=myconn.query();
	//mysqlpp::Result res1;
	// end-o-run summaries (print):
	
	//printf("xmax*ymax = %d; %d, %d\n", xmax*ymax, ymax, xmax);
	if (doSQL==2  or doSQL==25 or doSQL==3 or doSQL==4 or doSQL==6) {
		//printf("dosql=2 or something. we should get a summary.");
		for (unsigned int i=0; i<(xmax*ymax); i++) {
			if (fcounts[i]!=0) {
				printf("%d\t%d\n", i+1, fcounts[i]);
				//printf("%d\t%d\n", i+1, i);
				//printf("%d,\t%d\n", i+1, fcounts[i]);
				}
			else {
				//printf("finished.\nfire size, nFires, totalBurned: (%d) (%d) (%d)\n", nBurning, nFires, nBurnedTotal);
				};
			};
		};
	//printf("moving past dosql2\n");
	if (doSQL==5 or doSQL==25 ) { // no plots, just a summary -> SQL
		//
		for (unsigned int i=0; i<(xmax*ymax); i++) {
			// if (fcounts[i]!=0) printf("%d\t%d\n", i+1, fcounts[i]);
		//	printf ("sql bits: %d, %d, %d, %d\n", intKey, tmax, i+1, fcounts[i]);
			newquery.reset();
			newquery << "insert into ffcounts (simIndex, tmax, nBurned, nEvents) values (%0q, %1q, %2q, %3q)";
			newquery.parse();
			newquery.execute(intKey, tmax, i+1, fcounts[i]);
			//printf("%d,\t%d\n", i+1, fcounts[i]);
			};				
		};
	//printf("moving past dosql5,25\n");
	// return the final grid in full and give an average density at the end...?
	if (doSQL==11) {
		for (unsigned int i=0; i<(xmax+2)*(ymax+2); i++) {
			printf ("%d,\t%d,\t%d\n", i-int(i/(xmax+2))*(xmax+2), i/(xmax+2), getGridStatus(*(grids+i), tmax));
			};
		};
	//g1.reset_plot();
	//g1.plot_xyz(vx, vy, vGridStat, "xyz plot of TreesPlanted");

	//yodacode::yodapause();
	//
	// clean up memory?
	delete [] grids;
	delete [] fireList;
	delete [] fcounts;
	//delete [] directions;
	return 0;
	//return &grids[0];
	};
Esempio n. 4
0
void ProcessEquiSpacedOutput::SetupEquiSpacedField(void)
{

    if(m_f->m_verbose)
    {
        cout << "Interpolating fields to equispaced" << endl;
    }

    int coordim  = m_f->m_exp[0]->GetCoordim(0);
    int shapedim = m_f->m_exp[0]->GetExp(0)->GetShapeDimension();
    int npts     = m_f->m_exp[0]->GetTotPoints();
    Array<OneD, Array<OneD, NekDouble> > coords(3);

    int nel = m_f->m_exp[0]->GetExpSize();

    // set up the number of points in each element
    int newpoints;
    int newtotpoints = 0;

    Array<OneD,int> conn;
    int prevNcoeffs = 0;
    int prevNpoints = 0;
    int cnt = 0;

    // identify face 1 connectivity for prisms
    map<int,StdRegions::Orientation > face0orient;
    set<int> prismorient;
    LocalRegions::ExpansionSharedPtr e;

    // prepare PtsField
    vector<std::string> fieldNames;
    vector<int> ppe;
    vector<Array<OneD, int> > ptsConn;
    int nfields;

    for(int i = 0; i < nel; ++i)
    {
        e = m_f->m_exp[0]->GetExp(i);
        if(e->DetShapeType() == LibUtilities::ePrism)
        {
            StdRegions::Orientation forient = e->GetForient(0);
            int fid = e->GetGeom()->GetFid(0);
            if(face0orient.count(fid))
            { // face 1 meeting face 1 so reverse this id
                prismorient.insert(i);
            }
            else
            {
                // just store if Dir 1 is fwd or bwd
                if((forient == StdRegions::eDir1BwdDir1_Dir2FwdDir2) ||
                   (forient == StdRegions::eDir1BwdDir1_Dir2BwdDir2) ||
                   (forient == StdRegions::eDir1BwdDir2_Dir2FwdDir1) ||
                   (forient == StdRegions::eDir1BwdDir2_Dir2BwdDir1))
                {
                    face0orient[fid] = StdRegions::eBwd;
                }
                else
                {
                    face0orient[fid] = StdRegions::eFwd;
                }
            }
        }
    }

    for(int i = 0; i < nel; ++i)
    {
        e = m_f->m_exp[0]->GetExp(i);
        if(e->DetShapeType() == LibUtilities::ePrism)
        {
            int fid = e->GetGeom()->GetFid(2);
            // check to see if face 2 meets face 1
            if(face0orient.count(fid))
            {
                // check to see how face 2 is orientated
                StdRegions::Orientation forient2 = e->GetForient(2);
                StdRegions::Orientation forient0 = face0orient[fid];

                // If dir 1 or forient2 is bwd then check agains
                // face 1 value
                if((forient2 == StdRegions::eDir1BwdDir1_Dir2FwdDir2) ||
                   (forient2 == StdRegions::eDir1BwdDir1_Dir2BwdDir2) ||
                   (forient2 == StdRegions::eDir1BwdDir2_Dir2FwdDir1) ||
                   (forient2 == StdRegions::eDir1BwdDir2_Dir2BwdDir1))
                {
                    if(forient0 == StdRegions::eFwd)
                    {
                        prismorient.insert(i);
                    }
                }
                else
                {
                    if(forient0 == StdRegions::eBwd)
                    {
                        prismorient.insert(i);
                    }
                }
            }
        }
    }

    for(int i = 0; i < nel; ++i)
    {
        e = m_f->m_exp[0]->GetExp(i);
        if(m_config["tetonly"].m_beenSet)
        {
            if(m_f->m_exp[0]->GetExp(i)->DetShapeType() !=
                    LibUtilities::eTetrahedron)
            {
                continue;
            }
        }

        ppe.push_back(newpoints);
        newtotpoints += newpoints;

        switch(e->DetShapeType())
        {
        case LibUtilities::eSegment:
            {
                int npoints0 = e->GetBasis(0)->GetNumPoints();

                newpoints = LibUtilities::StdSegData::
                                    getNumberOfCoefficients(npoints0);
            }
            break;
        case LibUtilities::eTriangle:
            {
                int np0 = e->GetBasis(0)->GetNumPoints();
                int np1 = e->GetBasis(1)->GetNumPoints();
                int np = max(np0,np1);
                newpoints = LibUtilities::StdTriData::
                                    getNumberOfCoefficients(np,np);
            }
            break;
        case LibUtilities::eQuadrilateral:
            {
                int np0 = e->GetBasis(0)->GetNumPoints();
                int np1 = e->GetBasis(1)->GetNumPoints();
                int np = max(np0,np1);

                newpoints = LibUtilities::StdQuadData::
                                    getNumberOfCoefficients(np,np);
            }
            break;
        case LibUtilities::eTetrahedron:
            {
                int np0 = e->GetBasis(0)->GetNumPoints();
                int np1 = e->GetBasis(1)->GetNumPoints();
                int np2 = e->GetBasis(2)->GetNumPoints();
                int np = max(np0,max(np1,np2));

                newpoints = LibUtilities::StdTetData::
                                    getNumberOfCoefficients(np,np,np);
            }
            break;
        case LibUtilities::ePrism:
            {
                int np0 = e->GetBasis(0)->GetNumPoints();
                int np1 = e->GetBasis(1)->GetNumPoints();
                int np2 = e->GetBasis(2)->GetNumPoints();
                int np = max(np0,max(np1,np2));

                newpoints = LibUtilities::StdPrismData::
                                    getNumberOfCoefficients(np,np,np);
            }
            break;
        case LibUtilities::ePyramid:
            {
                int np0 = e->GetBasis(0)->GetNumPoints();
                int np1 = e->GetBasis(1)->GetNumPoints();
                int np2 = e->GetBasis(2)->GetNumPoints();
                int np = max(np0,max(np1,np2));

                newpoints = LibUtilities::StdPyrData::
                                    getNumberOfCoefficients(np,np,np);
            }
            break;
        case LibUtilities::eHexahedron:
            {
                int np0 = e->GetBasis(0)->GetNumPoints();
                int np1 = e->GetBasis(1)->GetNumPoints();
                int np2 = e->GetBasis(2)->GetNumPoints();
                int np = max(np0,max(np1,np2));

                newpoints = LibUtilities::StdPyrData::
                                    getNumberOfCoefficients(np,np,np);
            }
            break;
        default:
            {
                ASSERTL0(false,"Points not known");
            }
        }

        if(e->DetShapeType() == LibUtilities::ePrism)
        {
            bool standard = true;

            if(prismorient.count(i))
            {
                standard = false; // reverse direction
            }

            e->GetSimplexEquiSpacedConnectivity(conn,standard);
        }
        else
        {

            if((prevNcoeffs != e->GetNcoeffs()) ||
               (prevNpoints != e->GetTotPoints()))
            {
                prevNcoeffs = e->GetNcoeffs();
                prevNpoints = e->GetTotPoints();

                e->GetSimplexEquiSpacedConnectivity(conn);
            }
        }
        Array<OneD, int> newconn(conn.num_elements());
        for(int j = 0; j < conn.num_elements(); ++j)
        {
            newconn[j] = conn[j] + cnt;
        }

        ptsConn.push_back(newconn);
        cnt += newpoints;
    }

    if(m_f->m_fielddef.size())
    {
        nfields = m_f->m_exp.size();
    }
    else // just the mesh points
    {
        nfields = 0;
    }

    Array<OneD, Array<OneD, NekDouble> > pts(nfields + coordim);

    for(int i = 0; i < nfields + coordim; ++i)
    {
        pts[i] = Array<OneD, NekDouble>(newtotpoints);
    }

    // Interpolate coordinates
    for(int i = 0; i < coordim; ++i)
    {
        coords[i] = Array<OneD, NekDouble>(npts);
    }

    for(int i = coordim; i < 3; ++i)
    {
        coords[i] = NullNekDouble1DArray;
    }

    m_f->m_exp[0]->GetCoords(coords[0],coords[1],coords[2]);

    int nq1 = m_f->m_exp[0]->GetTotPoints();

    Array<OneD, NekDouble> x1(nq1);
    Array<OneD, NekDouble> y1(nq1);
    Array<OneD, NekDouble> z1(nq1);

    m_f->m_exp[0]->GetCoords(x1, y1, z1);


    Array<OneD, NekDouble> tmp;

    for(int n = 0; n < coordim; ++n)
    {
        cnt = 0;
        int cnt1 = 0;
        for(int i = 0; i < nel; ++i)
        {
            m_f->m_exp[0]->GetExp(i)->PhysInterpToSimplexEquiSpaced(
                                        coords[n] + cnt,
                                        tmp = pts[n] + cnt1);
            cnt1 += ppe[i];
            cnt  += m_f->m_exp[0]->GetExp(i)->GetTotPoints();
        }
    }

    if(m_f->m_fielddef.size())
    {
        ASSERTL0(m_f->m_fielddef[0]->m_fields.size() == m_f->m_exp.size(),
                 "More expansion defined than fields");

        for(int n = 0; n < m_f->m_exp.size(); ++n)
        {
            cnt = 0;
            int cnt1 = 0;

            if(m_config["modalenergy"].m_beenSet)
            {
                Array<OneD, const NekDouble> phys = m_f->m_exp[n]->GetPhys();
                for(int i = 0; i < nel; ++i)
                {
                    GenOrthoModes(i,phys+cnt,tmp = pts[coordim + n] + cnt1);
                    cnt1 += ppe[i];
                    cnt  += m_f->m_exp[0]->GetExp(i)->GetTotPoints();
                }
            }
            else
            {
                Array<OneD, const NekDouble> phys = m_f->m_exp[n]->GetPhys();
                for(int i = 0; i < nel; ++i)
                {
                    m_f->m_exp[0]->GetExp(i)->PhysInterpToSimplexEquiSpaced(
                            phys + cnt,
                            tmp = pts[coordim + n] + cnt1);
                    cnt1 += ppe[i];
                    cnt  += m_f->m_exp[0]->GetExp(i)->GetTotPoints();
                }
            }

            // Set up Variable string.
            fieldNames.push_back(m_f->m_fielddef[0]->m_fields[n]);
        }
    }

    m_f->m_fieldPts = MemoryManager<LibUtilities::PtsField>::AllocateSharedPtr(coordim, fieldNames, pts);
    if (shapedim == 2)
    {
        m_f->m_fieldPts->SetPtsType(LibUtilities::ePtsTriBlock);
    }
    else if (shapedim == 3)
    {
        m_f->m_fieldPts->SetPtsType(LibUtilities::ePtsTetBlock);
    }
    m_f->m_fieldPts->SetConnectivity(ptsConn);
}
//int doffire(unsigned tmax=1000000, unsigned short fmatch=200, unsigned int randPlant=1, unsigned int clustPlant=0, unsigned short burnAge=1, unsigned short burnPropAge=1, int rhoRocks=0, int doSQL=1, float pImmune=0, int nnnAge=0) {
int doffire(unsigned int tmax=1000000, unsigned int fmatch=125, int doSQL=2, float pImmune=0, float kImmune=1) {
	// burn toplolgy: do we nave nnn burning
//	if (nnnAge==0) nnnAge=54321;	// trees age>nnnAge will spread to next nearest neighbors. use "0" pram for no nnn connectivity; nothing should ever get this old.
	int aveRho = 0, aveVol=0;
	int burnAge=1, burnPropAge=1;
	int nTreesOnGrid=0;
	int nFireSteps=0;	// the number of steps the fire has propagated (the radius, or more correctly the maximum distance of a burning element from the flashpoint)

	std::string simName("ForestFire5c");
	std::string simPramComment("single-pass fire propagation/immunity evaluation");
	//
	unsigned short rFire = 1;
	unsigned int nBurning = 1;
	unsigned short dnBurning = 1;
	int thisXY, xFire, yFire;
//	int thisStatus;
	int * thisSquare, * fireSquare;
	unsigned int nBurnedTotal=0, nFires=0;  // number of elements burning, new Elements burning...
	float aveTreeAge=0;
	//signed int grids[(ymax+2)*(xmax+2)];
	int *grids = new int[(ymax+2)*(xmax+2)];
	bool doQuench = 0;
	//
	float frandImmune=0;
	int randImmune = 0;
	//
	//unsigned int rhoRocks = 10;	// of 100
	// initialize?
	srand(time(NULL));	// eventually, we have to be smarter about this and use independent random sets. see Gleb's random number gens.
	for (unsigned int i=0; i<(xmax+2)*(ymax+2); i++) {
		grids[i]=0;
		// seed the grid with some trees
		if (rand()%(xmax/2)==1 and i%(xmax+2)!=0 and i%(xmax+2)!=(xmax+1) and i>(xmax+2) and i<((xmax+2)*(ymax+1)) ) {
			grids[i]=1;
			nTreesOnGrid ++;
			};
		//yodapause();
		};
	//printf("random grid established...\n");
	//printGrid(&grids[0], 1, xmax, ymax);
	//
	char DB[]="ForestFire";
	char HOST[]="localhost";
	char USER[]="myoder";
	char PASSWORD[]="yoda";
	mysqlpp::Connection myconn(DB, HOST, USER, PASSWORD);
	mysqlpp::Query myquery=myconn.query();
	//mysqlpp::Result res1;
	mysqlpp::StoreQueryResult res1;
	int intKey;
	unsigned int fcounts[xmax*ymax];
		for (unsigned int i=0; i<xmax*ymax; i++) {
			fcounts[i]=0;
			};
	if (doSQL==1 or doSQL==5 or doSQL==25) {	
		//
		// insert a new row for this sim-run:
		myquery.reset();
		printf("insert simprams.\n");
		myquery << "insert into ForestFire.SimPrams (`SimName`, `xmax`, `ymax`, `sparkInterval`, `burnAge`, `tmax`, `nRand`, `pImmune`, `kImmune`, `Comment`) values (%0q, %1q, %2q, %3q, %4q, %5q, %6q, %7q, %8q, %9q )";
		myquery.parse();
		// note: simIndex(auto-int) and dtTime (default TIMESTAMP) set automatically.
		//myquery.execute(simName.c_str(), simName.c_str(), xmax, ymax, fmatch, burnAge, tmax, randPlant, clustPlant, kmax, simPramComment.c_str());
		  myquery.execute(simName.c_str(), xmax, ymax, fmatch, 1, tmax, 1, pImmune, kImmune, simPramComment.c_str());
		//
		// now, get the integer key for this simulation:
		// note that this could be accomplished with one call (optimal if MySQL calls have high overhead)
		// by writing a SPROC on the MySQL side.
		// also see the mysql_insert_id() (C API) and LAST_INSERT_ID() (SQL) functions, by which we should be ablt to automatically retrieve the indexID.
		myquery.reset();
		printf("fetch simIndex.\n");
		myquery << "select max(simIndex) from ForestFire.SimPrams";
		myquery.parse();
		res1 = myquery.store(simName.c_str(), simName.c_str());
		intKey = res1.at(0).at(0);
		}; // doSQL
	//
	//printf("beginnn.\n");
	for (unsigned int i=0; i<=tmax; i++) {
		// here, i'm being sloppy with random numbers. really, we need four independent
		// random number generators for xTree, yTree, xMatch, yMatch
		// printf(" iteration %d\n", i);
		//
		//
		//if (doSQL==5 or doSQL==6) if(i%1000000 == 0) printf("%d million\n", i/1000000);
		if (doSQL==6) if(i%1000000 == 0) printf("%d million\n", i/1000000);

		if (doSQL==16) {
			if(i%100000 == 0) {
				// printf("%d million\n", i/1000000);
				aveRho=0;
				aveVol=0;
				for (unsigned int k=0; k<(xmax+2)*(ymax+2); k++) {
					if (*(grids+k)>0 and *(grids+k)<rockAge) {
						aveRho = aveRho + 1;
						aveVol = aveVol + *(grids+k);
						};
					};
				//printf("mils,\t Rho,\t Vol,\t %d, %f, %f\n", i/1000000, float(aveRho)/float(xmax*ymax), float(aveVol)/float(xmax*ymax));
				printf("%d, %f, %f\n", i/1000000, float(aveRho)/float(xmax*ymax), float(aveVol)/float(xmax*ymax));
				};
			};


		//
		// PLANT A TREE:
		// select a grid for tree planting:
			//thisX = rand()%xmax+1;
			//thisY = rand()%ymax+1;
			//thisSquare = &grids[0] + thisX + (xmax+2)*thisY;	// point to the current square...
			// for speed, select one random number; if we land on a rock, then just skip. there aren't many rocks.
			thisXY = xmax+3 + rand()%((xmax+2)*ymax-1);
			thisSquare = grids + thisXY;
			// if (*thisSquare<rockAge) {
			if (*thisSquare==0) {
				*thisSquare = *thisSquare + 1;
				nTreesOnGrid ++;
				};

	// we've planted a tree. do we throw a match?
		// we can do this two ways. we can trow a match every M steps or set a 
		// 1/M probability every time.
		// for now, we're being super simple; throw a match every 'fmatch' steps:
		// throw a match with 1/fmatch probability. generate a random number beteen 1 and fmatch; each number appears with freq. 1/fmatch
		//ffmatch = float(i+1)/float(fmatch);
		//if (float(int(ffmatch))==ffmatch and i>xmax) {
		//if (rand()%((1+prefPlant)*fmatch)==1) {
		
		if (rand()%fmatch==1) {
			//yodapause();
			// throw a match.
			xFire = rand()%xmax+1;
			yFire = rand()%ymax+1;
			fireSquare = &grids[0] + xFire + (xmax+2)*yFire;
			//printf("match: (%d, %d) :: %d\n", xFire, yFire, *fireSquare);
			//yodapause();
			//
			//if (getGridStatus(*fireSquare, i) >= burnAge and getGridStatus(*fireSquare, i) < rockAge) {
			if (*fireSquare >= burnAge and *fireSquare < rockAge) {				
				// initiate a new fire.
				// start from the epicenter and work out in concentric rectangles (squares)
				// until there are no new fires.
				// note: we make two passes over each circle. for now, we assume all squares
				// continue to burn until the fire is over. this is a subtle consideration that
				// will not matter for simpler versions of the model, but if we introduce burn probabilities,
				// we will have to be more careful.
				// alternatively, we can scan the entire grid every time, but the above method will
				// save CPU time.
				//*fireSquare=-1;	// the fire-square starts burning
				*fireSquare=-(*fireSquare);	// the fire-square starts burning
				//
				rFire = 1;
				//nBurning = 1;
				dnBurning = 1;
				nBurning = dnBurning;
				//
				int yFireMin = int(yodacode::greaterOf((yFire-rFire), 1));	// we always start with a 1 squar boundary. we might, however, encounter the edges.
				int yFireMax = int(yodacode::lesserOf((yFire+rFire), float(ymax)));
				int xFireMin = int(yodacode::greaterOf(float(xFire-rFire), 1));
				int xFireMax = int(yodacode::lesserOf(float(xFire+rFire), float(xmax)));
				//printf("fire range: %d, %d, %d, %d\n", yFireMin, yFireMax, xFireMin, xFireMax);
				//printf("preplot\n.");
				//
				//plotGrid(&grids[0],i, xmax, ymax);
				if (doSQL==0) {
					printGrid(&grids[0], i, xmax, ymax);
					};
				//while (dnBurning > 0) {
				doQuench = 0;
				nFireSteps=0;	// steps fire has propagated, max dist/radius from flash-point. effectively time it's been burning.
				while (dnBurning > 0 and doQuench==0) {
					dnBurning=0;
					nFireSteps++;
					// 30 june 2008 yoder:
					//for (char doTwice = 0; doTwice <=1; doTwice++) {	// "char" is a 1 byte integer. we could also use a boolean to count to 2.
					for (char doTwice = 0; doTwice <1; doTwice++) {	// retrospectively, we don't need to do two loops since we do the whole area. also, this creates
																					// inconsistency when evaluating immunity.
																					// note: 5c data before 30 june uses the "doTwice" algorithm. different immunity effect?
					for (int iy = (yFireMin); iy <= (yFireMax); iy++) {
						//if (doQuench==1) break;
						for (int ix = (xFireMin); ix <= (xFireMax); ix++) {
							//if (doQuench==1) break;	// this is a safety measure. the loop should be otherwise killed by setting ix>xFireMax
							//
							// note this loops down then across...
							// if a neighbor is burning and the element is old enough and the element is not alread burning
							// (note by using burning -> -Age
							// also note: Gelb is right. a recursive approach is better.
							// printf("try-burn: %d, %d\n", ix, iy);
							//plotGrid(&grids[0], xmax, ymax);
							randImmune = rand()%1000;
							frandImmune = float(randImmune)/1000;
							//printf("frandImmune: %f\n", frandImmune);
							//yodapause();
							//
							int * centerGrid = &grids[0] + ix + (xmax+2)*iy;
							//
							int cStat, uStat, dStat, lStat, rStat;
						//	int ulStat, urStat, llStat, lrStat;	// diagonal elements.
						//	cStat = getGridStatus(*(centerGrid), i);
							//
						//	uStat = getGridStatus(*(centerGrid + (xmax+2)), i);
						//	dStat = getGridStatus(*(centerGrid - (xmax+2)), i);
						//	lStat = getGridStatus(*(centerGrid - 1), i);
						//	rStat = getGridStatus(*(centerGrid + 1), i);
						//	cStat = getGridStatus(*(centerGrid), i);
							//
							cStat = *(centerGrid);
							//
							uStat = *(centerGrid + (xmax+2));
							dStat = *(centerGrid - (xmax+2));
							lStat = *(centerGrid - 1);
							rStat = *(centerGrid + 1);
							//
							// diagonal elements:
						//	ulStat = getGridStatus(*(centerGrid + (xmax+2) - 1), i);
						//	urStat = getGridStatus(*(centerGrid + (xmax+2) + 1), i);
						//	llStat = getGridStatus(*(centerGrid - (xmax+2) - 1), i);
						//	lrStat = getGridStatus(*(centerGrid - (xmax+2) + 1), i);
							//yodapause();
							//if (grids[iy][ix] >= burnAge && (grids[ix+1][iy]==-1 || grids[ix-1][iy]==-1 || grids[ix][iy+1]==-1 || grids[ix][iy-1]==-1) ) {
							//printf(" checking: cg=%d, lg=%d, rg=%d, ug=%d, dg=%d, anyburn=%d\n", *centerGrid, *leftGrid, *rightGrid, *upGrid, *downGrid, (*leftGrid==-1 or *rightGrid==-1 or *upGrid==-1 or *downGrid==-1) );
							//if (*centerGrid >= burnAge and (*leftGrid==-1 or *rightGrid==-1 or *upGrid==-1 or *downGrid==-1)) {
							//if (*centerGrid >= burnAge and (*leftGrid<=-burnPropAge or *rightGrid<=-burnPropAge or *upGrid<=-burnPropAge or *downGrid<=-burnPropAge)) {
							//if (cStat >= burnAge and cStat < rockAge and (lStat<=-burnPropAge or rStat<=-burnPropAge or uStat<=-burnPropAge or dStat<=-burnPropAge)) {
							//
							// no immunity:
							//if (cStat >= burnAge and cStat < rockAge and (lStat<=-burnPropAge or rStat<=-burnPropAge or uStat<=-burnPropAge or dStat<=-burnPropAge)) {
							// local immunity:
							//printf("immune factor: %f, %f\n", pImmune, frandImmune);
							//if (frandImmune > pImmune and cStat >= burnAge and cStat < rockAge and (lStat<=-burnPropAge or rStat<=-burnPropAge or uStat<=-burnPropAge or dStat<=-burnPropAge)) {
							// next nearest neighbors:
							/*	
							if (cStat >= burnAge and cStat < rockAge 
								and  ( (lStat<=-burnPropAge or rStat<=-burnPropAge or uStat<=-burnPropAge or dStat<=-burnPropAge)
									 or ( (ulStat<=-nnnAge or urStat<=-nnnAge  or llStat<=-nnnAge  or lrStat<=-nnnAge)
										 and (ulStat<=-burnPropAge or urStat<=-burnPropAge or llStat<=-burnPropAge  or lrStat<=-burnPropAge)
										 )
							 		)
								) {
							*/
							if (cStat >= burnAge and cStat < rockAge 
								and (lStat<=-burnPropAge or rStat<=-burnPropAge or uStat<=-burnPropAge or dStat<=-burnPropAge)
								and frandImmune>(pImmune/float(nBurning+dnBurning))) {
								// 5c1: we've added element level f(k) immunity to each element; no quenching.
								*centerGrid = -(*centerGrid);
								// age -> number of trees in that grid...
								dnBurning ++;
								//
								// 5c1: no quenching. immunity evaluated on an element-by-element basis above.
								// what if we evaluate immunity here? if quench, break the propagation loop. (can we break-break? how 'bout we just set the iterators over the max vals):
								// note: we've not yet updated nBurning, so use nBurning + dnBurning:
								//if (frandImmune < (pImmune/(1+(float(nBurning+dnBurning)/kImmune))) ) {
							//	if (frandImmune < (pImmune/float(nBurning+dnBurning)) ) {
							//		// this seems to give us some funny log-periodic behavior for small Pimmune.
							//		// the next thing to try is: evaluate Pquench as each element is burned, but mitigate the introduction of new geometry (aka, the loop around the fire) by,
							//		// when frandImmune fails (fire quenches), we set doQuench=1, but let the fire continue through its current perimeter. maybe we need to just start testing
							//		// each individual element for burn?
							//		doQuench=1;
							//		ix=xFireMax+1;
							//		iy=yFireMax+1;
							//		};
								// printf("[%d, %d] catches from [%d, %d]\n", ix, iy, xFire, yFire);
								};
							}; // ix
						}; // iy
						}; // doTwice	
						nBurning = nBurning + dnBurning;
						//
						// mean-field immunities:
						// normalize formulae to extinguish size1 fires with probability pImmune
						//
						// inverse linear type (becareful of x/0):
						// if (frandImmune < (1+(1/kImmune))*(pImmune/(1+(float(nBurning)/kImmune))) ) {
						// if (frandImmune < pImmune/(1+(float(nBurning-1)/kImmune)) ) {
						// exponential:
						// if (frandImmune < pImmune*exp(-kImmune*(nBurning-1)) ) doQuench=1;
						// power law:
						// if (frandImmune < pImmune*pow(nBurning, -kImmune)) {
						//printf("kImmune norm: 1 + (1/kImmune): %f\n", 1 + (1/kImmune));
						//
				////////////////////////
				// temporarily move immunity inside the prop-loop.		
						// IMMUNITY (note different functions we play with):
						// do we quenche the fire?
						// 1/nFireSteps:
						//if (frandImmune < (pImmune/nFireSteps) ) {		// this is dumb way to make this work. stick to k
						// omori-type:
				//		if (frandImmune < (pImmune/(1+(float(nBurning-1)/kImmune))) ) {
				//		// pure 1/k:
				//		//if (frandImmune < (pImmune*kImmune/nBurning) ) {
				//		//if (frandImmune < pow(pImmune,(float(nBurning)/5) )) {
				//			doQuench=1;
				//			//printf("quenched %d.\n", nBurning);
				//			//yodapause();
				//			};
				/////////////////////////
					//rFire++;
					xFireMin = int(yodacode::greaterOf(1, float(xFireMin-1)));
					xFireMax = int(yodacode::lesserOf(float(xmax), xFireMax+1));
					yFireMin = int(yodacode::greaterOf(1, float(yFireMin-1)));
					yFireMax = int(yodacode::lesserOf(float(ymax), yFireMax+1));
					// g1.plot_xy(vfireX, vfireY, "");
					};	// end fire still burining
				//
				// recursive method:
				// if (grids[xFire][yFire] >= burnAge) {
				//	burn(xFire, yFire);	// burn() will look up, down, right, left and call itself recursively. we have to do the "pass array address" bit though...
				//	};
				//
				nFires++;
				nBurnedTotal = nBurnedTotal + nBurning;
				nTreesOnGrid = nTreesOnGrid-nBurning;
				fcounts[nBurning-1]++;
			//	plotGrid(&grids[0], xmax, ymax);
				if (doSQL==0) {
					printGrid(&grids[0], i, xmax, ymax);
					};
				// write fire to MySQL:
				if (doSQL==1) {
					// printf("fire size, nFires, totalBurned: (%d) (%d) (%d)\n", nBurning, nFires, nBurnedTotal);
					myquery.reset();
					myquery << "insert into ForestFire.ForestFires (simIndex, t, xSpark, ySpark, nBurned, nTrees) values (%0q, %1q, %2q, %3q, %4q, %5q) ";
					myquery.parse();
					myquery.execute(intKey, i, xFire, yFire, nBurning, nTreesOnGrid);
					//yodapause();
					};
				if (doSQL==3) {
					printf("fire at time %d\n", i);
					if (nBurning>=xmax/5) plotGrid (&grids[0], i, xmax, ymax, burnPropAge);
					};
				if (doSQL==4) {
					if (nBurning>=xmax/5) plotGridImg (&grids[0], i, xmax, ymax, burnPropAge);
					};
				//
				// fires finished burning; extinguish:
				for (int iy = (yFireMin); iy <= (yFireMax); iy++) {
					for (int ix = (xFireMin); ix <= (xFireMax); ix++) {
						// &grids[0] + ix + (xmax+2)*iy
						if (grids[ix + (xmax+2)*iy] < 0) grids[ix + (xmax+2)*iy]=0;
						};
					};
				}; //else printf("no tree at match point.\n");	// if match -> tree...
			}; // if match-time

		// do we initialize with 0?
		//printf("ary element 0,i: %d", grids[0][i]);
		};	// end sim-steps.

	// end simulation.
	//printf("doSQL: %d\n", doSQL);
	// doSQL's:
	// 0: 'print-grid" fires
	// 1: full SQL: insert each forest fire data-set into ForestFires
	// 2: print summary to screen. use this for direct gnuplot calls, " plot '<./ffire4...'" 
	// 3: Print each fire to screen; "plotGrid" each fire nBurning>(25) print summary to screen at end
	// 4: plotGridImg each fire nBurning>(20); print summary to screen,
	// 5: SQL: insert just summary data to SQL; prints progress by million (will screw up plotting)
	// 6: report summary, progress by million.
	// 11: return to standard-output the last grid in full. use to make an image of the final grid.
	//
	// for super long runs (10^9 steps), it looks like the mysql connection times out, so all is lost.
	// renew the connection. 
	//
//	if (myconn.connected()==0) myconn.connect(DB, HOST, USER, PASSWORD);
	mysqlpp::Connection newconn(DB, HOST, USER, PASSWORD);
	mysqlpp::Query newquery=myconn.query();
	//mysqlpp::Result res1;

	//mysqlpp::Query myquery=myconn.query();
	//mysqlpp::Result res1;
	// end-o-run summaries (print):
	if (doSQL==2  or doSQL==25 or doSQL==3 or doSQL==4 or doSQL==6) {
		for (unsigned int i=0; i<(xmax*ymax); i++) {
			if (fcounts[i]!=0) printf("%d\t%d\n", i+1, fcounts[i]);
			//printf("%d,\t%d\n", i+1, fcounts[i]);
			};
		} else {
			//printf("finished.\nfire size, nFires, totalBurned: (%d) (%d) (%d)\n", nBurning, nFires, nBurnedTotal);
			};
	if (doSQL==5 or doSQL==25 ) { // no plots, just a summary -> SQL
		//
		for (unsigned int i=0; i<(xmax*ymax); i++) {
			// if (fcounts[i]!=0) printf("%d\t%d\n", i+1, fcounts[i]);
		//	printf ("sql bits: %d, %d, %d, %d\n", intKey, tmax, i+1, fcounts[i]);
			newquery.reset();
			newquery << "insert into ffcounts (simIndex, tmax, nBurned, nEvents) values (%0q, %1q, %2q, %3q)";
			newquery.parse();
			newquery.execute(intKey, tmax, i+1, fcounts[i]);
			//printf("%d,\t%d\n", i+1, fcounts[i]);
			};				
		};
	// return the final grid in full and give an average density at the end...?
	if (doSQL==11) {
		for (unsigned int i=0; i<(xmax+2)*(ymax+2); i++) {
			printf ("%d,\t%d,\t%d\n", i-int(i/(xmax+2))*(xmax+2), i/(xmax+2), getGridStatus(*(grids+i), tmax));
			};
		};
	//g1.reset_plot();
	//g1.plot_xyz(vx, vy, vGridStat, "xyz plot of TreesPlanted");

	//yodacode::yodapause();
	return 0;
	//return &grids[0];
	};