// ============================================================================ // GLOctree::insertParticle() // insert a new particle in the tree void GLOctree::insertParticle(int index, Node ** node, float * rmid, int level, int obj) { int bit; int octant=0; float new_rmid[3]; //assert(level < 30); if (level > 30) { PRINT_D ; //std::cerr << "Skip particle with index [" << index << "]\n"; return; } level_max = MAX(level,level_max); if ( ! (*node) ) { (*node) = new Node(); } // look for position in the cube (octant) for (int i=0; i<3; i++) { float comp=p_data->pos[index*3+i]; if ((comp-rmid[i]) < 0) { bit=0; new_rmid[i]=((float ) (-size_max)/(float) (1<<level))+rmid[i]; } else { bit=1; new_rmid[i]=((float ) (size_max)/(float ) (1<<level))+rmid[i]; } octant+=(bit << (2-i)); } // check if octant is free if (((*node)->node[octant])==NULL) { // yes it's free ! Node * new_node=new Node(index,obj); // insert a particle (leaf) (*node)->node[octant] = new_node; p_data->tree_depth[index] = level; // Save particle's level } else { // octant is not free if ((*node)->node[octant]->type ==0) { // it's a node insertParticle(index,&((*node)->node[octant]),new_rmid,level+1,obj); } else { // it's a leaf // we must insert particles's leaf itself in a new octant int save_index=(*node)->node[octant]->index; //std::cerr << "save index="<< save_index <<"\n"; (*node)->node[octant]->type=0; // leaf become node int old_obj = (*node)->node[octant]->obj; // must use old obj !! insertParticle(save_index,&((*node)->node[octant]),new_rmid,level+1,old_obj); // we must now insert our particle insertParticle(index,&((*node)->node[octant]),new_rmid,level+1,obj); } } }
void PFReconstructor::reconstructBlock(const PFBlock& block) { /// see class description for summary of reconstruction approach Ids ids = block.elementIds(); #if WITHSORT std::sort(ids.begin(), ids.end()); #endif for (auto id : ids) { m_locked[id] = false; } if (ids.size() == 1) { //#TODO WARNING!!! LOTS OF MISSING CASES IdType id = ids[0]; if (Id::isEcal(id)) { insertParticle(block, reconstructCluster(m_pfEvent.ECALCluster(id), papas::Layer::kEcal)); } else if (Id::isHcal(id)) { insertParticle(block, reconstructCluster(m_pfEvent.HCALCluster(id), papas::Layer::kHcal)); } else if (Id::isTrack(id)) { insertParticle(block, reconstructTrack(m_pfEvent.track(id))); } else { // ask Colin about energy balance - what happened to the associated clusters that one would expect? // TODO } } else { for (auto id : ids) { if (Id::isHcal(id)) { reconstructHcal(block, id); } } for (auto id : ids) { if (Id::isTrack(id) && !m_locked[id]) { /* unused tracks, so not linked to HCAL # reconstructing charged hadrons. # ELECTRONS TO BE DEALT WITH.*/ insertParticle(block, reconstructTrack(m_pfEvent.track(id))); for (auto idlink : block.linkedIds(id, Edge::EdgeType::kEcalTrack)) { // TODO ask colin what happened to possible photons here: // TODO add in extra photons but decide where they should go? m_locked[idlink] = true; } } } } for (auto& id : ids) { if (!m_locked[id]) { m_unused.push_back(id); } } }
// ============================================================================ // GLOctree::build() // build octree int GLOctree::build() { if (psv && store_options->octree_enable) { new_data=false; init(); computeSizeMax(); p_data->tree_size_max = size_max; PRINT_D std::cerr << "Start build\n"; for (int obj=0; obj< (int ) psv->size(); obj++ ) { VirtualParticlesSelect * vps = (*psv)[obj].vps; if (vps->is_visible) { //for (int i=0; i < vps->npart; i+=vps->step_part) { for (int i=0; i < vps->ni_index; i++) { int index=vps->index_tab[i]; assert(index<*p_data->nbody); //std::cerr << "Nbody = " << nbody << " Obj = " << obj << " I = " << i << " Index = " << index << "\n"; insertParticle(index,&root, rmid, 1, obj ); } } } PRINT_D std::cerr << "stop build Level max= " << level_max << "\n"; return 1; } return 0; }
int main(int argc, char *argv[]) { int i, N=2500; const float L=1,W=1,dt=1e-6; G=2.0/N; double *x,*y,*mass,*forceX,*forceY,*u,*v,ax,ay; const int frameskip=100; int frame=frameskip-1; const double initSpeedLimit=0.001; const float theta = 0.8; x = (double *)malloc(N*sizeof(double)); y = (double *)malloc(N*sizeof(double)); u = (double *)malloc(N*sizeof(double)); v = (double *)malloc(N*sizeof(double)); mass = (double *)malloc(N*sizeof(double)); forceX = (double *)malloc(N*sizeof(double)); forceY = (double *)malloc(N*sizeof(double)); #ifndef DISTRIBUTION_AS_IN_ASSIGNMENT for(i=0;i<N;i++) { x[i]=frand(0,1); y[i]=frand(.25,.75); relativePosition(&u[i], &v[i], 0, 0, x[i], y[i]); u[i]*=frand(-initSpeedLimit,initSpeedLimit); v[i]*=frand(-initSpeedLimit,initSpeedLimit); mass[i]=frand(1, 100); forceX[i]=0; forceY[i]=0; } x[0]=x[1]=0.5; y[0]=0.45; y[1]=0.55; v[0]=v[1]=0; u[0]=-0.007; u[1]=0.007; mass[0]=mass[1]=1000; #endif #ifdef DISTRIBUTION_AS_IN_ASSIGNMENT const double alpha=0.25; const double V=20.0; for(i = 0; i<N; i++) { mass[i]=1; double R=frand(0, L/4.0); double fi=frand(0, 2*3.1415); x[i]=L/2.0+R*cos(fi); y[i]=W/2.0+alpha*R*sin(fi); double Rprim = sqrt((x[i]-L/2.0)*(x[i]-L/2.0) + (y[i]-W/2.0)*(y[i]-W/2.0)); u[i] = -V*Rprim*sin(fi); v[i] = V*Rprim*cos(fi); forceX[i]=0; forceY[i]=0; } #endif InitializeGraphics(argv[0],windowWidth,windowWidth); SetCAxes(0,1); Node *root; printf("Hit q to quit.\n"); int iterations=0; while(!CheckForQuit()) { iterations++; #ifndef BARNESHUT for(i=0;i<N;i++) { #endif #ifdef BARNESHUT // Bounce(&x[0],&y[0],&u[0],&v[0],L,W); root = createNode(0,x,y,mass); for(i=1;i<N;i++) { #endif if (x[i] > 2*L || x[i]< -1 || y[i] > 2*W || y[i] < -1) { printf("Things are going out of bounds"); exit(-1); } // Bounce(&x[i],&y[i],&u[i],&v[i],L,W); #ifndef BARNESHUT calculateForce(&forceX[i], &forceY[i], i, x, y, mass, N); #endif #ifdef BARNESHUT insertParticle(root, x, y, mass, i); #endif } #ifdef BARNESHUT for(i=0; i<N; i++) BarnesHut(root, x, y, mass, theta, i, &forceX[i], &forceY[i]); #endif update(x,y,u,v,mass,forceX, forceY,dt, N); frame++; frame=frame%frameskip; if(frame==0) { ClearScreen(); for(i=0;i<N;i++) DrawCircle(x[i],y[i],L,W,(1+log10(mass[i]))*circleRadius,circleColor); Refresh(); } freeNodes(root); } XFlush(display); XCloseDisplay(display); printf("Iterations: %d\n", iterations); return 0; } /* * Function: Bounce * Usage: Bounce(&x[i],&y[i],&u[i],&v[i],L,W); * ------------------------------------------- * If a particle moves beyond any of the boundaries then set * it on the other side of the boundary back in the domain and * reverse the velocities. * */ void Bounce(double *x, double *y, double *u, double *v, double L, double W) { if(*x>L ) { *x=2*L-*x; *u=-*u; } if(*x<0 ) { *x=-*x; *u=-*u; } if(*y>W ) { *y=2*W-*y; *v=-*v; } if(*y<0 ) { *y=-*y; *v=-*v; } }
//-------------------------------------------------------------- void testApp::update(){ while( receiver.hasWaitingMessages() ){ ofxOscMessage m; receiver.getNextMessage( &m ); if( m.getAddress() == "/particle/new" ){ int x = m.getArgAsInt32( 0 ); int y = m.getArgAsInt32( 1 ); int n = m.getArgAsInt32( 2 ); int h = m.getArgAsInt32( 3 ); insertParticle(x, y, n, h); } } tuioClient.getMessage(); //------------------------------- if (timer <= standBy){ nucle.mass = 10; nucle.maxDistance = screenHeight*0.07; if ( timer >= (standBy-standBy/3)){ universe.mass = 10; universe.proportional= false; universe.clockwise = false; universe.impulse = timer - (standBy - standBy/3); universe.angle = -40; universe.density = 0.8; blur.setRadius(1); fboAlpha = 200; } else { universe.mass = 0.75; universe.proportional= true; universe.clockwise = true; universe.impulse = 0.3; universe.angle = 0; universe.density = 0.7; blur.setRadius(0.5); fboAlpha = 150; } } else { nucle.maxDistance = screenHeight*0.01; nucle.mass = 0.7; blur.setRadius(2); fboAlpha = 255; } for (int i=0; i < pAct.size() ; i++) if (universe.onSpace(pAct[i]->loc) && (pAct[i]->alpha > 5) ){ pAct[i]->update(); if (nucle.onSpace(pAct[i]->loc)) if (pAct[i]->bArrive) killParticle(i); } else killParticle(i); for (int i=0; i < pInact.size() ; i++) if (!universe.onSpace(pInact[i]->loc) || (pInact[i]->alpha < 5) ) pInact.erase(pInact.begin()+i); else pInact[i]->update(); timer += 1/ofGetFrameRate(); }
void PFReconstructor::reconstructHcal(const PFBlock& block, IdType hcalId) { /* block: element ids and edges hcalid: id of the hcal being processed her has hcal and has a track -> add up all connected tracks, turn each track into a charged hadron -> add up all ecal energies -> if track energies is greater than hcal energy then turn the missing energies into an ecal (photon) NB this links the photon to the hcal rather than the ecals -> if track energies are less than hcal then make a neutral hadron with rest of hcal energy and turn all ecals into photons has hcal but no track (nb by design there will be no attached ecals because hcal ecal links have been removed) -> make a neutral hadron has hcals -> each hcal is treated using rules above */ // hcal used to make ecal_in has a couple of possible issues // m_pfEvent.HCALCluster(hcalId); // TODO assert(len(block.linked_ids(hcalid, "hcal_hcal"))==0 ) // TODO sorting Ids trackids = block.sort_distance_energy(hcalid, block.linked_ids(hcalid, "hcal_track") ) Ids ecalIds; Ids trackIds = block.linkedIds(hcalId, Edge::EdgeType::kHcalTrack); #if WITHSORT std::sort(trackIds.begin(), trackIds.end()); #endif for (auto trackId : trackIds) { for (auto ecalId : block.linkedIds(trackId, Edge::EdgeType::kEcalTrack)) { /*the ecals get all grouped together for all tracks in the block # Maybe we want to link ecals to their closest track etc? # this might help with history work # ask colin.*/ if (!m_locked[ecalId]) { ecalIds.push_back(ecalId); m_locked[ecalId] = true; } } } #if WITHSORT std::sort(trackIds.begin(), trackIds.end()); std::sort(ecalIds.begin(), ecalIds.end()); #endif // hcal should be the only remaining linked hcal cluster (closest one) const Cluster& hcal = m_pfEvent.HCALCluster(hcalId); double hcalEnergy = hcal.energy(); double ecalEnergy = 0.; double trackEnergy = 0.; if (!trackIds.empty()) { for (auto id : trackIds) { const Track& track = m_pfEvent.tracks().at(id); insertParticle(block, reconstructTrack(track)); trackEnergy += track.energy(); } for (auto id : ecalIds) { ecalEnergy += m_pfEvent.ECALCluster(id).energy(); } double deltaERel = (hcalEnergy + ecalEnergy) / trackEnergy - 1.; double caloERes = neutralHadronEnergyResolution(hcal); /*self.log.info( 'dE/p, res = {derel}, {res} '.format( derel = delta_e_rel, res = calo_eres ))*/ if (deltaERel > nsigmaHcal(hcal) * caloERes) { //# approx means hcal energy + ecal energies > track energies double excess = deltaERel * trackEnergy; // energy in excess of track energies // print( 'excess = {excess:5.2f}, ecal_E = {ecal_e:5.2f}, diff = {diff:5.2f}'.format( // excess=excess, ecal_e = ecal_energy, diff=excess-ecal_energy)) if (excess <= ecalEnergy) { /* # approx means hcal energy > track energies # Make a photon from the ecal energy # We make only one photon using only the combined ecal energies*/ insertParticle(block, reconstructCluster(hcal, papas::Layer::kEcal, excess)); } else { // approx means that hcal energy>track energies so we must have a neutral hadron // excess-ecal_energy is approximately hcal energy - track energies insertParticle(block, reconstructCluster(hcal, papas::Layer::kHcal, excess - ecalEnergy)); if (ecalEnergy) { // make a photon from the remaining ecal energies // again history is confusingbecause hcal is used to provide direction // be better to make several smaller photons one per ecal? insertParticle(block, reconstructCluster(hcal, papas::Layer::kEcal, ecalEnergy)); } } } } else { // # case whether there are no tracks make a neutral hadron for each hcal //# note that hcal-ecal links have been removed so hcal should only be linked to //# other hcals insertParticle(block, reconstructCluster(hcal, papas::Layer::kHcal)); } m_locked[hcalId] = true; }