// --------------------------------------------------------------------------- /// Simple tester of the mapper (uses linear distribution function to generate mapper). // --------------------------------------------------------------------------- void mapper_testLinear (void) { int i; FILE *fp; double y, dy; mapper_t *mapper; say ("Testing of the distribution function mapper using linear function with known inverse mapping."); say ("See file output/test_mapper.dat for results."); mapper = mapper_create (func_lin, 0, sqrt (2.0), 20); fp = cfg_open ("output/test_mapper.dat", "wt", __func__); fprintf (fp, "variables = y invGood invNum delta\nzone t=\"test\", f = point\n"); for (y = 0, dy = 0.01 ; y <= 1.0 ; y += dy) { double x1 = mapper_invoke (y, mapper); fprintf (fp, "%e %e %e %e\n", y, sqrt (2*y), x1, x1 - sqrt (2*y)); } fprintf (fp, "zone t=\"integral\", f = point\n"); for (i = 0 ; i < mapper->N ; i++) fprintf (fp, "%e %e %e %e\n", mapper->arg[i], mapper->func[i], 0.5*mapper->arg[i]*mapper->arg[i], mapper->func[i] - 0.5*mapper->arg[i]*mapper->arg[i]); fclose (fp); mapper_destroy (mapper); }
// --------------------------------------------------------------------------- /// More advanced tester of the mapper (uses maxwellian distribution function to generate mapper). // --------------------------------------------------------------------------- void mapper_testMaxwell (void) { int i; FILE *fp; double y, dy; mapper_t *mapper; say ("Testing of the distribution function mapper using Maxwell function with known inverse mapping."); say ("See file output/test_mapper2.dat for results."); mapper = mapper_create (func_maxwell, - 10.0, 10.0, 5000); // Creates mapper. const double norm = 1.0/(erf (mapper->arg[mapper->N]) - erf (mapper->arg[0])); // Normalization for analitic result. fp = cfg_open ("output/test_mapper2.dat", "wt", __func__); fprintf (fp, "variables = x yGood yNum delta\nzone t=\"test\", f = point\n"); for (y = 0.0, dy = 0.01 ; y <= 1.0 + 1e-7 ; y += dy) { double x = mapper_invoke (y, mapper); double analitic = norm*(erf(x) - erf (mapper->arg[0])); fprintf (fp, "%e %e %e %e\n", x, y, analitic, y - analitic); } fprintf (fp, "zone t=\"integral\", f = point\n"); for (i = 0 ; i <= mapper->N ; i++) { double analitic = norm*(erf (mapper->arg[i]) - erf (mapper->arg[0])); fprintf (fp, "%e %e %e %e\n", mapper->arg[i], analitic, mapper->func[i], mapper->func[i] - analitic); } fclose (fp); mapper_destroy (mapper); }
void CLIDestroy() { mapper_destroy(&cli_mapper); map_destroy(&cli_map); }
/** * Creates the DF itself used values precalculated at tag_photoDF(FILE *fp). */ static double tag_photoInit(const double rho, const int uniformWeight, double qDivM) { int nMax = 0; int patternSize = nx * ny * nz * Nx * Ny * Nz * N * (1 + mirror) * (1 + nRotations); marker_t *pattern = (marker_t *) malloc(patternSize * sizeof(marker_t)); FILE *fp = NULL; mapper_t *mapper; // Creates mapper. if(uniformWeight) mapper = mapper_create(tag_photoDF_DF, 0, mc_pi, 1000); else mapper = mapper_create(tag_photoDF_markers, 0, mc_pi, 1000); if(!cpu_here) { fp = cfg_open("output/photoDF_pattern.dat", "wt", "tag_photoInit"); // Saves pattern for examination. fprintf(fp, "variables = <greek>j/p</greek>, <greek>q/p</greek>, x, y, z, v<sub>x</sub>, v<sub>y</sub>, v<sub>z</sub>\nzone t=\"Basic pattern\", f = point\n"); } int p = 0; // Makes basic pattern. for(int i = 0; i < nx * Nx; ++i) for(int j = 0; j < ny * Ny; ++j) for(int k = 0; k < nz * Nz; ++k) for(int l = 0; l < N; ++l) { double phi, theta, tmp; denavit_createQuartet(p, nx * ny * nz * Nx * Ny * Nz * N, &tmp, &theta, &phi, &tmp); // Gets Denavit-Wallsh coverage sample. theta /= 1.0 + mirror; // Fills vz > 0 part (mirror will fill the rest). phi /= 1.0 + nRotations; // Fills one slice of pie in V-space. pattern[p].x = h1 * (i + 0.5) / (double) nx; // Uniform mesh in space. pattern[p].y = h2 * (j + 0.5) / (double) ny; pattern[p].z = h3 * (k + 0.5) / (double) nz; theta = mapper_invoke(theta, mapper); // Morphes angle to get desired distribution. pattern[p].vx = V0 * sin(theta) * cos(phi * 2 * mc_pi); pattern[p].vy = V0 * sin(theta) * sin(phi * 2 * mc_pi); pattern[p].vz = V0 * cos(theta); pattern[p].rho = rho; pattern[p].rho = qDivM; if(!cpu_here) fprintf(fp, "%e %e %e %e %e %e %e %e\n", atan2(pattern[p].vx, pattern[p].vy) / mc_pi, acos(pattern[p]. vz / V0) / mc_pi, pattern[p].x, pattern[p].y, pattern[p].z, pattern[p].vx, pattern[p].vy, pattern[p].vz); ++p; } nMax = p; mapper_destroy(mapper); // Destroys mapper to free memory. if(!uniformWeight) // Correction of the weights of the markers. { double correction = 0; for(int i = 0; i < nMax; ++i) // Sets angular distribution of charge density. { pattern[i].rho = pattern[i].vz * pattern[i].vz; correction += pattern[i].rho; } correction = rho * nMax / correction; // Sets proper magnitudes. for(int i = 0; i < nMax; ++i) pattern[i].rho *= correction; } if(!cpu_here) fprintf(fp, "\nzone t=\"Mirrored\", f = point\n"); for(int i = 0; i < nMax && mirror; ++i) // Adds mirrored basic pattern to the group. { pattern[p] = pattern[p - nMax]; // Full copy of all fields. /// \todo Remix mirror pattern (line allocate not in form pppp/p'p'p'p'p'/p_rotp_rot, but interleave) to avoid explicit excitation of the modes with \f$ lambda = N_x h_x \f$. pattern[p].z = h3 * Nz - pattern[p].z; // Mirror: Z -> Z'. pattern[p].vz = -pattern[p].vz; // Mirror: Vz - Vz'. if(!cpu_here) fprintf(fp, "%e %e %e %e %e %e %e %e\n", atan2(pattern[p].vx, pattern[p].vy) / mc_pi, acos(pattern[p].vz / V0) / mc_pi, pattern[p].x, pattern[p].y, pattern[p].z, pattern[p].vx, pattern[p].vy, pattern[p].vz); ++p; } nMax = p; // Pattern += (basic pattern & mirror) rotated by 2*\pi*j/(nRotations + 1), j = 1, .., nRot. for(int l = 1; l <= nRotations; ++l) { if(!cpu_here) fprintf(fp, "\nzone t=\"Rotated by %d<sup>o</sup>\", f = point\n", (int) l * 360 / (nRotations + 1)); double phi = 2 * mc_pi * l / (double) (nRotations + 1); for(int k = 0; k < nMax; ++k) { pattern[p] = pattern[k]; // Full copy of all fields. pattern[p].vx = pattern[k].vx * cos(phi) - pattern[k].vy * sin(phi); // Rotation of the V vector. pattern[p].vy = pattern[k].vx * sin(phi) + pattern[k].vy * cos(phi); if(!cpu_here) fprintf(fp, "%e %e %e %e %e %e %e %e\n", atan2(pattern[p].vx, pattern[p].vy) / mc_pi, acos(pattern[p].vz / V0) / mc_pi, pattern[p].x, pattern[p].y, pattern[p].z, pattern[p].vx, pattern[p].vy, pattern[p].vz); ++p; } } if(!cpu_here) fclose(fp); if(p != patternSize) // Checks prediction of the pattern size. error("tag_photoInit: number of initialized markers is smaller than used one."); double xMin = +1e100, yMin = +1e100, zMin = +1e100; // Bounding box of the pattern. double xMax = -1e100, yMax = -1e100, zMax = -1e100; for(p = 0; p < patternSize; ++p) { xMin = (pattern[p].x < xMin) ? pattern[p].x : xMin; yMin = (pattern[p].y < yMin) ? pattern[p].y : yMin; zMin = (pattern[p].z < zMin) ? pattern[p].z : zMin; xMax = (pattern[p].x > xMax) ? pattern[p].x : xMax; yMax = (pattern[p].y > yMax) ? pattern[p].y : yMax; zMax = (pattern[p].z > zMax) ? pattern[p].z : zMax; } xMin -= 1e-4 * h1; // Extends bbox to ensure overlap and real check. yMin -= 1e-4 * h2; zMin -= 1e-4 * h3; xMax += 1e-4 * h1; yMax += 1e-4 * h2; zMax += 1e-4 * h3; double nPart = 0; for(int i = dmn_mesh_min[0]; i < dmn_mesh_max[0] + 1 - mc_have_x; i += Nx) // Fills domain by pattern. { for(int j = dmn_mesh_min[1]; j < dmn_mesh_max[1] + 1 - mc_have_y; j += Ny) { for(int k = dmn_mesh_min[2]; k < dmn_mesh_max[2] + 1 - mc_have_z; k += Nz) { if(((i * h1 + xMax < cpu_mesh_min[0] * h1 || i * h1 + xMin > cpu_mesh_max[0] * h1) && mc_have_x) || // Comparison by bounding box. ((j * h2 + yMax < cpu_mesh_min[1] * h2|| j * h2 + yMin > cpu_mesh_max[1] * h2) && mc_have_y) || ((k * h3 + zMax < cpu_mesh_min[2] * h3|| k * h3 + zMin > cpu_mesh_max[2] * h3) && mc_have_z)) continue; for(int l = 0; l < patternSize; ++l) { double x, y, z; x = pattern[l].x + i * h1; y = pattern[l].y + j * h2; z = pattern[l].z + k * h3; if(((x >= cpu_mesh_min[0] * h1 && x < cpu_mesh_max[0] * h1) || !mc_have_x) && // Fine filter for || setup. ((y >= cpu_mesh_min[1] * h2&& y < cpu_mesh_max[1] * h2) || !mc_have_y) && ((z >= cpu_mesh_min[2] * h3 && z < cpu_mesh_max[2] * h3) || !mc_have_z)) { marker_t *marker = plasma_marker(); // Gets pointer on uninitialized marker. marker->x = x; marker->y = y; marker->z = z; marker->vx = pattern[l].vx; marker->vy = pattern[l].vy; marker->vz = pattern[l].vz; marker->rho = pattern[l].rho; nPart++; } } } } } free(pattern); // Releases memory used to store stencil. return nPart; }