Public Member Functions | |
BLCMDfieldlines () | |
G4String | commandName () |
int | command (BLArgumentVector &argv, BLArgumentMap &namedArgs) |
void | defineNamedArgs () |
bool | isInWorld (G4ThreeVector &pos) |
void | generatePoints () |
void | generateOneFieldLine (G4ThreeVector &point) |
void | callback (int type) |
void | Draw () |
double | bmag (int i, int j) |
G4ThreeVector | point (int i, int j) |
int | excludeRadiusSq (double bmag) |
Private Attributes | |
G4double | t |
G4String | centerStr |
G4double | radius |
G4int | nLines |
G4double | dl |
G4String | color |
G4double | minField |
G4int | maxPoints |
G4int | subdivide |
G4int | N |
G4int | exit |
G4int | square |
G4int | Efield |
G4int | forever |
G4ThreeVector | center |
std::vector< G4ThreeVector > | points |
std::vector< G4ThreeVector > | argPoints |
std::vector< G4Polyline > | lines |
BLVisManager * | visManager |
BLGlobalField * | field |
int | ic |
double | dx |
double | scale |
G4RotationMatrix * | rot |
double | worldHalfHeight |
double | worldHalfWidth |
double | worldHalfLength |
BLCMDfieldlines::BLCMDfieldlines | ( | ) |
References BLCMDTYPE_OTHER, centerStr, color, dl, dx, Efield, exit, field, forever, ic, maxPoints, minField, N, nLines, radius, BLCommand::registerCommand(), rot, scale, BLCommand::setDescription(), BLCommand::setSynopsis(), square, subdivide, t, visManager, worldHalfHeight, worldHalfLength, and worldHalfWidth.
Referenced by command().
00094 : BLCommand(), BLCallback(), 00095 G4VUserVisAction(), points(), argPoints(), lines() 00096 { 00097 registerCommand(BLCMDTYPE_OTHER); 00098 setSynopsis("Display magnetic field lines."); 00099 setDescription("Field lines are drawn starting within a circle " 00100 "specified as center and radius (global coordinates); the plane of " 00101 "the circle is normal to the B field at its center. Field lines " 00102 "are distributed within the circle " 00103 "with a density inversely proportional to |B|. While it is attempted " 00104 "to keep their spacing as uniform as possible, there are both " 00105 "ambiguity and randomness involved in placing the lines within the " 00106 "circle. Lines are placed within the circle from its center outward, " 00107 "and if |B|<minField then no more lines are placed.\n\n" 00108 "nLines is only approximate, and the actual number of lines drawn will " 00109 "be within a factor of 2 of the value. Asking for fewer than 10 or " 00110 "more than 1000 lines is likely to be ineffective. Unnamed parameters " 00111 "can contain specific x,y,z values of points to start a field line.\n\n" 00112 "Lines are drawn in both directions starting from the plane of the " 00113 "circle, and each half-line stops when it again reaches that plane. " 00114 "Line drawing also stops " 00115 "whenever |B| is less than minField or when it leaves the world. If " 00116 "you are interested in field lines far outside the magnets, you may " 00117 "need to add some object with a large value of x, y, and/or z, in " 00118 "order to expand the world volume. " 00119 "With dl=1 and subdivide=10, the accuracy of their meeting is usually " 00120 "better than 0.1 mm after several tens of meters.\n\n" 00121 "This command does nothing if not in visualization mode. For best " 00122 "results, use the Open Inventor viewer, and give your magnets a " 00123 "transparency of about 0.3 (e.g. color=1,1,1,0.3); if necessary, use " 00124 "the right-button menu to set the DrawStyle/TransparencyType to " 00125 "'sorted object add'. With field lines in 3-d, you will want the " 00126 "ability to zoom, rotate, and move the image interactively.\n\n" 00127 "Setting exit=1 will display the system and the field lines, without " 00128 "any event tracks; exiting the viewer will then exit the program. " 00129 "With exit=0, field lines are drawn only at the end of the first run."); 00130 00131 t = 0.0*ns; 00132 centerStr = "0,0,0"; 00133 radius = 100.0*mm; 00134 nLines = 100; 00135 dl = 10.0*mm; 00136 color="1,1,1"; 00137 minField = 0.001*tesla; 00138 maxPoints = 10000; 00139 subdivide = 10; 00140 N = 128; 00141 exit = 0; 00142 square = 0; 00143 Efield = 0; 00144 forever = 0; 00145 visManager = 0; // set in callback(4) 00146 field = 0; // set in callback(4) 00147 ic = N/2; 00148 dx = 0.0; 00149 scale = ic/4; 00150 rot = 0; // set in callback(4) 00151 worldHalfHeight = worldHalfWidth = worldHalfLength = 0.0; 00152 }
G4String BLCMDfieldlines::commandName | ( | ) | [inline, virtual] |
int BLCMDfieldlines::command | ( | BLArgumentVector & | argv, | |
BLArgumentMap & | namedArgs | |||
) | [virtual] |
Implements BLCommand.
References argPoints, BLCMDfieldlines(), center, centerStr, dx, Efield, BLCommand::getList(), BLManager::getObject(), BLCommand::handleNamedArgs(), ic, minField, N, BLCommand::print(), BLCommand::printError(), radius, BLManager::registerCallback(), and scale.
00182 { 00183 handleNamedArgs(namedArgs); 00184 00185 argPoints.clear(); 00186 for(unsigned i=0; i<argv.size(); ++i) { 00187 std::vector<double> list = getList(argv[i],","); 00188 if(list.size() != 3) { 00189 printError("Invalid point: %s",argv[i].c_str()); 00190 continue; 00191 } 00192 argPoints.push_back(G4ThreeVector(list[0],list[1],list[2])); 00193 } 00194 00195 if(N < 10 || N > 16383) 00196 printError("Invalid N: < 10 or > 16383"); 00197 ic = N/2; 00198 dx = radius/ic; 00199 scale = ic/4; 00200 00201 std::vector<double> tmp = getList(centerStr,","); 00202 if(tmp.size() != 3) 00203 printError("Invald value for center '%s'",centerStr.c_str()); 00204 else 00205 center = G4ThreeVector(tmp[0],tmp[1],tmp[2]); 00206 00207 if(Efield) 00208 minField = minField/tesla*(megavolt/meter); 00209 00210 print(""); 00211 00212 BLManager::getObject()->registerCallback(new BLCMDfieldlines(*this),4); 00213 00214 return 0; 00215 }
void BLCMDfieldlines::defineNamedArgs | ( | ) | [virtual] |
Reimplemented from BLCommand.
References BLCommand::argDouble(), BLCommand::argInt(), BLCommand::argString(), centerStr, color, dl, Efield, exit, forever, maxPoints, minField, N, nLines, radius, square, subdivide, and t.
00218 { 00219 argDouble(t,"t","Time at which field lines are plotted (0 ns).",ns); 00220 argString(centerStr,"center","Center of circle (x,y,z) to start lines (mm, global)."); 00221 argDouble(radius,"radius", "Radius of circle to start lines (mm).",mm); 00222 argInt(nLines,"nLines","Approximate number of field lines to plot (100)."); 00223 argDouble(dl,"dl","Interval between points plotted (10 mm).",mm); 00224 argString(color,"color","Color of field lines (white=\"1,1,1\")."); 00225 argDouble(minField,"minField","Minimum B field (0.001 tesla)",tesla); 00226 argInt(maxPoints,"maxPoints","Max # points plotted in a line (10000)."); 00227 argInt(subdivide,"subdivide","# field integration points between plotted points (10)."); 00228 argInt(N,"N","# grid points in x and y (128)."); 00229 argInt(exit,"exit","Set nonzero to display field lines and exit (0)."); 00230 argInt(square,"square","Set nonzero to start from square rather than circle (0)."); 00231 argInt(Efield,"Efield","Set nonzero to draw E field (0); minField is in MegaVolts/meter."); 00232 argInt(forever,"forever","Set nonzero to draw lines until maxPoints is reached or |B|<minField, not stopping at the initial plane."); 00233 }
bool BLCMDfieldlines::isInWorld | ( | G4ThreeVector & | pos | ) |
References worldHalfHeight, worldHalfLength, and worldHalfWidth.
Referenced by generateOneFieldLine().
00236 { 00237 return fabs(pos[0]) <= worldHalfWidth && 00238 fabs(pos[1]) <= worldHalfHeight && 00239 fabs(pos[2]) <= worldHalfLength; 00240 }
void BLCMDfieldlines::generatePoints | ( | ) |
References BLAssert, bmag(), distance2, exclude, excludeRadiusSq(), ic, index, N, point(), points, and square.
Referenced by callback().
00396 { 00397 /* This routine places points for field lines into the circle in the 00398 plane normal to B at center. 00399 00400 The basic algorithm is to cover the circle with an NxN grid, to 00401 place points in the grid, and then to exclude grid points within 00402 a given radius of the point; the radius depends on the value of B 00403 at the point just placed. The first point is placed at the center, 00404 and successive points are placed at the non-excluded grid point 00405 closest to the center. 00406 */ 00407 #define index(i,j) (i*N+j) 00408 #define distance2(i1,j1,i2,j2) ((i1-i2)*(i1-i2) + (j1-j2)*(j1-j2)) 00409 #define exclude(I,J,D2) \ 00410 for(int i=0; i<N; ++i) { \ 00411 for(int j=0; j<N; ++j) { \ 00412 if(distance2(i,j,I,J) <= D2) \ 00413 grid[index(i,j)] = 0; \ 00414 } \ 00415 } 00416 00417 BLAssert(N >= 10 && N <= 16383); // ensure distance2() fits in an int 00418 00419 unsigned char *grid = new unsigned char[N*N]; 00420 00421 // initialize grid(), excluding points outside radius 00422 int excludeSq = ic*ic; 00423 for(int i=0; i<N; ++i) { 00424 for(int j=0; j<N; ++j) { 00425 if(!square && distance2(i,j,ic,ic) > excludeSq) 00426 grid[index(i,j)] = 0; 00427 else 00428 grid[index(i,j)] = 1; 00429 } 00430 } 00431 00432 // place as many points as will fit, starting with (ic,ic) 00433 int imin=ic, jmin=ic; 00434 do { 00435 // place this point 00436 G4ThreeVector p = point(imin,jmin); 00437 points.push_back(p); 00438 exclude(imin,jmin,excludeRadiusSq(bmag(i,j))); 00439 00440 // find un-excluded point closest to (ic,ic) 00441 int d2min=N*N; 00442 imin = -1; 00443 for(int i=0; i<N; ++i) { 00444 for(int j=0; j<N; ++j) { 00445 if(grid[index(i,j)] == 0) continue; 00446 int d2=distance2(i,j,ic,ic); 00447 if(d2 < d2min) { 00448 d2min = d2; 00449 imin = i; 00450 jmin = j; 00451 } 00452 } 00453 } 00454 } while(imin >= 0); 00455 }
void BLCMDfieldlines::generateOneFieldLine | ( | G4ThreeVector & | point | ) |
References B, BLAssert, color, dl, E, Efield, field, forever, BLGlobalField::getFieldValue(), BLCommand::getVisAttrib(), isInWorld(), lines, maxPoints, minField, subdivide, and t.
Referenced by callback().
00323 { 00324 BLAssert(subdivide > 0); 00325 00326 double step = dl/subdivide; 00327 G4ThreeVector B, E, norm; 00328 G4ThreeVector pos=point; 00329 if(!isInWorld(pos)) return; 00330 field->getFieldValue(pos,t,B,E); 00331 if(Efield) B = E; 00332 if(B.mag() < minField) return; 00333 // norm is the normal to the plane perpendicular to B at this point. 00334 norm = B.unit(); 00335 00336 G4Polyline line; 00337 line.SetVisAttributes(getVisAttrib(color)); 00338 00339 // half-line on positive side of norm 00340 pos = point; 00341 line.push_back(pos); 00342 for(int n=0; n<maxPoints; ++n) { 00343 for(int j=0; j<subdivide; ++j) { 00344 if(!isInWorld(pos)) goto end1; 00345 if(forever == 0 && (pos-point)*norm < 0.0) break; 00346 field->getFieldValue(pos,t,B,E); 00347 if(Efield) B = E; 00348 if(B.mag() < minField) goto end1; 00349 pos += step*B.unit(); 00350 } 00351 line.push_back(pos); 00352 if(forever == 0 && (pos-point)*norm < 0.0) break; 00353 } 00354 end1: if(line.size() > 1) lines.push_back(line); 00355 line.clear(); 00356 00357 // half-line on negative side of norm 00358 pos = point; 00359 line.push_back(pos); 00360 for(int n=0; n<maxPoints; ++n) { 00361 for(int j=0; j<subdivide; ++j) { 00362 if(!isInWorld(pos)) goto end2; 00363 if(forever == 0 && (pos-point)*norm > 0.0) break; 00364 field->getFieldValue(pos,t,B,E); 00365 if(Efield) B = E; 00366 if(B.mag() < minField) goto end2; 00367 pos -= step*B.unit(); 00368 } 00369 line.push_back(pos); 00370 if(forever == 0 && (pos-point)*norm > 0.0) break; 00371 } 00372 end2: if(line.size() > 1) lines.push_back(line); 00373 }
void BLCMDfieldlines::callback | ( | int | type | ) | [virtual] |
Reimplemented from BLCallback.
References argPoints, B, BLAssert, bmag(), center, Draw(), E, Efield, exit, field, g4bl_exit(), generateOneFieldLine(), generatePoints(), BLGlobalField::getFieldValue(), BLGroup::getHeight(), BLGroup::getLength(), BLGlobalField::getObject(), BLVisManager::getObject(), BLGroup::getWidth(), BLGroup::getWorld(), ic, lines, minField, nLines, points, radius, rot, scale, t, visManager, worldHalfHeight, worldHalfLength, and worldHalfWidth.
00243 { 00244 // initialize variables that must be delayed. 00245 visManager = BLVisManager::getObject(); 00246 if(!visManager) return; 00247 field = BLGlobalField::getObject(); 00248 BLGroup *world = BLGroup::getWorld(); 00249 worldHalfHeight = world->getHeight()/2.0; 00250 worldHalfWidth = world->getWidth()/2.0; 00251 worldHalfLength = world->getLength()/2.0; 00252 00253 if(radius > 0.0 && nLines > 0) { 00254 // get rotation from Z axis to B at center. 00255 G4ThreeVector B, E, axis(0.0,0.0,1.0); 00256 field->getFieldValue(center,t,B,E); 00257 if(Efield) B = E; 00258 if(B.mag() < minField) return; 00259 axis = axis.cross(B.unit()); 00260 if(axis.mag() > 1.0e-6) 00261 rot = new G4RotationMatrix(axis.unit(),acos(B.unit()[2])); 00262 else 00263 rot = new G4RotationMatrix(); 00264 G4ThreeVector test = *rot * G4ThreeVector(0.0,0.0,1.0); 00265 BLAssert((test-B.unit()).mag()<1.0e-6 || (test+B.unit()).mag()<1.0e-6); 00266 00267 fflush(stdout); 00268 fprintf(stderr,"\n"); 00269 00270 // generate the points from which field lines are drawn 00271 // loop over scale to get within a factor of 2 of nLines. 00272 scale = (ic/4)*bmag(ic,ic); 00273 for(int i=0; i<15; ++i) { 00274 fprintf(stderr,"fieldlines: trying for ~ %d field lines...", 00275 nLines); 00276 points.clear(); 00277 generatePoints(); 00278 int n = points.size(); 00279 fprintf(stderr," got %d\n",n); 00280 if(n <= 0) return; 00281 if(n < nLines/2) 00282 scale = 0.75*scale; 00283 else if(n > nLines*2) 00284 scale = 1.2*scale; 00285 else 00286 break; 00287 } 00288 } 00289 00290 // add argPoints 00291 for(unsigned i=0; i<argPoints.size(); ++i) 00292 points.push_back(argPoints[i]); 00293 00294 // generate the field lines. 00295 fprintf(stderr,"fieldlines: generating %d field lines...", 00296 (int)points.size()); 00297 lines.clear(); 00298 for(unsigned i=0; i<points.size(); ++i) { 00299 generateOneFieldLine(points[i]); 00300 } 00301 fprintf(stderr," done.\n\n"); 00302 00303 visManager->SetUserAction(this, 00304 G4VisExtent(-DBL_MAX,DBL_MAX,-DBL_MAX,DBL_MAX,-DBL_MAX,DBL_MAX)); 00305 00306 // draw the field lines 00307 Draw(); 00308 00309 if(exit) { 00310 G4UImanager* UI = G4UImanager::GetUIpointer(); 00311 UI->ApplyCommand("/vis/viewer/update"); 00312 g4bl_exit(0); 00313 } 00314 }
void BLCMDfieldlines::Draw | ( | ) |
References lines, and visManager.
Referenced by callback().
00317 { 00318 for(unsigned i=0; i<lines.size(); ++i) 00319 visManager->Draw(lines[i]); 00320 }
double BLCMDfieldlines::bmag | ( | int | i, | |
int | j | |||
) |
References B, E, Efield, field, BLGlobalField::getFieldValue(), point(), and t.
Referenced by callback(), and generatePoints().
00376 { 00377 G4ThreeVector p(point(i,j)),B, E; 00378 field->getFieldValue(p,t,B,E); 00379 if(Efield) B = E; 00380 return B.mag(); 00381 }
G4ThreeVector BLCMDfieldlines::point | ( | int | i, | |
int | j | |||
) |
int BLCMDfieldlines::excludeRadiusSq | ( | double | bmag | ) |
G4double BLCMDfieldlines::t [private] |
Referenced by BLCMDfieldlines(), bmag(), callback(), defineNamedArgs(), and generateOneFieldLine().
G4String BLCMDfieldlines::centerStr [private] |
Referenced by BLCMDfieldlines(), command(), and defineNamedArgs().
G4double BLCMDfieldlines::radius [private] |
Referenced by BLCMDfieldlines(), callback(), command(), and defineNamedArgs().
G4int BLCMDfieldlines::nLines [private] |
Referenced by BLCMDfieldlines(), callback(), and defineNamedArgs().
G4double BLCMDfieldlines::dl [private] |
Referenced by BLCMDfieldlines(), defineNamedArgs(), and generateOneFieldLine().
G4String BLCMDfieldlines::color [private] |
Referenced by BLCMDfieldlines(), defineNamedArgs(), and generateOneFieldLine().
G4double BLCMDfieldlines::minField [private] |
Referenced by BLCMDfieldlines(), callback(), command(), defineNamedArgs(), excludeRadiusSq(), and generateOneFieldLine().
G4int BLCMDfieldlines::maxPoints [private] |
Referenced by BLCMDfieldlines(), defineNamedArgs(), and generateOneFieldLine().
G4int BLCMDfieldlines::subdivide [private] |
Referenced by BLCMDfieldlines(), defineNamedArgs(), and generateOneFieldLine().
G4int BLCMDfieldlines::N [private] |
Referenced by BLCMDfieldlines(), command(), defineNamedArgs(), excludeRadiusSq(), and generatePoints().
G4int BLCMDfieldlines::exit [private] |
Referenced by BLCMDfieldlines(), callback(), and defineNamedArgs().
G4int BLCMDfieldlines::square [private] |
Referenced by BLCMDfieldlines(), defineNamedArgs(), and generatePoints().
G4int BLCMDfieldlines::Efield [private] |
Referenced by BLCMDfieldlines(), bmag(), callback(), command(), defineNamedArgs(), and generateOneFieldLine().
G4int BLCMDfieldlines::forever [private] |
Referenced by BLCMDfieldlines(), defineNamedArgs(), and generateOneFieldLine().
G4ThreeVector BLCMDfieldlines::center [private] |
Referenced by callback(), command(), and point().
std::vector<G4ThreeVector> BLCMDfieldlines::points [private] |
Referenced by callback(), and generatePoints().
std::vector<G4ThreeVector> BLCMDfieldlines::argPoints [private] |
Referenced by callback(), and command().
std::vector<G4Polyline> BLCMDfieldlines::lines [private] |
Referenced by callback(), Draw(), and generateOneFieldLine().
BLVisManager* BLCMDfieldlines::visManager [private] |
Referenced by BLCMDfieldlines(), callback(), and Draw().
BLGlobalField* BLCMDfieldlines::field [private] |
Referenced by BLCMDfieldlines(), bmag(), callback(), and generateOneFieldLine().
int BLCMDfieldlines::ic [private] |
Referenced by BLCMDfieldlines(), callback(), command(), generatePoints(), and point().
double BLCMDfieldlines::dx [private] |
Referenced by BLCMDfieldlines(), command(), and point().
double BLCMDfieldlines::scale [private] |
Referenced by BLCMDfieldlines(), callback(), command(), and excludeRadiusSq().
G4RotationMatrix* BLCMDfieldlines::rot [private] |
Referenced by BLCMDfieldlines(), callback(), and point().
double BLCMDfieldlines::worldHalfHeight [private] |
Referenced by BLCMDfieldlines(), callback(), and isInWorld().
double BLCMDfieldlines::worldHalfWidth [private] |
Referenced by BLCMDfieldlines(), callback(), and isInWorld().
double BLCMDfieldlines::worldHalfLength [private] |
Referenced by BLCMDfieldlines(), callback(), and isInWorld().