SIMION® Industry standard charged particle optics simulation software.
Newsflash: SIMION 8.1.1 is here: dielectrics, new examples + preview of permeability; ASMS2012 posters; major improvements to enhanced surface accuracy feature coming soon (details in Check for Updates).
About | Documentation | Community/Support | Downloads | Ordering

SL Libraries -- C++

The SIMION SL™ Toolkit (version 1.2.1.0 - 2004-11-09)

pa.h

Go to the documentation of this file.
00001 /** 00002 * @mainpage 00003 * 00004 * This is the C++ version of the SIMION SL Libraies. 00005 * It provides libraries for manipulating SIMION potential array (PA/PA?) 00006 * files and also includes SL Remote for remotely calling C++ code from SL 00007 * user programs. 00008 * 00009 * <a href="namespacesimion.html">simion namespace members</a> 00010 * 00011 * COMPATIBILITY 00012 * 00013 * The PA class was extended and changed significantly between the SL 00014 * Toolkit 1.0 and 1.2. Refer to the SL Toolkit Change Log for 00015 * details. 00016 * 00017 * @author David Manura (c) 2003-2004 Scientific Instrument Services, Inc. 00018 * Licensed under the terms of the SIMION SL Toolkit. 00019 * Created 2003-11. 00020 */ 00021 00022 /** 00023 * @file pa.h 00024 * Header file for SIMION potential array class. 00025 * 00026 * This class provides methods for reading, writing, and 00027 * manipulating SIMION potential array (PA/PA?) files. 00028 * 00029 * Refer to page D-5 of the SIMION 7.0 manual for info on the 00030 * %PA file format. 00031 * 00032 * You may want to disable assertions (via the macro NDEBUG) 00033 * if speed is critical. 00034 * 00035 * @author (c) 2003-2004 Scientific Instrument Services, Inc. David Manura. 00036 * Licensed under the terms of the SIMION SL Toolkit. 00037 * $Revision: 1.7 $ $Date: 2004/11/08 17:55:28 $ Created 2003-11. 00038 * 00039 */ 00040 00041 00042 #ifndef SIMIONSL_PA_H 00043 #define SIMIONSL_PA_H 00044 00045 #include "util.h" 00046 00047 #include <iostream> 00048 #include <vector> 00049 #include <string> 00050 00051 /** 00052 * The SIMION namespace for the SIMION SL Toolkit. 00053 * 00054 * This namespace holds all SIMION SL Toolkit classes and members. 00055 * Example: 00056 * 00057 * @code 00058 * #include <simion/pa.h> 00059 * #include <iostream> 00060 * using namespace simion; 00061 * using namespace std; 00062 * int main() { 00063 * PA pa(); 00064 * cout << pa.header_patxt() << endl; 00065 * return 0; 00066 * } 00067 * @endcode 00068 */ 00069 00070 namespace simion 00071 { 00072 00073 /** 00074 * symmetry constants. 00075 */ 00076 enum symmetry_t 00077 { 00078 /// cylindrical symmetry 00079 CYLINDRICAL = 0, 00080 /// planar symmetry 00081 PLANAR = 1 00082 }; 00083 00084 /** 00085 * potential array field types. 00086 */ 00087 enum field_t 00088 { 00089 /// electrostatic 00090 ELECTROSTATIC = 0, 00091 /// magnetic 00092 MAGNETIC = 1 00093 }; 00094 00095 /** 00096 * Bits definitions for the "mirror" field in the header of a PA file. 00097 * @see PAHeader. 00098 */ 00099 enum mirror_t 00100 { 00101 /// array mirrored in x 00102 MIRROR_X = 1, 00103 /// array mirrored in y 00104 MIRROR_Y = 2, 00105 /// array mirrored in z 00106 MIRROR_Z = 4, 00107 /// is magnetic potential array (else assumed electrostatic array) 00108 MAGNETIC_PA = 8 00109 }; 00110 00111 00112 class PA; 00113 class PAArgs; 00114 class PAHeader; 00115 class PAFormat; 00116 class PAPointInfo; 00117 class PATextHeader; 00118 class PATextHandler; 00119 class Vector3R; 00120 class Task; // extern 00121 class PATextImpl_; 00122 00123 /** 00124 * Class representing a three-dimensional vector of real components 00125 * (x, y, z). 00126 */ 00127 class Vector3R 00128 { 00129 public: 00130 /** Constructor. */ 00131 Vector3R(double x=0.0, double y=0.0, double z=0.0); 00132 00133 /** Set x, y, z components simultaneously. */ 00134 void set(double x, double y, double z); 00135 00136 /** Get x component. */ 00137 double x() const; 00138 /** Set x component. */ 00139 void x(double val); 00140 00141 /** Get y component. */ 00142 double y() const; 00143 /** Set y component. */ 00144 void y(double val); 00145 00146 /** Get z omponent. */ 00147 double z() const; 00148 /** Set z component. */ 00149 void z(double val); 00150 00151 private: 00152 double x_, y_, z_; 00153 }; 00154 00155 /** 00156 * Constainer class representing a single data point in a %PA. 00157 * This is used as a return value in certain PA methods 00158 * (e.g. point). 00159 */ 00160 class PAPoint 00161 { 00162 public: 00163 /** Whether point is an electrode. */ 00164 bool electrode; 00165 /** Potential of point (volts or mags). */ 00166 double potential; 00167 00168 /** 00169 * Constructor. 00170 * @param electrode_ whether point is an electrode. 00171 * @param potential_ potential in volts or mags. 00172 */ 00173 PAPoint(bool electrode_, double potential_) : 00174 electrode(electrode_), potential(potential_) { } 00175 00176 }; 00177 00178 //IMPROVE: support pasharp? 00179 00180 /** 00181 * Container class for a set of potential array attributes. 00182 * This allows any subset of the attributes to be passed at once into 00183 * a given function, somewhat like named parameters in other languages. 00184 * For example, 00185 * 00186 * @code 00187 * PA pa(PAArgs().nx(10).ny(20).symmetry(CYLINDRICAL)); 00188 * @endcode 00189 * 00190 * See the PA class for details on the meaning of these attributes. 00191 * Additional attributes are 00192 * 00193 * - fast_adjustable - whether array is fast adjustable 00194 * - enable_points - whether to load/save point data (in addition to header) 00195 * 00196 * Each attribute has three methods: 00197 * 00198 * - get value 00199 * - get whether value is defined 00200 * - set value 00201 * 00202 * The typical usage by the caller is 00203 * 00204 * @code 00205 * args.nx(100); 00206 * @endcode 00207 * 00208 * The typical usage by the receiver is 00209 * 00210 * @code 00211 * if(args.nx_defined()) cout << args.nx(); // do something 00212 * @endcode 00213 * 00214 * Note that this class performs no checking on values. Checking is 00215 * the responsibility of the PA class. 00216 * 00217 * @see PA 00218 */ 00219 class PAArgs 00220 { 00221 public: 00222 /** Identifiers for arguments. */ 00223 enum arg_t { 00224 A_file = (1 << 0), 00225 A_mode = (1 << 1), 00226 A_max_voltage = (1 << 2), 00227 A_nx = (1 << 3), 00228 A_ny = (1 << 4), 00229 A_nz = (1 << 5), 00230 A_mirror_x = (1 << 6), 00231 A_mirror_y = (1 << 7), 00232 A_mirror_z = (1 << 8), 00233 A_field_type = (1 << 9), 00234 A_symmetry = (1 << 10), 00235 A_ng = (1 << 11), 00236 A_fast_adjustable = (1 << 12), 00237 A_enable_points = (1 << 13) 00238 }; 00239 00240 /*** 00241 * Constructor. 00242 */ 00243 PAArgs() : 00244 file_ (), 00245 mode_ (-1), 00246 max_voltage_ (100000), 00247 nx_ (100), 00248 ny_ (100), 00249 nz_ (1), 00250 mirror_x_ (false), 00251 mirror_y_ (false), 00252 mirror_z_ (false), 00253 field_type_ (ELECTROSTATIC), 00254 symmetry_ (PLANAR), 00255 ng_ (100), 00256 fast_adjustable_ (false), 00257 enable_points_ (true), 00258 valid_ (0) /// flags marking valid attributes (OR of arg_t) 00259 { } 00260 00261 // Each attribute is given a set of three methods 00262 // defined by the below macro. 00263 00264 # ifndef DOXYGEN_SHOULD_SKIP_THIS 00265 # define SL_MAKE_METHODS(name, type) \ 00266 /** Get name attribute. */ \ 00267 type name() const { return name ## _; } \ 00268 /** Get whether name attribute defined. */ \ 00269 bool name ## _defined() const { return is_set_(A_ ## name); } \ 00270 /** Set name attribute. */ \ 00271 PAArgs& name(type val) { name ## _ = val; set_(A_ ## name); return *this; } 00272 # endif 00273 00274 SL_MAKE_METHODS(file, std::string) 00275 SL_MAKE_METHODS(mode, int) 00276 SL_MAKE_METHODS(max_voltage, double) 00277 SL_MAKE_METHODS(nx, int) 00278 SL_MAKE_METHODS(ny, int) 00279 SL_MAKE_METHODS(nz, int) 00280 SL_MAKE_METHODS(mirror_x, bool) 00281 SL_MAKE_METHODS(mirror_y, bool) 00282 SL_MAKE_METHODS(mirror_z, bool) 00283 SL_MAKE_METHODS(field_type, field_t) 00284 SL_MAKE_METHODS(symmetry, symmetry_t) 00285 SL_MAKE_METHODS(ng, int) 00286 SL_MAKE_METHODS(fast_adjustable, bool) 00287 SL_MAKE_METHODS(enable_points, bool) 00288 00289 /** Gets and OR-ed bit field of arguments defined. */ 00290 int defined(); 00291 00292 # undef SL_MAKE_METHODS 00293 00294 private: 00295 00296 std::string file_; 00297 int mode_; 00298 double max_voltage_; 00299 int nx_; 00300 int ny_; 00301 int nz_; 00302 bool mirror_x_; 00303 bool mirror_y_; 00304 bool mirror_z_; 00305 field_t field_type_; 00306 symmetry_t symmetry_; 00307 int ng_; 00308 bool fast_adjustable_; 00309 bool enable_points_; 00310 00311 int valid_; // bitwise OR of arg_t flags 00312 00313 void set_(arg_t val); 00314 bool is_set_(arg_t val) const; 00315 }; 00316 00317 00318 //IMRPOVE:implement setters too? 00319 /** 00320 * Class that implements the header section of a %PA file format. 00321 * 00322 * Note: This class is normally not used by SL Toolkit users. The 00323 * class provides a low-level interface to the PA file format, 00324 * whereas the PA class provides a higher level interface to %PA files. 00325 * 00326 * The binary representation of this class is designed to be writen 00327 * to the header section of the PA file. 00328 * 00329 * Refer to page D-5 of the SIMION 7.0 manual for info on the 00330 * %PA file format. 00331 */ 00332 class PAHeader 00333 { 00334 public: 00335 /** Mode (always -1) */ 00336 int mode_; 00337 00338 /** Symmetry (PLANAR or CYLINDRICAL) */ 00339 int symmetry_; 00340 00341 /** max voltage limit */ 00342 double max_voltage_; 00343 00344 /** number of grid points in x direction */ 00345 int nx_; 00346 00347 /** number of grid points in y direction */ 00348 int ny_; 00349 00350 /** number of grid points in z direction */ 00351 int nz_; 00352 00353 /** 00354 * first three lowest bits are the x, y, and z 00355 * mirroring respectively. Remaining bits are 00356 * the ng magnetic scaling factor. 00357 */ 00358 int mirror_; 00359 00360 /** 00361 * Constructor. 00362 */ 00363 PAHeader() : 00364 mode_ (-1), 00365 symmetry_ (PLANAR), 00366 max_voltage_ (100000.0), 00367 nx_ (100), 00368 ny_ (100), 00369 nz_ (1), 00370 mirror_ (0 + (100<<4)) 00371 { } 00372 00373 /** 00374 * Constructor. 00375 * @param mode mode (always -1) 00376 * @param field_type field type (ELECTROSTATIC or MAGNETIC) 00377 * @param symmetry symmetry (PLANAR or CYLINDRICAL) 00378 * @param max_voltage max voltage limit 00379 * @param nx number of grid points in x direction 00380 * @param ny number of grid points in y direction 00381 * @param nz number of grid points in z direction 00382 * @param mirror_x whether x mirroring is enabled 00383 * @param mirror_y whether y mirroring is enabled 00384 * @param mirror_z whether z mirroring is enabled 00385 * @param ng magnetic scaling factor 00386 */ 00387 PAHeader( 00388 int mode, 00389 field_t field_type, 00390 symmetry_t symmetry, 00391 double max_voltage, 00392 int nx, 00393 int ny, 00394 int nz, 00395 bool mirror_x, 00396 bool mirror_y, 00397 bool mirror_z, 00398 int ng 00399 ); 00400 00401 /** Get whether x mirroring is enabled. */ 00402 bool mirror_x() const; 00403 /** Get whether y mirroring is enabled. */ 00404 bool mirror_y() const; 00405 /** Get whether z mirroring is enabled. */ 00406 bool mirror_z() const; 00407 00408 /** Get whether field type identifier. */ 00409 field_t field_type() const; 00410 00411 /** Get ng magnetic scaling factor. */ 00412 int ng() const; 00413 00414 /** Get symmetry identifier. */ 00415 symmetry_t symmetry() const; 00416 }; 00417 00418 /** 00419 * header used by the PATXT format 00420 */ 00421 class PATextHeader : public PAArgs 00422 { 00423 public: 00424 /** identifiers for data columns */ 00425 enum point_column_t 00426 { 00427 PI_X = (1<<0), 00428 PI_Y = (1<<1), 00429 PI_Z = (1<<2), 00430 PI_IS_ELECTRODE = (1<<3), 00431 PI_POTENTIAL = (1<<4), 00432 PI_RAW_VALUE = (1<<5), 00433 PI_FIELD_X = (1<<6), 00434 PI_FIELD_Y = (1<<7), 00435 PI_FIELD_Z = (1<<8), 00436 00437 PI_FIELD = PI_FIELD_X | PI_FIELD_Y | PI_FIELD_Z, 00438 PI_XYZ = PI_X | PI_Y | PI_Z 00439 }; 00440 00441 /** 00442 * Constructor. 00443 */ 00444 PATextHeader() : columns_enabled_(0) { } 00445 00446 /** 00447 * Gets whether data point column is enabled. 00448 */ 00449 bool is_column_enabled(point_column_t t) const; 00450 00451 /** 00452 * Set data point column at given index. 00453 */ 00454 void enable_column(int idx, point_column_t t); 00455 00456 /** 00457 * Get set of enabled columns (as OR'ed bitfield). 00458 */ 00459 int enabled_columns() const; 00460 00461 /** 00462 * Get value at given data point column. 00463 */ 00464 point_column_t column(int idx) const; 00465 00466 /** 00467 * Get number of data point columns. 00468 */ 00469 int column_count() const; 00470 00471 private: 00472 int columns_enabled_; 00473 std::vector<point_column_t> columns_; 00474 }; 00475 00476 /** 00477 * Container class for options passed to PA.save(). 00478 * 00479 * Like PAArgs, this simulated named parameter passing. 00480 */ 00481 class PAFormat 00482 { 00483 public: 00484 /** file formatting */ 00485 enum format_t { 00486 /// normal SIMION binary format 00487 BINARY, 00488 /// ASCII PATXT format 00489 ASCII 00490 }; 00491 00492 /** what the data values represent */ 00493 enum values_t { 00494 /// scalar potentials 00495 POTENTIAL, 00496 /// field vectors 00497 FIELD 00498 }; 00499 00500 /** 00501 * Constructor. 00502 * format_t file formatting 00503 * double sampling interval 00504 * enable_header whether the header is enabled (FIX: ASCII format only?) 00505 * enable_data whether the data points are enabled (FIX: ASCII format only?) 00506 * enable_coords whether the (x,y,z) coordinates are enabled for 00507 * data points (only for ASCII format with enable_data set) 00508 * values_t what the data points contain (ASCII format only. 00509 * POTENTIAL is assumed for binary format) 00510 */ 00511 PAFormat( 00512 format_t format = BINARY, 00513 double dx = 1, 00514 bool enable_header = true, 00515 bool enable_data = true, 00516 bool enable_coords = true, 00517 values_t values = POTENTIAL) 00518 : 00519 format_ (format), 00520 dx_ (dx), 00521 enable_header_ (enable_header), 00522 enable_data_ (enable_data), 00523 enable_coords_ (enable_coords), 00524 values_ (values) 00525 { } 00526 00527 # ifndef DOXYGEN_SHOULD_SKIP_THIS 00528 # define SL_MAKE_METHODS(name, type) \ 00529 /** Get name. */ \ 00530 type name() const { return name ## _; } \ 00531 /** Set name. */ \ 00532 PAFormat& name(type val) { name ## _ = val; return *this;} 00533 # endif 00534 00535 SL_MAKE_METHODS(format, format_t) 00536 SL_MAKE_METHODS(dx, double) 00537 SL_MAKE_METHODS(enable_header, bool) 00538 SL_MAKE_METHODS(enable_data, bool) 00539 SL_MAKE_METHODS(enable_coords, bool) 00540 SL_MAKE_METHODS(values, values_t) 00541 00542 # undef SL_MAKE_METHODS 00543 00544 private: 00545 format_t format_; 00546 double dx_; 00547 bool enable_header_; 00548 bool enable_data_; 00549 bool enable_coords_; 00550 values_t values_; 00551 }; 00552 00553 00554 /** 00555 * Container class used by PATextHandler to store information 00556 * about a single data point mentioned in a PATXT file. 00557 * 00558 * NOTE: This class is typically not used directly be SL Toolkit users. 00559 * See the PA class instead. 00560 */ 00561 class PAPointInfo 00562 { 00563 private: 00564 int x_; 00565 int y_; 00566 int z_; 00567 bool is_electrode_; 00568 double potential_; 00569 double raw_value_; 00570 double field_x_; 00571 double field_y_; 00572 double field_z_; 00573 00574 int enabled_; // ORed point_column_t 00575 public: 00576 PAPointInfo() : 00577 x_ (0), 00578 y_ (0), 00579 z_ (0), 00580 is_electrode_ (false), 00581 potential_ (0.0), 00582 raw_value_ (0.0), 00583 field_x_ (0.0), 00584 field_y_ (0.0), 00585 field_z_ (0.0), 00586 enabled_ (0) 00587 { } 00588 00589 # ifndef DOXYGEN_SHOULD_SKIP_THIS 00590 # define SL_MAKE_METHODS(name, type) \ 00591 /** Get name. */ \ 00592 type name() const { return name ## _; } \ 00593 /** Set name. */ \ 00594 void name(type val) { name ## _ = val; } 00595 # endif 00596 00597 SL_MAKE_METHODS(x, int) 00598 SL_MAKE_METHODS(y, int) 00599 SL_MAKE_METHODS(z, int) 00600 SL_MAKE_METHODS(is_electrode, bool) 00601 SL_MAKE_METHODS(potential, double) 00602 SL_MAKE_METHODS(raw_value, double) 00603 SL_MAKE_METHODS(field_x, double) 00604 SL_MAKE_METHODS(field_y, double) 00605 SL_MAKE_METHODS(field_z, double) 00606 SL_MAKE_METHODS(enabled, int) 00607 00608 # undef SL_MAKE_METHODS 00609 00610 /** 00611 * Get string representation of object. 00612 */ 00613 std::string string() const; 00614 }; 00615 00616 /** 00617 * Abstract base class for call-back handlers used by the by the PATXT 00618 * processor. 00619 * 00620 * Note: This class is normally not used by SL Toolkit users. 00621 * The PA class uses this internally. 00622 */ 00623 class PATextHandler 00624 { 00625 public: 00626 /** 00627 * Handler PATXT header. 00628 * This is called once at the start of processing. 00629 */ 00630 virtual void process_header(const PATextHeader& header) = 0; 00631 00632 /** 00633 * Handle point. 00634 * This is called for each point in lexographic order. 00635 */ 00636 virtual void process_point(const PAPointInfo& info) = 0; 00637 }; 00638 00639 00640 /** 00641 * SIMION Potential array class. 00642 * 00643 * This C++ class provides functionality for reading/writing SIMION 00644 * potential array files (PA/PA?). 00645 * 00646 * This now support an ASCII text format for PAs. This text format 00647 * may be either in the DOS or UNIX text format. 00648 * 00649 * SYNOPSIS 00650 * @code 00651 * <div style="background-color:#e0e0e0"><pre> 00652 * #include <simion/pa.h> 00653 * //#include <simion/pa.cpp> 00654 * 00655 * int main() 00656 * { 00657 * // example reading 00658 * PA pa; 00659 * pa.load("buncher.pa#"); 00660 * cout << pa.header_string() << endl; 00661 * 00662 * // example writing 00663 * PA pa2(PAArgs().nx(100).ny(20).symmetry(CYLINDRICAL)); 00664 * int x,y,z; 00665 * z = 0; 00666 * for(y=0; y < pa2.ny(); y++) { 00667 * for(x=0; x < pa2.nx(); x++) { 00668 * bool inside = (x+y) < 10; 00669 * if(inside) pa2.point(x, y, z, true, 5); // electrode 5V 00670 * }} 00671 * pa2.save("cone.pa#"); 00672 * 00673 * // create a magnetic field from scratch 00674 * PA pa3(PAArgs().nx(50).ny(50).field_type(MAGNETIC)); 00675 * z = 0; 00676 * for(y=0; y < pa3.ny(); y++) { 00677 * for(x=0; x < pa3.nx(); x++) { 00678 * double ex = x; 00679 * double ey = y*y; 00680 * double ez = 0; 00681 * pa3.field(x, y, z, ex, ey, ez); 00682 * }} 00683 * pa3.save("mag1.pa"); 00684 * 00685 * return 0; 00686 * } 00687 * @endcode 00688 * 00689 * TERMINOLOGY 00690 * 00691 * A potential array consist of a set of (integer) grid 00692 * points within a 2D rectangle or 3D rectangular prism. 00693 * These points are denoted (xi, yi, zi) for xi in 0..nx-1, 00694 * yi in 0..ny-1, zi in 0..nz-1 (where nz=1 in the 2D case). 00695 * 00696 * All grid points are assigned a real potential and are marked as 00697 * either electrodes or non-electrodes. Any real point (x, y, z) is 00698 * directly surrounded by at most four (2D) or eight (3D) grid points. 00699 * If all surrounding points are electrodes, the point is considered a 00700 * solid point (which can splat ions). Electrode points that are not 00701 * solid points make up ideal grid (which allow ions to fly through). 00702 * Solids have finite width, while ideal grids have infinitesimal width. 00703 * 00704 * To reduce the number of computations, the grid is assigned 00705 * symmetry (cylindrical or planar) and mirroring (x, y, or z). In 00706 * cylindrical symmetry (which only applies to 2D grids), the 2D grid 00707 * is revolved around the line x=0 to generate a 3D geometry. A 2D 00708 * grid under planar symmetry is duplicated infinitely in the Z 00709 * direction. A 3D grid (which can only have planar symmetry), is unchanged. 00710 * x mirroring equated point (x, y, z) to (-x, y, z), and the analogous is 00711 * true for the other dimensions. 00712 * 00713 * See D-5 of the SIMION 7.0 manual for info on the 00714 * %PA file format. See other sections on PAs for more general background. 00715 * 00716 */ 00717 00718 class PA 00719 { 00720 public: 00721 enum {MAX_POINTS = 50000000}; 00722 00723 /** 00724 * @name Construction and Serialization 00725 * @{ 00726 */ 00727 00728 /** 00729 * Constructs a new, empty potential array. 00730 * 00731 * By default, 00732 * - mode = -1, 00733 * - symmetry = PLANAR, 00734 * - max_voltage = 100000, 00735 * - nx = 3, 00736 * - ny = 3, 00737 * - nz = 1, 00738 * - ng = 100, 00739 * - mirror_x = false, 00740 * - mirror_y = false, 00741 * - mirror_z = false, 00742 * - fast_adjustable = false, 00743 * - enable_points = true. 00744 */ 00745 PA(); 00746 00747 /** 00748 * Constructs a new potential array from the given arguments. 00749 * The default arguments are the same as in PA(). 00750 * 00751 * Example: 00752 * 00753 * @code 00754 * PA pa(PAArgs().nx(10).ny(20).nz(30).symmetry(CYLINDRICAL)); 00755 * @endcode 00756 */ 00757 PA(const PAArgs& args); 00758 00759 /** 00760 * Destructor. 00761 * All used memory is freed. 00762 */ 00763 virtual ~PA(); 00764 00765 /** 00766 * Returns a string containing PATXT-formatted header 00767 * for the current array. 00768 * 00769 * For example, for SIMION's QUAD.PA# file, the result is as such: 00770 * 00771 * @verbatim 00772 * begin_header 00773 * mode -1 00774 * symmetry planar 00775 * max_voltage 20000 00776 * nx 77 00777 * ny 39 00778 * nz 1 00779 * mirror_x 0 00780 * mirror_y 1 00781 * mirror_z 0 00782 * field_type electrostatic 00783 * ng 100 00784 * fast_adjustable 1 00785 * end_header 00786 * @endverbatim 00787 * 00788 * This method is also very useful for debugging to quickly display 00789 * the information on a given potential array. 00790 * 00791 * @return string 00792 */ 00793 std::string header_string() const; 00794 00795 /** 00796 * Sets the task object for this PA. 00797 * This provides an optional features. The task object, if present, 00798 * is used to provide feedback as the 00799 * percent completion of a long running task (e.g. loading/saving) 00800 * and to allow the task to be terminated prematurely. 00801 * 00802 * @param status pointer to task object (may be NULL to disable). 00803 */ 00804 void set_status(Task* status); 00805 00806 /** 00807 * Load potential array from file. 00808 * Throws string on error. 00809 * 00810 * @param path file path 00811 */ 00812 void load(const std::string& path) throw(std::string); 00813 00814 /** 00815 * Load potential array from an input stream. 00816 * Throws string on error. 00817 * 00818 * @param is input stream 00819 */ 00820 void load(std::istream& is) throw(std::string); 00821 00822 /** 00823 * Saves the potential array to a file. 00824 * Throws string on error. 00825 * 00826 * To save to a binary file, do something like 00827 * 00828 * @code 00829 * pa.save("myfile.pa#"); 00830 * @endcode 00831 * 00832 * To save to an ASCII formatted file, or for additional options, do 00833 * something like 00834 * 00835 * @code 00836 * pa.save("myfile.pa#", 00837 * PAFormat().format(PAFormat::ASCII).enable_coords(false)); 00838 * @endcode 00839 * 00840 * @param path file path 00841 * @param opt Format options (optional). If omitted, the binary 00842 * format is used. 00843 */ 00844 void save(const std::string& path, const PAFormat& opt = PAFormat()) 00845 throw(std::string); 00846 00847 /** 00848 * Writes the potential array to an output stream. 00849 * Throws string on error. 00850 * 00851 * @param os output stream 00852 * @param opt Format options (optional). If omitted, the binary 00853 * format is used. 00854 */ 00855 void save(std::ostream& os, const PAFormat& opt = PAFormat()) 00856 throw(std::string); 00857 00858 00859 /// @} 00860 00861 /** 00862 * @name Attribute Getters/Setters 00863 * @{ 00864 */ 00865 00866 /** 00867 * Gets whether data points are enabled. 00868 * 00869 * The default is for points to be enabled, but if you only need 00870 * to manipulate header information, you can conserve memory by 00871 * disabling data points, in which case only the header 00872 * information (not the data points) are loaded from and saved to 00873 * a file. 00874 */ 00875 bool enable_points() const; 00876 00877 /** 00878 * Sets whether data points are enabled. 00879 */ 00880 void enable_points(bool val); 00881 00882 /** 00883 * Determines if array is fast adjustable. 00884 */ 00885 bool fast_adjustable() const; 00886 00887 /** 00888 * Sets whether array is fast adjustable. 00889 */ 00890 void fast_adjustable(bool val); 00891 00892 /** 00893 * Retrieves the field type (potential v.s. magnetic). 00894 * 00895 * @return field type 00896 */ 00897 field_t field_type() const; 00898 00899 /** 00900 * Sets the field type (potential v.s. magnetic). 00901 * 00902 * @param val field type 00903 */ 00904 void field_type(field_t val); 00905 00906 /** 00907 * Gets the max voltage value of the potential array. 00908 * The max voltage value affects the interpretation of 00909 * point potentials (see the point() function). 00910 * See p. D-6 of the SIMION 7.0 manual for details on this 00911 * parameter. 00912 * 00913 * @return size 00914 */ 00915 double max_voltage() const; 00916 00917 /** 00918 * Sets the max voltage value of the potential array. 00919 * The max voltage value affects the interpretation of 00920 * point potentials (see the point() function). 00921 * SIMION typically sets the value slightly above the 00922 * maximum potential in the array due to floating point 00923 * rounding. 00924 * See p. D-6 of the SIMION 7.0 manual for details on this 00925 * parameter. 00926 */ 00927 void max_voltage(double val); 00928 00929 /** 00930 * Gets whether array has X symmetry 00931 * 00932 * @return Boolean 00933 */ 00934 bool mirror_x() const; 00935 00936 /** 00937 * Sets whether array has X symmetry 00938 * 00939 * @param val has X symmetry 00940 */ 00941 void mirror_x(bool val); 00942 00943 /** 00944 * Gets whether array has Y symmetry. 00945 * 00946 * @return Boolean 00947 */ 00948 bool mirror_y() const; 00949 00950 /** 00951 * Sets whether array has Y symmetry. 00952 * This must be true for cylindrical arrays. 00953 * 00954 * @param val has Y symmetry 00955 */ 00956 void mirror_y(bool val); 00957 00958 /** 00959 * Gets whether array has Z symmetry. 00960 * This must be false for cylindrical and 2D planar arrays. 00961 * 00962 * @return Boolean 00963 */ 00964 bool mirror_z() const; 00965 00966 /** 00967 * Sets whether array has Z symmetry 00968 * 00969 * @param val has Z symmetry 00970 */ 00971 void mirror_z(bool val); 00972 00973 /** 00974 * Gets the mode number. 00975 * Currently, this value has no meaning, and 00976 * all arrays have mode of -1. 00977 * 00978 * @return mode 00979 */ 00980 int mode() const; 00981 00982 /** 00983 * Sets the mode number. 00984 * Currently, this value has no meaning, and 00985 * all arrays have mode of -1. 00986 */ 00987 void mode(int val); 00988 00989 /** 00990 * Retrieves the "ng" scaling constant using in magnetic arrays. 00991 * 00992 * SIMION uses the ng constant to make magnetic potentials 00993 * correspond to magnetic field values. Refer to page 2-10 00994 * in the SIMION 7.0 manual for details. 00995 * 00996 * @return ng 00997 */ 00998 int ng() const; 00999 01000 /** 01001 * Sets the "ng" scaling constant. 01002 * 01003 * SIMION uses the ng constant to make magnetic potentials 01004 * correspond to magnetic field values. Refer to page 2-10 01005 * in the SIMION 7.0 manual for details. 01006 * 01007 * @param val new value 01008 */ 01009 void ng(int val); 01010 01011 /** 01012 * Returns number of points in array. 01013 * That is, nx * ny * nz. 01014 * 01015 * @return number of points 01016 */ 01017 int num_points() const; 01018 01019 /** 01020 * Gets the number of voxels (2D or 3D pixels). 01021 * 01022 * Each voxel is surrounded by four (2D arrays) or eight (3D 01023 * arrays) grid points. For 2D arrays, this is (nx()-1) * 01024 * (ny()-1). For 3D arrays, this is (nx()-1) * (ny()-1) * 01025 * (nz()-1). 01026 */ 01027 int num_voxels() const; 01028 01029 /** 01030 * Gets the array dimension in the y-direction (grid units) 01031 * 01032 * @return size 01033 */ 01034 int nx() const; 01035 01036 /** 01037 * Sets the array dimension in the x-direction (grid units) 01038 * Point data is cleared on resizing. 01039 */ 01040 void nx(int val); 01041 01042 /** 01043 * Gets the array dimension in the y-direction (grid units) 01044 * 01045 * @return size 01046 */ 01047 int ny() const; 01048 01049 /** 01050 * Sets the array dimension in the y-direction (grid units) 01051 * Point data is cleared on resizing. 01052 */ 01053 void ny(int val); 01054 01055 /** 01056 * Gets the array dimension in the z-direction (grid units) 01057 * 01058 * @return size 01059 */ 01060 int nz() const; 01061 01062 /** 01063 * Sets the array dimension in the z-direction (grid units) 01064 * Point data is cleared on resizing. 01065 */ 01066 void nz(int val); 01067 01068 /** 01069 * Gets the PA# associated with this PA0 (if any). 01070 * @return PA# array. NULL if none. 01071 */ 01072 PA* pasharp() const; 01073 01074 /** 01075 * Sets the PA# associated with this PA0. 01076 * This is only intended for PA0 arrays. 01077 * The PA# information is needed to properly save a PA0 file. 01078 * 01079 * @code 01080 * PA pasharp(PAArgs().file("test.pa#")); 01081 * PA pa0(); 01082 * //... add code to create pa0 array here. 01083 * pa0.pasharp(&pasharp); 01084 * pa0.save("test.pa0"); 01085 * @endcode 01086 * 01087 * @param pasharp PA# array. NULL clears it. 01088 */ 01089 void pasharp(PA* pasharp); 01090 01091 //IMPROVE:implement get() function analogous to set? 01092 01093 /** 01094 * Sets multiple attributes at once. 01095 * 01096 * This can take the same set of parameters as the new() method. 01097 * This method is useful when the attributes are interdependent. 01098 * 01099 * @code 01100 * pa.set(PAArgs().nz(1).symmetry(CYLINDRICAL); 01101 * @endcode 01102 * 01103 * See the individual setter methods for details on each parameter. 01104 */ 01105 void set(const PAArgs& args); 01106 01107 /** 01108 * Sets the array size in all dimensions (x, y, z) (grid units). 01109 * Point data is cleared on resizing. 01110 */ 01111 void size(int nx, int ny, int nz = 1); 01112 01113 /** 01114 * Retrieves the symmetry (cylindrical v.s. planar) 01115 * of the array. 01116 * 01117 * @return symmetry 01118 */ 01119 symmetry_t symmetry() const; 01120 01121 /** 01122 * Changes the symmetry of the potential array. 01123 * 01124 * @param val new symmetry 01125 */ 01126 void symmetry(symmetry_t val); 01127 01128 /// @} 01129 01130 /** 01131 * @name Boundary and Coordinates 01132 * @{ 01133 */ 01134 01135 /** 01136 * Determines if given integer point is inside the potential array. 01137 * Boundaries are considered included. 01138 * 01139 * Symmetry and mirroring ARE NOT handled. 01140 * 01141 * @param xi x-coordinate in grid units [0..nx-1] 01142 * @param yi y-coordinate in grid units [0..ny-1] 01143 * @param zi z-coordinate in grid units [0..nz-1] 01144 */ 01145 bool inside(int xi, int yi, int zi = 0) const; 01146 01147 /** 01148 * Determines is given real point is inside the potential array. 01149 * Boundaries are considered inside. 01150 * 01151 * Symmetry and mirroring ARE handled. 01152 * 01153 * @param x x-coordinate in grid units. 01154 * @param y y-coordinate in grid units. 01155 * @param z z-coordinate in grid units. 01156 */ 01157 bool inside(double x, double y, double z = 0.0) const; 01158 01159 /** 01160 * Convert a real point to its normalized form, 01161 * removing symmetry and mirroring. 01162 * 01163 * For example, (-5, 3, 4) transforms to (5, 3, 4) under x mirroring. 01164 * 01165 * @param x x-coordinate in grid units 01166 * @param y y-coordinate in grid units 01167 * @param z z-coordinate in grid units 01168 * @return (x, y, z) coordinates in grid units (no mirror/symmetry) 01169 */ 01170 Vector3R norm_grid_coords(double x, double y, double z) const; 01171 01172 /** 01173 * Determines is given pixel is inside the potential array. 01174 * Boundaries are considered inside. 01175 * A pixel consists of all points between an including the 01176 * nearest grid points. 01177 * Note: inside_pixel(x,y,z) implies inside(x,y,z). 01178 * 01179 * Symmetry and mirroring ARE NOT handled. 01180 * 01181 * @param xi x-coordinate in grid units [0..nx-1] 01182 * @param yi y-coordinate in grid units [0..ny-1] 01183 * @param zi z-coordinate in grid units [0..nz-1] 01184 */ 01185 bool voxel_inside(int xi, int yi, int zi = 0) const; 01186 01187 /// @} 01188 01189 /** 01190 * @name Point Setters/Getters 01191 * @{ 01192 */ 01193 01194 /** 01195 * Sets all points to 0V, non-electrodes. 01196 * 01197 * This is different from enable_points(false) or ~PA(), which 01198 * actually releases the memory. 01199 */ 01200 void clear_points(); 01201 01202 /** 01203 * Gets whether the given integer point is an electrode. 01204 * Symmetry and mirroring ARE NOT handled. 01205 * 01206 * @param xi x-coordinate in grid units [0..nx-1] 01207 * @param yi y-coordinate in grid units [0..ny-1] 01208 * @param zi z-coordinate in grid units [0..nz-1] 01209 * @return true if electrode, false if non-electrode 01210 */ 01211 bool electrode(int xi, int yi, int zi = 0) const; 01212 01213 /** 01214 * Gets whether the given real point is on an electrode. 01215 * All points are either electrodes or non-electrodes. 01216 * Electrodes may be either solids or grids. Grids 01217 * have infinitesimal width. 01218 * 01219 * Symmetry and mirroring ARE handled. 01220 * 01221 * @param x x-coordinate in grid units. 01222 * @param y y-coordinate in grid units. 01223 * @param z z-coordinate in grid units. 01224 */ 01225 bool electrode(double x, double y, double z = 0.0) const; 01226 01227 /** 01228 * Sets the electrode status at the given integer point location. 01229 * 01230 * @param xi x-coordinate in grid units (0..nx-1) 01231 * @param yi y-coordinate in grid units (0..ny-1) 01232 * @param zi z-coordinate in grid units (0..nz-1) 01233 * @param is_electrode whether is electrode (true) or non-electrode (false) 01234 */ 01235 void electrode(int xi, int yi, int zi, bool is_electrode); 01236 01237 /** 01238 * Gets the electric or magnetic field vector at the given point. 01239 * The field is the gradient of the potential. 01240 * 01241 * Symmetry and mirroring ARE handled. 01242 * 01243 * @param x x-coordinate in grid units. 01244 * @param y y-coordinate in grid units. 01245 * @param z z-coordinate in grid units. 01246 * @return field vector 01247 */ 01248 Vector3R field(double x, double y, double z = 0.0) const; 01249 01250 /** 01251 * Sets the field (potential gradient) vector at the given point. 01252 * 01253 * The setting function internally performs the numerical 01254 * integration on the given field vectors to generate the 01255 * corresponding scalar potentials that must be stored in the PA 01256 * file. The setting function also has some special calling 01257 * requirements. First, the all points must initially be zero 01258 * volt, nonelectrodes. Second, the field setting method must be 01259 * called for all points in the array in lexographic order 01260 * (e.g. (0,0,0), (0,0,1), ... (0,0,nx()-1), (0,1,0), (0,1,1), 01261 * (0,1,nx()-1), ...). 01262 * 01263 * @code 01264 * // set 01265 * for(int z = 0; z < pa.nz(); z++) { 01266 * for(int y = 0; y < pa.ny(); y++) { 01267 * for(int x = 0; z < pa.nz(); x++) { 01268 * double ex = x; 01269 * double ey = y**2; 01270 * double ez = 0; 01271 * pa.field(x, y, z, ex, ey, ez); 01272 * }}} 01273 * @endcode 01274 */ 01275 void field(int xi, int yi, int zi, double ex, double ey, double ez, 01276 bool is_electrode = false); 01277 01278 /** 01279 * Gets the potential and electrode status at the given point location. 01280 */ 01281 PAPoint point(int xi, int yi, int zi) const; 01282 01283 /** 01284 * Sets the potential and electrode status at the given point location. 01285 * 01286 * @param xi x-coordinate in grid units (0..nx-1) 01287 * @param yi y-coordinate in grid units (0..ny-1) 01288 * @param zi z-coordinate in grid units (0..nz-1) 01289 * @param electrode whether is electrode (true) or non-electrode (false) 01290 * @param potential new potential value 01291 */ 01292 void point(int xi, int yi, int zi, bool electrode, double potential); 01293 01294 01295 /** 01296 * Gets the potential at the given integer point location. 01297 * The point may be either an electrode or non-electrode. 01298 * inside(xi, yi, zi) must be true. 01299 * 01300 * @param xi x-coordinate in grid units [0..nx-1] 01301 * @param yi y-coordinate in grid units [0..ny-1] 01302 * @param zi z-coordinate in grid units [0..nz-1] 01303 * @return potential 01304 */ 01305 double potential(int xi, int yi, int zi = 0) const; 01306 01307 /** 01308 * Retrieve the potential at the given real point location. 01309 * Interpolation is used for points between grid points. 01310 * inside(x, y, z) must be true. 01311 * 01312 * Symmetry and mirroring ARE handled. 01313 * 01314 * @param x x-coordinate in grid units. 01315 * @param y y-coordinate in grid units. 01316 * @param z z-coordinate in grid units. 01317 */ 01318 double potential(double x, double y, double z = 0.0) const; 01319 01320 /** 01321 * Sets the potential at the given integer point. 01322 * The electrode/non-electrode state is preserved. 01323 * 01324 * @param xi x-coordinate in grid units. 01325 * @param yi y-coordinate in grid units. 01326 * @param zi z-coordinate in grid units. 01327 * @param potential new potential in volts. 01328 */ 01329 void potential(int xi, int yi, int zi, double potential); 01330 01331 /** 01332 * Get the raw value at the given integer point location. 01333 * 01334 * The raw value is defined by 01335 * \li raw = potential + (electrode ? 2 * max_voltage() : 0) 01336 * 01337 * (You must have previously called create or load before 01338 * using this.) 01339 * 01340 * @param xi x-coordinate in grid units (0..nx-1) 01341 * @param yi y-coordinate in grid units (0..ny-1) 01342 * @param zi z-coordinate in grid units (0..nz-1) 01343 * @return raw value 01344 */ 01345 double raw_value(int xi, int yi, int zi = 0) const; 01346 01347 /** 01348 * Get the raw value at the given real point location. 01349 * The raw value is defined by 01350 * - raw = potential + (electrode ? 2 * max_voltage : 0). 01351 */ 01352 //IMPROVE:implement? 01353 //double raw_value(double x, double y, double z = 0.0) const; 01354 01355 01356 /** 01357 * Set the raw value at the given integer point location. 01358 * 01359 * The raw value is defined by 01360 * \li raw = potential + (electrode ? 2 * max_voltage : 0). 01361 * 01362 * (You must have previously called create or load before 01363 * using this.) 01364 * 01365 * @param xi x-coordinate in grid units (0..nx-1) 01366 * @param yi y-coordinate in grid units (0..ny-1) 01367 * @param zi z-coordinate in grid units (0..nz-1) 01368 * @param val new value 01369 */ 01370 void raw_value(int xi, int yi, int zi, double val); 01371 01372 01373 /** 01374 * Sets the given pixel as solid (electrode, non-grid) 01375 * and the voltage to the given value. 01376 * 01377 * The pixel is consists of the space bounded by 01378 * [x, y, z] and [x+1, y+1, z+1] (3D planar arrays) or 01379 * [x, y] and [x+1, y+1] (cylindrical or 2D planar arrays). 01380 * 01381 * @param xi x-coordinate in grid units. 01382 * @param yi y-coordinate in grid units. 01383 * @param zi z-coordinate in grid units. 01384 * @param is_electrode whether to set to electrode points 01385 * (else non-electrode). 01386 * @param potential potential to set points to. 01387 */ 01388 void solid(int xi, int yi, int zi, bool is_electrode, double potential); 01389 01390 /** 01391 * Gets whether the given pixel is a solid point. 01392 * All solid points are electrodes. 01393 * Electrodes may be either solids or grids. 01394 * The pixel is consists of the space bounded by 01395 * [x, y, z] and [x+1, y+1, z+1] (3D planar arrays) or 01396 * [x, y] and [x+1, y+1] (cylindrical or 2D planar arrays). 01397 * 01398 * @param xi x-coordinate in grid units [0..nx-1] 01399 * @param yi y-coordinate in grid units [0..ny-1] 01400 * @param zi z-coordinate in grid units [0..nz-1] 01401 * @return true if solid, else false. 01402 */ 01403 bool solid(int xi, int yi, int zi = 0) const; 01404 01405 ///@} 01406 01407 01408 /** 01409 * @name Parsing 01410 * @{ 01411 */ 01412 01413 /** 01414 * Parses an ASCII PA file. 01415 * Typically you don't need to use this since the "load" 01416 * method calls this. 01417 * 01418 * @param is input stream (binary or ASCII) 01419 * @param handler object that parsing events will be sent to 01420 * 01421 * Throws string on error. 01422 */ 01423 void parse_ascii(std::istream& is, PATextHandler& handler); 01424 01425 /// @} 01426 01427 /** 01428 * @name Attribute Checking 01429 * @{ 01430 */ 01431 01432 01433 /** 01434 * Checks whether the given combination of 01435 * attributes is valid. 01436 * Sets error() on false. 01437 * Any subset of the above named parameters may be 01438 * specified. This method is useful in cases 01439 * when the attributes are interdependent. 01440 */ 01441 bool check(const PAArgs& args); 01442 01443 /** 01444 * Checks whether the given field type is valid. 01445 * Valid field types are ELECTROSTATIC and MAGNETIC. 01446 * Sets error() on false. 01447 */ 01448 bool check_field_type(field_t val); 01449 01450 /** 01451 * Checks whether the given mode is valid. 01452 * Sets error() on false. 01453 */ 01454 bool check_mode(int val); 01455 01456 /** 01457 * Checks whether the given max voltage valid is valid. 01458 * Sets error() on false. 01459 */ 01460 bool check_max_voltage(double val); 01461 01462 /** 01463 * Checks whether the given ng magnetic scaling constant is valid. 01464 * Sets error() on false. 01465 */ 01466 bool check_ng(int val); 01467 01468 /** 01469 * Checks whether the given grid dimensions in the x direction is valid. 01470 * Sets error() on false. 01471 */ 01472 bool check_nx(int val); 01473 01474 /** 01475 * Checks whether the given grid dimensions in the y direction is valid. 01476 * Sets error() on false. 01477 */ 01478 bool check_ny(int val); 01479 01480 /** 01481 * Checks whether the given grid dimensions in the z direction is valid. 01482 * Sets error() on false. 01483 */ 01484 bool check_nz(int val); 01485 01486 /** 01487 * Checks whether the given set of grid dimensions 01488 * in the x, y, and z directions is valid as a whole. 01489 * Sets error() on false. 01490 * 01491 * Note that check_nx(nx) and check_ny(ny) and check_nz(nz) implies 01492 * check_size(nx, ny, nz), although the converse is not necessarily 01493 * true. 01494 */ 01495 bool check_size(int nx, int ny, int nz = 1); 01496 01497 /** 01498 * Checks whether the given symmetry is valid. 01499 * Valid symmetries are PLANAR and CYLINDRICAL. 01500 * Sets error() on false. 01501 */ 01502 bool check_symmetry(symmetry_t val); 01503 01504 /** 01505 * Get last error message generated by one of the check calls. 01506 */ 01507 inline std::string error() const; 01508 01509 ///@} 01510 01511 /** 01512 * Returns string representation of symmetry value 01513 * (as returned by symmetry()). 01514 * 01515 * @return "cylindrical" or "planar" 01516 */ 01517 static std::string symmetry_string(symmetry_t val); 01518 01519 /** 01520 * Returns string representation of symmetry value 01521 * (as returned by field_type()). 01522 * 01523 * @return "electrostatic" or "planar" 01524 */ 01525 static std::string field_string(field_t val); 01526 01527 private: 01528 int mode_; // mode must be -1 01529 field_t field_type_; 01530 symmetry_t symmetry_; 01531 bool mirror_x_; 01532 bool mirror_y_; 01533 bool mirror_z_; 01534 int nx_; // array's x dimension size 01535 int ny_; // array's y dimension size 01536 int nz_; // array's z dimension size 01537 bool fast_adjustable_; 01538 double max_voltage_; // max voltage allowed for pa 01539 int ng_; // number of grid points between poles 01540 bool enable_points_; 01541 01542 double* points_; // data points 01543 01544 PATextImpl_* pat_; 01545 PA* pasharp_; // associated PA# (if any) 01546 01547 01548 std::string error_; // last error message 01549 01550 01551 std::string fail_point_(int x, int y, int z) const; 01552 std::string fail_point_(double x, double y, double z) const; 01553 01554 int pos_(int xi, int yi, int zi) const; 01555 01556 /** 01557 * Creates a the point data array (may be very large). 01558 * Normally, you don't need to use this since it it called 01559 * by "create". 01560 * Any existing data array is first destroyed. 01561 */ 01562 void create_points_(); 01563 01564 /** 01565 * Frees any data in the array. 01566 * This undoes a "create", and you must subsequently call 01567 * "create" if you want to use the object again. 01568 * Normally, you don't need to call this yourself becuase 01569 * it is called automatically on object destruction. 01570 */ 01571 void destroy_points_(); 01572 01573 /** 01574 * Determines is given point is inside the potential array. 01575 * The array must be cylindrical. 01576 * Boundaries are included. 01577 * 01578 * Symmetry and mirroring ARE handled. 01579 * 01580 * @param x x-coordinate in grid units. 01581 * @param r r-coordinate (y) in grid units. 01582 */ 01583 bool inside_cylindrical_(double x, double r) const; 01584 01585 void load_ascii_(std::istream& is) throw(std::string); 01586 void load_binary_(std::istream& is) throw(std::string); 01587 01588 void save_ascii_(std::ostream& os, const PAFormat& opt) throw(std::string); 01589 void save_binary_(std::ostream& os, const PAFormat& opt) throw(std::string); 01590 01591 // attribute checking 01592 bool fail_string_(const std::string& str); 01593 bool fail_mode_(int val); 01594 bool fail_max_voltage_(double val); 01595 bool fail_nx1_(int val); 01596 bool fail_nx2_(int val); 01597 bool fail_ny1_(int val); 01598 bool fail_ny2_(int val); 01599 bool fail_nz1_(int val); 01600 bool fail_nz2_(int val); 01601 bool fail_ng_(int val); 01602 bool fail_field_type_(field_t val); 01603 bool fail_symmetry_(symmetry_t val); 01604 bool fail_size_(int nx, int ny, int nz); 01605 }; 01606 01607 01608 01609 //============================================================== 01610 //=== Inline Code 01611 //============================================================== 01612 01613 #ifndef DOXYGEN_SHOULD_SKIP_THIS 01614 #define SL_MAKE_ARGS \ 01615 (PAArgs().nx(nx_).ny(ny_).nz(nz_).symmetry(symmetry_). \ 01616 mirror_x(mirror_x_).mirror_y(mirror_y_).mirror_z(mirror_z_)) 01617 #endif 01618 01619 01620 // IMPLEMENTATION PAHeader 01621 01622 inline PAHeader::PAHeader( 01623 int mode, 01624 field_t field_type, 01625 symmetry_t symmetry, 01626 double max_voltage, 01627 int nx, 01628 int ny, 01629 int nz, 01630 bool mirror_x, 01631 bool mirror_y, 01632 bool mirror_z, 01633 int ng 01634 ) : 01635 mode_ (mode), 01636 symmetry_ (symmetry != 0 ? 1 : 0), 01637 max_voltage_ (max_voltage), 01638 nx_ (nx), 01639 ny_ (ny), 01640 nz_ (nz), 01641 mirror_ ( (mirror_x ? MIRROR_X : 0) | 01642 (mirror_y ? MIRROR_Y : 0) | 01643 (mirror_z ? MIRROR_Z : 0) | 01644 (field_type == MAGNETIC ? MAGNETIC_PA : 0) | 01645 (ng << 4) 01646 ) 01647 { 01648 } 01649 01650 inline field_t PAHeader::field_type() const 01651 { 01652 return (mirror_ & MAGNETIC_PA) != 0 ? MAGNETIC : ELECTROSTATIC; 01653 } 01654 inline bool PAHeader::mirror_x() const { return (mirror_ & MIRROR_X) != 0; } 01655 inline bool PAHeader::mirror_y() const { return (mirror_ & MIRROR_Y) != 0; } 01656 inline bool PAHeader::mirror_z() const { return (mirror_ & MIRROR_Z) != 0; } 01657 inline int PAHeader::ng() const { return mirror_ >> 4; } 01658 inline symmetry_t PAHeader::symmetry() const { 01659 return symmetry_ == PLANAR ? PLANAR : CYLINDRICAL; 01660 } 01661 01662 // IMPLEMENTATION PATextHeader 01663 01664 inline void PATextHeader::enable_column(int idx, point_column_t t) 01665 { 01666 if(idx >= (int)columns_.size()) 01667 columns_.resize(idx+1); 01668 if(idx != -1) { 01669 columns_enabled_ |= t; 01670 columns_[idx] = t; 01671 } 01672 else { 01673 columns_enabled_ &= ~t; 01674 columns_[idx] = (point_column_t)0; 01675 } 01676 } 01677 inline PATextHeader::point_column_t PATextHeader::column(int idx) const 01678 { return columns_[idx]; } 01679 inline int PATextHeader::column_count() const { return columns_.size(); } 01680 inline int PATextHeader::enabled_columns() const { return columns_enabled_; } 01681 inline bool PATextHeader::is_column_enabled(point_column_t t) const 01682 { 01683 return (columns_enabled_ & t) != 0; 01684 } 01685 01686 01687 01688 // IMPLEMENTATION PAArgs 01689 01690 inline int PAArgs::defined() { return valid_; } 01691 inline bool PAArgs::is_set_(PAArgs::arg_t val) const { return (valid_ & val) != 0; } 01692 inline void PAArgs::set_(PAArgs::arg_t val) { valid_ |= val; } 01693 01694 // IMPLEMENTATION: Vector3R 01695 01696 inline Vector3R::Vector3R(double x, double y, double z) : 01697 x_(x), y_(y), z_(z) 01698 { } 01699 inline void Vector3R::set(double x, double y, double z) 01700 { x_ = x; y_ = y; z_ = z; } 01701 inline double Vector3R::x() const { return x_; } 01702 inline void Vector3R::x(double val) { x_ = val; } 01703 inline double Vector3R::y() const { return y_; } 01704 inline void Vector3R::y(double val) { y_ = val; } 01705 inline double Vector3R::z() const { return z_; } 01706 inline void Vector3R::z(double val) { z_ = val; } 01707 01708 // IMPLEMENTATION PA 01709 01710 inline std::string PA::fail_point_(double x, double y, double z) const 01711 { 01712 return (std::string)"point (" + str(x) + "," + str(y) + "," + str(z) + 01713 ") out of bounds (" + str(nx_) + "," + str(ny_) + "," + str(nz_) + ")."; 01714 } 01715 01716 inline std::string PA::fail_point_(int xi, int yi, int zi) const 01717 { 01718 return (std::string)"point (" + str(xi) + "," + str(yi) + "," + str(zi) + 01719 ") out of bounds (" + str(nx_) + "," + str(ny_) + "," + str(nz_) + ")."; 01720 } 01721 01722 inline int PA::pos_(int xi, int yi, int zi) const 01723 { 01724 return (zi * ny_ + yi) * nx_ + xi; 01725 } 01726 01727 01728 inline bool PA::enable_points() const { return enable_points_; } 01729 inline void PA::enable_points(bool val) { 01730 if(val && !enable_points_) destroy_points_(); 01731 if(!val && enable_points_) create_points_(); 01732 enable_points_ = val; 01733 01734 } 01735 01736 inline bool PA::fast_adjustable() const { return fast_adjustable_; } 01737 inline void PA::fast_adjustable(bool val) { fast_adjustable_ = val; } 01738 01739 inline field_t PA::field_type() const { return field_type_; } 01740 inline void PA::field_type(field_t val) 01741 { 01742 field_type_ = val; 01743 } 01744 01745 inline double PA::max_voltage() const { return max_voltage_; } 01746 inline void PA::max_voltage(double val) 01747 { 01748 sl_assert(check_max_voltage(val), "max_voltage", error()); 01749 max_voltage_ = val; 01750 } 01751 01752 inline bool PA::mirror_x() const { return mirror_x_; } 01753 inline void PA::mirror_x(bool val) 01754 { 01755 mirror_x_ = !!val; 01756 } 01757 01758 inline bool PA::mirror_y() const { return mirror_y_; } 01759 inline void PA::mirror_y(bool val) 01760 { 01761 sl_assert(check(SL_MAKE_ARGS.mirror_y(val)), "mirror_y", error()); 01762 mirror_y_ = !!val; 01763 } 01764 01765 inline bool PA::mirror_z() const { return mirror_z_; } 01766 inline void PA::mirror_z(bool val) 01767 { 01768 sl_assert(check(SL_MAKE_ARGS.mirror_z(val)), "mirror_z", error()); 01769 01770 mirror_z_ = !!val; 01771 } 01772 01773 inline int PA::mode() const { return mode_; } 01774 inline void PA::mode(int val) 01775 { 01776 sl_assert(check_mode(val), "mode", error()); 01777 mode_ = val; 01778 } 01779 01780 inline int PA::ng() const { return ng_; } 01781 inline void PA::ng(int val) 01782 { 01783 // IMPROVE: check ng >= 1 (not 0) if magnetic 01784 sl_assert(check_ng(val), "ng", error()); 01785 ng_ = val; 01786 } 01787 01788 inline int PA::num_points() const { return nx_ * ny_ * nz_; } 01789 01790 inline int PA::num_voxels() const { 01791 int num = (nx_ - 1) * (ny_ - 1); 01792 if(nz_ != 1) num *= (nz_ - 1); 01793 return num; 01794 } 01795 01796 inline int PA::nx() const { return nx_; } 01797 inline void PA::nx(int val) 01798 { 01799 sl_assert(check_nx(val), "nx", error()); 01800 nx_ = val; 01801 } 01802 01803 inline int PA::ny() const { return ny_; } 01804 inline void PA::ny(int val) 01805 { 01806 sl_assert(check_ny(val), "ny", error()); 01807 ny_ = val; 01808 } 01809 01810 inline int PA::nz() const { return nz_; } 01811 inline void PA::nz(int val) 01812 { 01813 sl_assert(check_nz(val), "nz", error()); 01814 nz_ = val; 01815 } 01816 01817 inline PA* PA::pasharp() const { return pasharp_; } 01818 inline void PA::pasharp(PA* pasharp) { pasharp_ = pasharp; } 01819 01820 inline symmetry_t PA::symmetry() const { return (symmetry_t)symmetry_; } 01821 inline void PA::symmetry(symmetry_t val) 01822 { 01823 symmetry_ = (val == CYLINDRICAL) ? CYLINDRICAL : PLANAR; 01824 } 01825 01826 01827 inline bool PA::electrode(int xi, int yi, int zi) const 01828 { 01829 sl_assert(inside(xi, yi, zi), "electrode", fail_point_(xi,yi,zi)); 01830 01831 return raw_value(xi, yi, zi) > max_voltage(); 01832 } 01833 01834 inline void PA::electrode(int xi, int yi, int zi, bool is_electrode) 01835 { 01836 sl_assert(inside(xi, yi, zi), "point", fail_point_(xi, yi, zi)); 01837 01838 int pos = pos_(xi,yi,zi); 01839 if(points_[pos] > max_voltage_) { 01840 if(!is_electrode) points_[pos] -= 2 * max_voltage_; 01841 } 01842 else { 01843 if(!is_electrode) points_[pos] += 2 * max_voltage_; 01844 } 01845 } 01846 01847 inline PAPoint PA::point(int xi, int yi, int zi) const 01848 { 01849 return PAPoint(electrode(xi,yi,zi), potential(xi,yi,zi)); 01850 } 01851 01852 inline void PA::point(int xi, int yi, int zi, bool electrode, double potential) 01853 { 01854 sl_assert(inside(xi, yi, zi), "point", fail_point_(xi, yi, zi)); 01855 sl_assert(potential <= max_voltage(), "point", 01856 (std::string)"Potential (" + str(potential) + ") exceeds max voltage (" 01857 + str(max_voltage()) + ")"); 01858 01859 double val = electrode ? 2*max_voltage() + potential 01860 : potential; 01861 raw_value(xi, yi, zi, val); 01862 } 01863 01864 inline double PA::potential(int xi, int yi, int zi) const 01865 { 01866 sl_assert(inside(xi, yi, zi), "potential", fail_point_(xi, yi, zi)); 01867 01868 double val = raw_value(xi, yi, zi); 01869 if(val > max_voltage()) // electrode 01870 val -= 2*max_voltage(); 01871 01872 // sl_assert(abs(val) <= max_voltage(), "potential", "...", "voltage out of range") 01873 01874 return val; 01875 } 01876 01877 inline void PA::potential(int xi, int yi, int zi, double potential) 01878 { 01879 sl_assert(inside(xi, yi, zi), "potential", fail_point_(xi, yi, zi)); 01880 sl_assert(potential <= max_voltage(), "point", 01881 (std::string)"Potential (" + str(potential) + ")" + 01882 " exceeds max voltage (" + str(max_voltage()) + ")"); 01883 01884 int pos = pos_(xi,yi,zi); 01885 bool is_electrode = (points_[pos] > max_voltage_); 01886 points_[pos] = potential; 01887 if(is_electrode) points_[pos] += 2 * max_voltage_; 01888 } 01889 01890 inline double PA::raw_value(int xi, int yi, int zi) const 01891 { 01892 sl_assert(inside(xi, yi, zi), "raw_value", fail_point_(xi,yi,zi)); 01893 01894 return points_[pos_(xi,yi,zi)]; 01895 } 01896 inline void PA::raw_value(int xi, int yi, int zi, double val) 01897 { 01898 sl_assert(inside(xi, yi, zi), "raw_value", fail_point_(xi, yi, zi)); 01899 01900 points_[pos_(xi,yi,zi)] = val; 01901 } 01902 01903 01904 inline bool PA::check_mode(int val) 01905 { 01906 if(val != -1) return fail_mode_(val); 01907 return true; 01908 } 01909 01910 inline bool PA::check_max_voltage(double val) 01911 { 01912 if(val <= 0) return fail_max_voltage_(val); 01913 return true; 01914 } //q:ok? 01915 01916 inline bool PA::check_nx(int val) 01917 { 01918 if(val < 3) return fail_nx1_(val); 01919 if(val > 90000) return fail_nx1_(val); 01920 return true; 01921 } 01922 01923 inline bool PA::check_ny(int val) 01924 { 01925 if(val < 3) return fail_ny1_(val); 01926 if(val > 90000) return fail_ny2_(val); 01927 return true; 01928 } 01929 01930 inline bool PA::check_nz(int val) 01931 { 01932 if(val < 1) return fail_nz1_(val); 01933 if(val > 90000) return fail_nz2_(val); 01934 return true; 01935 } 01936 01937 inline bool PA::check_ng(int val) 01938 { 01939 if(val < 0) return fail_ng_(val); 01940 return true; 01941 } 01942 01943 inline bool PA::check_field_type(field_t val) 01944 { 01945 if(val != ELECTROSTATIC && val != MAGNETIC) 01946 return fail_field_type_(val); 01947 return true; 01948 } 01949 01950 inline bool PA::check_symmetry(symmetry_t val) 01951 { 01952 if(val != PLANAR && val != CYLINDRICAL) 01953 return fail_symmetry_(val); 01954 return true; 01955 } 01956 inline bool PA::check_size(int nx, int ny, int nz) 01957 { 01958 if(!(check_nx(nx) && check_ny(ny) && check_nz(nz))) return false; 01959 if(mult_overflow(nx,ny) || mult_overflow(nx*ny,nz) || nx*ny*nz > 50000000) 01960 return fail_size_(nx, ny, nz); 01961 return true; 01962 } 01963 01964 inline std::string PA::error() const { return error_; } 01965 01966 #undef SL_MAKE_ARGS 01967 01968 } // end namespace 01969 01970 #endif // first include 01971
(c) 2003-2004. Scientific Instrument Services, Inc. All Rights Reserved.
Please report any errors/comments regarding this web page:
  Name/e-mail/phone (optional):
 
The SIMION SL Toolkit™ and documentation is (c) 2003-2004 Scientific Instrument Services, Inc. All Rights Reserved.
Any comments on this web page? (will be sent to SIS)
[Optional] Your name: email: phone/fax:
The SL Tookit™ and documentation is (c) 2003 Scientific Instrument Services, Inc. All Rights Reserved.
(c) 2003-2006 Scientific Instrument Services, Inc. (SIS). Contact SIS.