#ifndef __DRESIDUALFINDER_CU__ #define __DRESIDUALFINDER_CU__ #include #include #include //---------------- // GPU_FindClosestTrajectoryPoint //---------------- __global__ void GPU_FindClosestTrajectoryPoint(int N, int M, trajectory_t *trajectories, int *wire_hit_d, int *hit_index_d) { //int idx_i = threadIdx.x; // hit (N) //int idx_j = blockIdx.x; // trajectory (M) int idx_i = blockIdx.x; //N int idx_j = threadIdx.x; //M if(idx_isteps; for(int i = 0; i < trajectory->Nsteps; i++, step++) { // Distance from point to wire is magnitude of // cross product of vector pointing from wire // center to point and the normalized vector // pointing in direction of wire. float x = step->pos.x - wire->x; float y = step->pos.y - wire->y; float z = step->pos.z - wire->z; float3 b = make_float3(x, y, z); float3 &wire_dir = wire->udir; float3 cross_prod = cross(b, wire_dir); // Only care about minimum magnitude which is // also the minimum magnitude squared float val2 = cross_prod.x*cross_prod.x + cross_prod.y*cross_prod.y + cross_prod.z*cross_prod.z; // Use boolean result of less than operator as // an integer to index which element of the two // element arrays to store this in. This way, the // minimum is always put into element 1. int idx = val2 < vals[1]; //1 or 0 based on min or not vals[idx] = val2; //Set new min ptr[idx] = i; } //min distance point should be in ptr[1] int finalIndex = N*idx_j + idx_i; //ptr[1]=(int)(sqrt(vals[1])*1000.0); //ptr[1] = finalIndex; hit_index_d[finalIndex] = ptr[1]; } } //---------------- // GPU_CalcResiduals //---------------- __global__ void GPU_CalcResiduals(int N, int M, trajectory_t *trajectories, int *wire_hit_d, int *hit_index_d, float *hit_dist_d, float *hit_resi_d) { //int idx_i = threadIdx.x; // hit (N) //int idx_j = blockIdx.x; // trajectory (M) int idx_i = blockIdx.x; //N int idx_j = threadIdx.x; //M if(idx_isteps[step_idx]; hit_dist_d[idx] = GPU_DistToRT(wire, step); hit_resi_d[idx] = hit_dist_d[idx]; } } //---------------- // GPU_CalcMatrix_Binv //---------------- __global__ void GPU_CalcMatrix_Binv(int N, int M, trajectory_t *trajectories, int *wire_hit_d, float *hit_resi_d, float *Binv_matrix_d) { /// Finding the change in the state vector requires calculating /// the inverse of the "B" matrix and then inverting it to get "B". /// The "Binv" matrix is made from the "F" matrix. "F" is just the /// Jacobian dR_i/dS_j where R_i is the change in the residual of /// the i-th hit and S_j is the corresponding change of the j-th state /// parameter. The uncertainties are included through an inverted /// covariance matrix "Vinv" (see below). The formula for "Binv" is: /// /// Binv = Ft*Vinv*F /// /// Each thread running this routine will calculate a single /// element of the Binv matrix. In reality, there should be /// 25 threads per Binv and one Binv matrix for every mass /// hypothesis. /// /// The covariance "V" is the sum of the measurement uncertainties /// and the multiple scattering covariance. The measurement /// uncertainties are a diagonal matrix and the multiple /// scattering covariance can contain off-diagnal elements. In /// the current version, the multiple scattering is not included. /// This means that V is a diagonal matrix. Further, we do not /// distinguish between CDC and FDC and assume all measurements /// have the same uncertainty. This makes the inversion of the /// V matrix trivial. It is just an identity matrix scaled by /// 1/sigma^2. If this were not the case, then this kernel should /// be broken up into 2 so that the different dimensioned matrix /// multiplications could be done in two steps. As it is now /// though, this reduces to Ft*F / sigma^2 float err = 0.1443375673; // FDC sigma = 0.5/sqrt(12) float err2 = err*err; int idx_hypoth = blockIdx.x; int idx_i = threadIdx.x; int idx_j = threadIdx.y; if( idx_i<5 && idx_j<5 && idx_hypoth