void H2_3D_Tree::ComputeWeights(double *Tkz, int *Ktable, double *Kweights, double *Cweights, int n, double alpha, int use_chebyshev) { int i, k, m, l1, l2, l3, count, ncell, ninteract; double tmp1, tmp2; vector3 vtmp; double *nodes, *vec; vector3 *fieldt, *Sn; nodes = (double *)malloc(n * sizeof(double)); vec = (double *)malloc(n * sizeof(double)); int n3 = n*n*n; // n3 = n^3 int Nc = 2*n3; // Number of child Chebyshev nodes fieldt = (vector3 *)malloc(Nc * sizeof(vector3)); // Chebyshev-transformed coordinates Sn = (vector3 *)malloc(n * Nc * sizeof(vector3)); //double pi = M_PI; // Initialize lookup table for (i=0;i<343;i++) Ktable[i] = -1; // Create lookup table ncell = 0; ninteract = 0; for (l1=-3;l1<4;l1++) { for (l2=-3;l2<4;l2++) { for (l3=-3;l3<4;l3++) { if (abs(l1) > 1 || abs(l2) > 1 || abs(l3) > 1) { Ktable[ncell] = ninteract; ninteract++; } ncell++; } } } // Compute the n Chebyshev nodes of T_n(x) // for (m=0; m<n; m++) // nodes[m] = cos(pi*((double)m+0.5)/(double)n); // Compute n Chebyshev nodes in [-.5, .5] CalculateNodeLocations(n,nodes,use_chebyshev); // Evaluate the Chebyshev polynomials of degree 0 to n-1 at the nodes for (m=0; m<n; m++) { ComputeTk(nodes[m],n,vec); i = m*n; for (k=0;k<n;k++) { Tkz[i+k] = vec[k]; } } if (use_chebyshev) { // Compute the weights for the kernel matrix K count = 0; for (l1=0;l1<n;l1++) { tmp1 = 1./sqrt(1-nodes[l1]*nodes[l1]); for (l2=0;l2<n;l2++) { tmp2 = tmp1/sqrt(1-nodes[l2]*nodes[l2]); for(l3=0;l3<n;l3++) { Kweights[count] = tmp2/sqrt(1-nodes[l3]*nodes[l3]); count++; } } } } else { // Compute the weights for the kernel matrix K count = 0; for (l1=0;l1<n;l1++) { tmp1 = 1./sqrt(1-nodes[l1]*nodes[l1]); for (l2=0;l2<n;l2++) { tmp2 = tmp1/sqrt(1-nodes[l2]*nodes[l2]); for(l3=0;l3<n;l3++) { Kweights[count] = 1; //tmp2/sqrt(1-nodes[l3]*nodes[l3]); count++; } } } } // Map all Chebyshev nodes from the children cells to the parent k = 0; double scale = 1 / (1+alpha); //scale = 1; for (i=0;i<2;i++) { // Determine the mapping function for the specific child cell vtmp.x = -0.5; vtmp.y = -0.5; if (i == 0) vtmp.z = -0.5; else vtmp.z = 0.5; for (l1=0;l1<n;l1++) { for (l2=0;l2<n;l2++) { for (l3=0;l3<n;l3++) { fieldt[k].x = nodes[l1] * .5 + vtmp.x * scale; fieldt[k].y = nodes[l2] * .5 + vtmp.y * scale; fieldt[k].z = nodes[l3] * .5 + vtmp.z * scale; k++; } } } } // Compute Sc, the mapping function for the field points ComputeSn(fieldt,Tkz,n,Nc,Sn, use_chebyshev); // Extract out the Chebyshev weights count = 0; for (l1=0;l1<n;l1++) { k = l1*Nc; for (l2=0;l2<n;l2++) { Cweights[count] = Sn[k+l2].z; count++; } } for (l1=0;l1<n;l1++) { k = l1*Nc; for (l2=0;l2<n;l2++) { Cweights[count] = Sn[k+n3+l2].z; count++; } } free(nodes); free(vec); free(fieldt); free(Sn); }
void ComputeWeightsPBC(double *UpMat, int n, double alpha, double *Tkz) { int i, j, k, l, m, l1, l2, l3, count1, count2; vec3 vtmp; int n3 = n*n*n; // n3 = n^3 int n6 = n3*n3; // n6 = n^6 int Nc = 27*n3; // Number of child Chebyshev nodes double nodes[n]; //, vec[n]; vec3 fieldt[Nc]; // Chebyshev-transformed coordinates vec3 Sn[n*Nc]; double pi = M_PI; double third = 1.0/3.0; // the parent box is divided into three children in each dimension // Compute the n Chebyshev nodes of T_n(x) for (m=0;m<n;m++) nodes[m] = cos(pi*((double)m+0.5)/(double)n); // Map all Chebyshev nodes from the children cells to the parent k = 0; for (i=0;i<27;i++) { // Determine the mapping function for the specific child cell if (i<9) { vtmp.x = -2; if (i<3) vtmp.y = -2; else if (i<6) vtmp.y = 0; else vtmp.y = 2; } else if (i<18) { vtmp.x = 0; if (i<12) vtmp.y = -2; else if (i<15) vtmp.y = 0; else vtmp.y = 2; } else { vtmp.x = 2; if (i<21) vtmp.y = -2; else if (i<24) vtmp.y = 0; else vtmp.y = 2; } if (i%3 == 0) vtmp.z = -2; else if (i%3 == 1) vtmp.z = 0; else vtmp.z = 2; // Map all Chebyshev nodes from the children cells to the parent // Note: 'nodes' below corresponds to alpha=0 // scaled child grids: nodes[i]*(1+alpha) +- 2 // scaled parent box: (1+alpha)*6 // ihalfL: 1/((1+alpha)*3) // so the relative position is: (nodes[i] +- 2/(1+alpha)) / 3 double L = AdjustBoxSize(1.0, alpha); for (l1=0;l1<n;l1++) { for (l2=0;l2<n;l2++) { for (l3=0;l3<n;l3++) { fieldt[k].x = (nodes[l1] + vtmp.x / L) * third; fieldt[k].y = (nodes[l2] + vtmp.y / L) * third; fieldt[k].z = (nodes[l3] + vtmp.z / L) * third; k++; } } } } // Compute Sc, the mapping function for the field points ComputeSn(fieldt, Nc, Sn, n, Tkz, 1); // 1 for Chebyshev // Compute Sxyz, the weights for the sources double *Sxyz = (double *)malloc(n3 * Nc * sizeof(double)); for (k=0;k<Nc;k++) { l = 0; for (l1=0;l1<n;l1++) { for (l2=0;l2<n;l2++) { for (l3=0;l3<n;l3++) { Sxyz[l*Nc+k] = Sn[l1*Nc+k].x*Sn[l2*Nc+k].y*Sn[l3*Nc+k].z; l++; } } } } // Accumulate the weights into a single weight matrix W double *W = (double *)calloc(n6, sizeof(double)); for (i=0;i<27;i++) { count1 = 0; count2 = i*n3; for (j=0;j<n3;j++) { for (k=0;k<n3;k++) { W[count1] += Sxyz[k*Nc+count2]; // Notice the transpose here count1++; } count2++; } } UpMat = Assign(UpMat, W, n6); free(Sxyz); free(W); }