//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]; };
//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]; };
void MapView::Render() { // get new pose. pthread_mutex_lock(&filter->filter_CS); lastFramePoseSpeed = filter->getCurrentPoseSpeedAsVec(); // Note: this is maybe an old pose, but max. one frame old = 50ms = not noticable. pthread_mutex_unlock(&filter->filter_CS); if(clearTrail) { trailPoints.clear(); clearTrail = false; } // render bool addTrail; if(trailPoints.size() == 0) addTrail = true; else { TooN::Vector<3> distToLast = lastFramePoseSpeed.slice<0,3>() - trailPoints[trailPoints.size()-1].pointFilter; double d = distToLast[0]*distToLast[0] + distToLast[1]*distToLast[1]+distToLast[2]*distToLast[2]; addTrail = d > 0.1*0.1; } // the following complicated code is to save trail-points in ptam-scale, such that scale-reestimation will re-scale the drawn path. if(addTrail) { if(ptamWrapper->PTAMStatus == ptamWrapper->PTAM_BEST || ptamWrapper->PTAMStatus == ptamWrapper->PTAM_TOOKKF || ptamWrapper->PTAMStatus == ptamWrapper->PTAM_GOOD) { if(ptamWrapper->PTAMInitializedClock != 0 && getMS() - ptamWrapper->PTAMInitializedClock > 200) { TooN::Vector<3> PTAMScales = filter->getCurrentScales(); TooN::Vector<3> PTAMOffsets = filter->getCurrentOffsets().slice<0,3>(); TooN::Vector<3> ptamPointPos = lastFramePoseSpeed.slice<0,3>(); ptamPointPos -= PTAMOffsets; ptamPointPos /= PTAMScales[0]; trailPoints.push_back(TrailPoint( lastFramePoseSpeed.slice<0,3>(), ptamPointPos )); } } else if(ptamWrapper->PTAMStatus == ptamWrapper->PTAM_LOST || ptamWrapper->PTAMStatus == ptamWrapper->PTAM_FALSEPOSITIVE) { if(ptamWrapper->PTAMInitializedClock != 0 && getMS() - ptamWrapper->PTAMInitializedClock > 200) { TooN::Vector<3> PTAMScales = filter->getCurrentScales(); TooN::Vector<3> PTAMOffsets = filter->getCurrentOffsets().slice<0,3>(); TooN::Vector<3> ptamPointPos = lastFramePoseSpeed.slice<0,3>(); ptamPointPos -= PTAMOffsets; ptamPointPos /= PTAMScales[0]; trailPoints.push_back(TrailPoint( lastFramePoseSpeed.slice<0,3>(), ptamPointPos )); } } else { trailPoints.push_back(TrailPoint( lastFramePoseSpeed.slice<0,3>() )); } } if(resetMapViewFlag) { resetMapView(); resetMapViewFlag = false; } // get lineWidthFactor lineWidthFactor = sqrt((float)(myGLWindow->size()[0] * myGLWindow->size()[1] / (640*480))); plotGrid(); pthread_mutex_lock(&ptamWrapper->shallowMapCS); std::vector<tse3>* kfl = &(ptamWrapper->keyFramesTransformed); // draw keyframes for(unsigned int i=0;i<kfl->size();i++) { plotCam((*kfl)[i],false,2,0.04f,1); } // draw trail drawTrail(); // draw keypoints plotMapPoints(); pthread_mutex_unlock(&ptamWrapper->shallowMapCS); // draw predicted cam // real in opaque predConvert->setPosRPY(lastFramePoseSpeed[0], lastFramePoseSpeed[1], lastFramePoseSpeed[2], lastFramePoseSpeed[3], lastFramePoseSpeed[4], lastFramePoseSpeed[5]); plotCam(predConvert->droneToGlobal,true,5.0f,0.2f,1); // --------------------- make msg ------------------------------ msg = ""; TooN::Vector<6> of = filter->getCurrentOffsets(); TooN::Vector<3> sc = filter->getCurrentScales(); if(drawUI == UI_DEBUG) { snprintf(charBuf,1000,"Pose: "); snprintf(charBuf+10,800, "x: %.2f ",lastFramePoseSpeed[0]); snprintf(charBuf+20,800, "y: %.2f ",lastFramePoseSpeed[1]); snprintf(charBuf+30,800, "z: %.2f ",lastFramePoseSpeed[2]); snprintf(charBuf+40,800, "r: %.2f ",lastFramePoseSpeed[3]); snprintf(charBuf+50,800, "p: %.2f ",lastFramePoseSpeed[4]); snprintf(charBuf+60,800, "y: %.2f ",lastFramePoseSpeed[5]); snprintf(charBuf+70,800, "vx: %.2f ",lastFramePoseSpeed[6]); snprintf(charBuf+80,800, "vy: %.2f ",lastFramePoseSpeed[7]); snprintf(charBuf+90,800, "vz: %.2f ",lastFramePoseSpeed[8]); snprintf(charBuf+100,800, "vy: %.2f",lastFramePoseSpeed[9]); msg += charBuf; snprintf(charBuf,1000,"\nSync: "); snprintf(charBuf+10,800, "ox: %.2f ",of[0]); snprintf(charBuf+20,800, "oy: %.2f ",of[1]); snprintf(charBuf+30,800, "oz: %.2f ",of[2]); snprintf(charBuf+40,800, "or: %.2f ",of[3]); snprintf(charBuf+50,800, "op: %.2f ",of[4]); snprintf(charBuf+60,800, "oy: %.2f ",of[5]); snprintf(charBuf+70,800, "Sx: %.2f ",sc[0]); snprintf(charBuf+80,800, "Sy: %.2f ",sc[1]); snprintf(charBuf+90,800, "Sz: %.2f",sc[2]); msg += charBuf; snprintf(charBuf,1000,"\nStDvs: "); snprintf(charBuf+10,800, "x: %.2f ",std::sqrt((double)lastFramePoseSpeed[0])); snprintf(charBuf+20,800, "y: %.2f ",std::sqrt((double)lastFramePoseSpeed[1])); snprintf(charBuf+30,800, "z: %.2f ",std::sqrt((double)lastFramePoseSpeed[2])); snprintf(charBuf+40,800, "r: %.2f ",std::sqrt((double)lastFramePoseSpeed[3])); snprintf(charBuf+50,800, "p: %.2f ",std::sqrt((double)lastFramePoseSpeed[4])); snprintf(charBuf+60,800, "y: %.2f ",std::sqrt((double)lastFramePoseSpeed[5])); snprintf(charBuf+70,800, "vx: %.2f ",std::sqrt((double)lastFramePoseSpeed[6])); snprintf(charBuf+80,800, "vy: %.2f ",std::sqrt((double)lastFramePoseSpeed[7])); snprintf(charBuf+90,800, "vz: %.2f ",std::sqrt((double)lastFramePoseSpeed[8])); snprintf(charBuf+100,800, "vy: %.2f",std::sqrt((double)lastFramePoseSpeed[9])); msg += charBuf; } else { snprintf(charBuf,1000,"Drone Pose: "); snprintf(charBuf+13,800, "xyz=(%.2f, ",lastFramePoseSpeed[0]); snprintf(charBuf+25,800, "%.2f, ",lastFramePoseSpeed[1]); snprintf(charBuf+32,800, "%.2f), ",lastFramePoseSpeed[2]); snprintf(charBuf+42,800, "rpy=(%.2f, ",lastFramePoseSpeed[3]); snprintf(charBuf+54,800, "%.2f, ",lastFramePoseSpeed[4]); snprintf(charBuf+61,800, "%.2f) ",lastFramePoseSpeed[5]); msg += charBuf; } myGLWindow->GetMousePoseUpdate(); CVD::glSetFont("sans"); if(drawUI != UI_NONE) myGLWindow->DrawCaption(msg); if(drawUI == UI_DEBUG) { glMatrixMode(GL_PROJECTION); glPushMatrix(); glTranslatef((float)0, (float)100, 0.0); glScalef(45,-45,1); snprintf(charBuf,1000,"xyz: %.2f %.2f %.2f",lastFramePoseSpeed[0],lastFramePoseSpeed[1],lastFramePoseSpeed[2]); CVD::glDrawText(charBuf, CVD::NICE, 1.6, 0.1); glPopMatrix(); } myGLWindow->swap_buffers(); myGLWindow->HandlePendingEvents(); }
void SPScatterPlotter::plot(QPainter &painter, QRect area) const { plotGrid(painter, area); plotAxis(painter, area, m_xlabel, m_ylable); plotData(painter, area); }