inline double KDERules<MetricType, KernelType, TreeType>:: Score(const size_t queryIndex, TreeType& referenceNode) { double score, maxKernel, minKernel, bound; const arma::vec& queryPoint = querySet.unsafe_col(queryIndex); const double minDistance = referenceNode.MinDistance(queryPoint); bool newCalculations = true; if (tree::TreeTraits<TreeType>::FirstPointIsCentroid && lastQueryIndex == queryIndex && traversalInfo.LastReferenceNode() != NULL && traversalInfo.LastReferenceNode()->Point(0) == referenceNode.Point(0)) { // Don't duplicate calculations. newCalculations = false; lastQueryIndex = queryIndex; lastReferenceIndex = referenceNode.Point(0); } else { // Calculations are new. maxKernel = kernel.Evaluate(minDistance); minKernel = kernel.Evaluate(referenceNode.MaxDistance(queryPoint)); bound = maxKernel - minKernel; } if (newCalculations && bound <= (absError + relError * minKernel) / referenceSet.n_cols) { // Estimate values. double kernelValue; // Calculate kernel value based on reference node centroid. if (tree::TreeTraits<TreeType>::FirstPointIsCentroid) { kernelValue = EvaluateKernel(queryIndex, referenceNode.Point(0)); } else { kde::KDEStat& referenceStat = referenceNode.Stat(); kernelValue = EvaluateKernel(queryPoint, referenceStat.Centroid()); } densities(queryIndex) += referenceNode.NumDescendants() * kernelValue; // Don't explore this tree branch. score = DBL_MAX; } else { score = minDistance; } ++scores; traversalInfo.LastReferenceNode() = &referenceNode; traversalInfo.LastScore() = score; return score; }
inline force_inline double KDERules<MetricType, KernelType, TreeType>:: EvaluateKernel(const size_t queryIndex, const size_t referenceIndex) const { return EvaluateKernel(querySet.unsafe_col(queryIndex), referenceSet.unsafe_col(referenceIndex)); }
/* * Function: EvaluateKernelCell * ------------------------------------------------------------------- * Evaluates the kernel for interactions between a pair of cells. * M2L operator initialization */ void H2_3D_Tree::EvaluateKernelCell(vector3 *field, vector3 *source, int Nf, int Ns, doft *dof, double *kernel) { int i, j, k, l, count, count_kernel; int dof_f = dof->f; int dof_s = dof->s; int dofNf = dof->f * Nf; int dof2 = dof->f * dof->s; double * Kij; int LDA_kernel = dofNf; Kij = (double*) malloc(dof2 * sizeof(double)); for (j=0;j<Ns;j++) { for (i=0;i<Nf;i++) { EvaluateKernel(field[i],source[j],Kij, dof); count_kernel = dof_f * i + LDA_kernel * dof_s * j; count = 0; for (k=0;k<dof_s;k++) for (l=0;l<dof_f;l++, count++) /* Column-major storage */ kernel[count_kernel + k * LDA_kernel + l] = Kij[count]; } } free(Kij); }
inline double KDERules<MetricType, KernelType, TreeType>:: Score(TreeType& queryNode, TreeType& referenceNode) { double score, maxKernel, minKernel, bound; const double minDistance = queryNode.MinDistance(referenceNode); // Calculations are not duplicated. bool newCalculations = true; if (tree::TreeTraits<TreeType>::FirstPointIsCentroid && (traversalInfo.LastQueryNode() != NULL) && (traversalInfo.LastReferenceNode() != NULL) && (traversalInfo.LastQueryNode()->Point(0) == queryNode.Point(0)) && (traversalInfo.LastReferenceNode()->Point(0) == referenceNode.Point(0))) { // Don't duplicate calculations. newCalculations = false; lastQueryIndex = queryNode.Point(0); lastReferenceIndex = referenceNode.Point(0); } else { // Calculations are new. maxKernel = kernel.Evaluate(minDistance); minKernel = kernel.Evaluate(queryNode.MaxDistance(referenceNode)); bound = maxKernel - minKernel; } // If possible, avoid some calculations because of the error tolerance. if (newCalculations && bound <= (absError + relError * minKernel) / referenceSet.n_cols) { // Auxiliary variables. double kernelValue; kde::KDEStat& referenceStat = referenceNode.Stat(); kde::KDEStat& queryStat = queryNode.Stat(); // If calculating a center is not required. if (tree::TreeTraits<TreeType>::FirstPointIsCentroid) { kernelValue = EvaluateKernel(queryNode.Point(0), referenceNode.Point(0)); } // Sadly, we have no choice but to calculate the center. else { kernelValue = EvaluateKernel(queryStat.Centroid(), referenceStat.Centroid()); } // Sum up estimations. for (size_t i = 0; i < queryNode.NumDescendants(); ++i) { densities(queryNode.Descendant(i)) += referenceNode.NumDescendants() * kernelValue; } score = DBL_MAX; } else { score = minDistance; } ++scores; traversalInfo.LastQueryNode() = &queryNode; traversalInfo.LastReferenceNode() = &referenceNode; traversalInfo.LastScore() = score; return score; }
/* * Function: ComputeKernelUniformGrid * ------------------------------------------------------------------ * Computes the kernel for 316(2n-1)^3 interactions between Uniform * Grid nodes. Does not compute SVD. */ void H2_3D_Tree::ComputeKernelUniformGrid(double *Kweights, int n, doft *dof, char *Kmat, double alphaAdjust, rfftw_plan p_r2c) { /* TODO: multi-dof, alphaAdjust */ int i, k1, k2, k3, l1, l2, l3; vector3 scenter; int dof2 = dof->s * dof->f; //int dof2n6 = dof2 * (2*n-1)*(2*n-1)*(2*n-1); // Total size double nodes[n], kernel[dof2]; vector3 fieldpos, sourcepos; // Compute Chebyshev nodes of T_n(x) //double scale = 1+alphaAdjust; CalculateNodeLocations(n,nodes,0); // creat FFT plan int vecSize = 2*n-1, reducedMatSize = pow(vecSize, 3); int M2LSize = dof2 *reducedMatSize; double *MatM2L = (double*)malloc(M2LSize *sizeof(double)); double *freqMat = (double*)malloc(316 *M2LSize *sizeof(double)); // Compute the kernel values for interactions with all 316 cells int countM2L=0, count, count1; int shift1, shift2, shiftGlo, shiftLoc; int reducedMatSizeDofs = reducedMatSize *dof->s; int f, s; for (k1=-3;k1<4;k1++) { scenter.x = (double)k1; for (k2=-3;k2<4;k2++) { scenter.y = (double)k2; for (k3=-3;k3<4;k3++) { scenter.z = (double)k3; if (abs(k1) > 1 || abs(k2) > 1 || abs(k3) > 1) { for (count=0, l1=0; l1<vecSize; l1++) { GetPosition(n, l1, &fieldpos.x, &sourcepos.x, nodes); sourcepos.x += scenter.x; for (l2=0; l2<vecSize; l2++) { GetPosition(n, l2, &fieldpos.y, &sourcepos.y, nodes); sourcepos.y += scenter.y; for (l3=0; l3<vecSize; l3++, count++) { GetPosition(n, l3, &fieldpos.z, &sourcepos.z, nodes); sourcepos.z += scenter.z; EvaluateKernel(fieldpos,sourcepos,kernel,dof); // kernel[f x s] in column major // MatM2L[(2n-1)^3 x s x f] in column // major count1 = 0; shift1 = count; for (s=0; s < dof->s; s++) { for(f=0, shift2=0; f < dof->f; f++) { MatM2L[shift1 + shift2] = kernel[count1++]; shift2 += reducedMatSizeDofs; } shift1 += reducedMatSize; } } } } // FFT shiftGlo = countM2L *M2LSize; for (i=0, shiftLoc=0; i<dof2; i++) { rfftw_one(p_r2c, MatM2L + shiftLoc, freqMat + shiftGlo + shiftLoc); shiftLoc += reducedMatSize; } countM2L++; } } } } FILE *ptr_file; ptr_file = fopen(Kmat, "wb"); fwrite(freqMat, sizeof(double),316 *M2LSize, ptr_file); fclose(ptr_file); free(MatM2L); free(freqMat); }