int *generateNCounts(galaxy *gals, int numGals, int numVoxelsPerDim, int xStart, int yStart, int zStart, int boxLength){ // Allocate the voxel array. int *voxels = calloc(pow(numVoxelsPerDim, 3), sizeof(int)); // Convert the galaxy list to cartesian coordinates. cartesianGalaxy *cartGals = convertToCartesian(gals, numGals); // Loop through each galaxy and add it to the corresponding voxel. double voxelLength = (double)boxLength/numVoxelsPerDim; int ind; #pragma omp parallel for for(ind = 0; ind < numGals; ind++){ // Adjust the location of the galaxy. double x = (cartGals+ind)->x - xStart; double y = (cartGals+ind)->y - yStart; double z = (cartGals+ind)->z - zStart; // Calculate the index of the galaxy. int i = x/voxelLength; int j = y/voxelLength; int k = z/voxelLength; int index = i + numVoxelsPerDim*j + pow(numVoxelsPerDim, 2)*k; // Increment the voxel at this location. #pragma omp critical voxels[index]++; } return voxels; }
/** * Compute the area as a diagnostic and print it stdout. */ void SwarmCylinders::Spline::computeArea() { double da = 1e-3; vector<double> x; vector<double> y; for (int i = 0; i < 1.0 / da; i++) { vector<double> a; a.push_back(i * da * M_PI); vector<double> r; r.push_back(evaluate(a[0])); convertToCartesian(r, a); x.push_back(r[0]); y.push_back(a[0]); a.clear(); r.clear(); } double area = 0; const int xsize = x.size(); for (int i = 0; i < xsize - 1; i++) area += 0.5 * (x[i + 1] - x[i]) * (y[i] + y[i + 1]); printf("** Area: %1.10f", -area); }
/** * Check if the spline crosses the y-axis, if so, abort. */ void SwarmCylinders::checkValidityOfSpline() const { const int nSpline = 512; const double ymin = 0.10; // if 0, prevents you from creating splines that cross the y-axis const double dalpha = 2.0 * M_PI / (double) nSpline; vector<double> xTest; vector<double> yTest; for (int i = 0; i < nSpline; i++) { xTest.push_back(spline.evaluate((double) i + 0.5) * dalpha); yTest.push_back(((double) i + 0.5) * dalpha); } convertToCartesian(xTest, yTest); for (int i = 0; i < nSpline; i++) { if (yTest[i] < ymin) { printf("** The spline crosses or is too close to the the mirror plane! (ymin = %0.4f, k1 = %0.4f k2 = %0.4f, alpha = %0.4f)\n", ymin, K1, K2, alpha); abort(); } } }
QImage CurveTransform::transform() { for(unsigned int i = 0; i < image_width; i++) { for(unsigned int j = 0; j < image_height; j++) { CartesianPair coords = {i, j}; drawPixels(convertToPixels(convertToCartesian(convertToPolar(coords))),coords); //Lisp, eat your heart out } } return out_image; }
/** * Initially place the cylinders somewhere inside the region bounded by the * spline. */ void SwarmCylinders::placeCylinders() { printf("** Number of agents: %d\n", n); printf("** Placing agents %1.4f inside of the boundary! \n", rmin); double dalpha = 2.0 * M_PI / (double) n; for (int i = 0; i < n; i++) { x.push_back(spline.evaluate(((double) i + 0.5) * dalpha) - rmin); y.push_back(((double) i + 0.5) * dalpha); } convertToCartesian(x, y); }
double *generateMap(galaxy *gals, int numGals, int numVoxelsPerDim, int xStart, int yStart, int zStart, int boxLength, int **voxels){ // Allocate the voxel array. *voxels = calloc(pow(numVoxelsPerDim, 3), sizeof(int)); // Convert the galaxy list to cartesian coordinates. cartesianGalaxy *cartGals = convertToCartesian(gals, numGals); // Loop through each galaxy and add it to the corresponding voxel. double voxelLength = (double)boxLength/numVoxelsPerDim; int ind; #pragma omp parallel for for(ind = 0; ind < numGals; ind++){ // Adjust the location of the galaxy. double x = (cartGals+ind)->x - xStart; double y = (cartGals+ind)->y - yStart; double z = (cartGals+ind)->z - zStart; // Calculate the index of the galaxy. int i = x/voxelLength; int j = y/voxelLength; int k = z/voxelLength; int index = i + numVoxelsPerDim*j + pow(numVoxelsPerDim, 2)*k; // Increment the voxel at this location. #pragma omp critical (*(*voxels + index))++; } // Loop through each voxel and calculate the contrasts. double p0 = numGals/pow(numVoxelsPerDim, 3); double *map = calloc(pow(numVoxelsPerDim, 3), sizeof(double)); #pragma omp parallel for for(ind = 0; ind < (int)pow(numVoxelsPerDim, 3); ind++){ if((*voxels)[ind] == 0){ map[ind] = -0.9; }else{ *(map+ind) = (*(*voxels+ind) - p0)/p0; } } return map; }
/** * Print the spline in (x,y) coordinates to a file named spline.txt. */ void SwarmCylinders::printSpline() const { double dalpha = 2.0 * M_PI / (double) M; vector<double> xs; vector<double> ys; for (int i = 0; i < M; i++) { xs.push_back(spline.evaluate(((double) i + 0.5) * dalpha)); ys.push_back(((double) i + 0.5) * dalpha); } convertToCartesian(xs, ys); FILE* fid; fid = fopen("spline.txt", "w"); for (int i = 0; i < (int) xs.size(); i++) { fprintf(fid, "%10.6f %10.6f\n", xs[i], ys[i]); } fclose(fid); }
/** * Find the equilibrium after placing the cylinders in the domain somewhere. * Iterates until tolerence is met. */ void SwarmCylinders::findEquilibrium() { double dalpha = 2.0 * M_PI / (double) M; vector<double> m; for (int i = 0; i < M; i++) { m.push_back(spline.evaluate(i * dalpha) * dalpha); /// assuming constant density charge on boundary } vector<double> xs; vector<double> ys; for (int i = 0; i < M; i++) { xs.push_back(spline.evaluate(((double) i + 0.5) * dalpha)); ys.push_back(((double) i + 0.5) * dalpha); } convertToCartesian(xs, ys); int nIter = 0; bool steadyState = false; while (!steadyState) { vector<double> xNew; vector<double> yNew; const int xsize = x.size(); for (int i = 0; i < xsize; i++) { xNew.push_back(0.0); yNew.push_back(0.0); } for (int i = 0; i < xsize; i++) { double u = 0.0; double v = 0.0; for (int j = 0; j < xsize; j++) /// from each body { if (i != j) { double norm = sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j])); double factor = factorCylinder / (norm * norm * norm); u += (x[i] - x[j]) * factor; v += (y[i] - y[j]) * factor; } } for (int j = 0; j < M; j++) /// from boundary { double norm = sqrt((x[i] - xs[j]) * (x[i] - xs[j]) + (y[i] - ys[j]) * (y[i] - ys[j])); double factor = factorBoundary * m[j] / (norm * norm * norm); u += (x[i] - xs[j]) * factor; v += (y[i] - ys[j]) * factor; } xNew[i] = x[i] + dt * u; yNew[i] = y[i] + dt * v; } convertToPolar(xNew, yNew); for (int i = 0; i < xsize; i++) { const double rMax = spline.evaluate(yNew[i]) - radius; if (rMax < xNew[i]) xNew[i] = 0.1 * rMax; /// move it toward (0,0) // xNew[i] = min(spline.evaluate(yNew[i])-radius, xNew[i]); /// make it sit on the boundary if it is not repelled enough (not exactly correct) } convertToCartesian(xNew, yNew); double maxNorm = 0.0; for (int i = 0; i < xsize; i++) { double norm = sqrt((xNew[i] - x[i]) * (xNew[i] - x[i]) + (yNew[i] - y[i]) * (yNew[i] - y[i])); /// relative difference maxNorm = max(norm, maxNorm); } for (int i = 0; i < xsize; i++) { x[i] = xNew[i]; y[i] = yNew[i]; } // TODO Remove this testing shit, writing the positions each iteration if (nIter % 10 == 0) { FILE* fidx; FILE* fidy; if (nIter == 0) { fidx = fopen("x.txt", "w"); fidy = fopen("y.txt", "w"); } else { fidx = fopen("x.txt", "a"); fidy = fopen("y.txt", "a"); } const int xsize = x.size(); for (int i = 0; i < xsize; ++i) { fprintf(fidx, "%e ", x[i]); fprintf(fidy, "%e ", y[i]); } fprintf(fidx, "\n"); fprintf(fidy, "\n"); fclose(fidx); fclose(fidy); } nIter++; if (maxNorm <= threshold) break; if (nIter % 5000 == 0) printf("** Norm at iteration %d: %e\n", nIter, maxNorm); if (nIter > 50000) { printf("** Something is wrong, swarm shape is not converging quickly enough... aborting... \n"); abort(); } } printf("** Number of iterations to steady state formation: %d\n", nIter); }