Garfield++ v1r0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
ComponentVoxel.cc
Go to the documentation of this file.
1#include <iostream>
2#include <fstream>
3#include <sstream>
4#include <string>
5#include <algorithm>
6#include <cmath>
7
8#include "ComponentVoxel.hh"
9
10namespace Garfield {
11
13 : ComponentBase(),
14 m_nX(0),
15 m_nY(0),
16 m_nZ(0),
17 m_xMin(0.),
18 m_yMin(0.),
19 m_zMin(0.),
20 m_xMax(0.),
21 m_yMax(0.),
22 m_zMax(0.),
23 m_hasMesh(false),
24 m_hasPotential(false),
25 m_hasField(false),
26 m_pMin(0.),
27 m_pMax(0.) {
28
29 m_className = "ComponentVoxel";
30}
31
32void ComponentVoxel::ElectricField(const double xin, const double yin,
33 const double zin, double& ex, double& ey,
34 double& ez, double& p, Medium*& m,
35 int& status) {
36
37 m = NULL;
38 // Make sure the field map has been loaded.
39 if (!ready) {
40 std::cerr << m_className << "::ElectricField:\n";
41 std::cerr << " Field map is not available for interpolation.\n";
42 status = -10;
43 return;
44 }
45
46 unsigned int i, j, k;
47 bool xMirrored, yMirrored, zMirrored;
48 if (!GetElement(xin, yin, zin, i, j, k, xMirrored, yMirrored, zMirrored)) {
49 status = -11;
50 return;
51 }
52 status = 0;
53 // Get the electric field and potential.
54 ex = m_mesh[i][j][k].ex;
55 ey = m_mesh[i][j][k].ey;
56 ez = m_mesh[i][j][k].ez;
57 p = m_mesh[i][j][k].v;
58 if (xMirrored) ex = -ex;
59 if (yMirrored) ey = -ey;
60 if (zMirrored) ez = -ez;
61 // Get the medium.
62 int region = m_mesh[i][j][k].region;
63 if (m_media.count(region) < 1) {
64 m = 0;
65 status = -5;
66 return;
67 }
68 m = m_media[region];
69 if (m == NULL) status = -5;
70}
71
72void ComponentVoxel::ElectricField(const double x, const double y,
73 const double z, double& ex, double& ey,
74 double& ez, Medium*& m, int& status) {
75
76 double v = 0.;
77 ElectricField(x, y, z, ex, ey, ez, v, m, status);
78}
79
80Medium* ComponentVoxel::GetMedium(const double& xin, const double& yin,
81 const double& zin) {
82
83 // Make sure the field map has been loaded.
84 if (!ready) {
85 std::cerr << m_className << "::GetMedium:\n";
86 std::cerr << " Field map not available for interpolation.\n";
87 return NULL;
88 }
89
90 unsigned int i, j, k;
91 bool xMirrored, yMirrored, zMirrored;
92 if (!GetElement(xin, yin, zin, i, j, k, xMirrored, yMirrored, zMirrored)) {
93 return NULL;
94 }
95 if (m_media.count(m_mesh[i][j][k].region) < 1) {
96 return NULL;
97 }
98 return m_media[m_mesh[i][j][k].region];
99}
100
101void ComponentVoxel::SetMesh(const unsigned int nx, const unsigned int ny,
102 const unsigned int nz, const double xmin,
103 const double xmax, const double ymin,
104 const double ymax, const double zmin,
105 const double zmax) {
106
107 ready = false;
108 if (nx == 0 || ny == 0 || nz == 0) {
109 std::cerr << m_className << "::SetMesh:\n";
110 std::cerr << " Number of mesh elements must be positive.\n";
111 return;
112 }
113 if (xmin >= xmax) {
114 std::cerr << m_className << "::SetMesh:\n";
115 std::cerr << " Invalid x range.\n";
116 return;
117 } else if (ymin >= ymax) {
118 std::cerr << m_className << "::SetMesh:\n";
119 std::cerr << " Invalid y range.\n";
120 return;
121 } else if (zmin >= zmax) {
122 std::cerr << m_className << "::SetMesh:\n";
123 std::cerr << " Invalid z range.\n";
124 return;
125 }
126 m_nX = nx;
127 m_nY = ny;
128 m_nZ = nz;
129 m_xMin = xmin;
130 m_yMin = ymin;
131 m_zMin = zmin;
132 m_xMax = xmax;
133 m_yMax = ymax;
134 m_zMax = zmax;
135 // Resize the mesh.
136 m_mesh.resize(m_nX);
137 for (unsigned int i = 0; i < m_nX; ++i) {
138 m_mesh[i].resize(m_nY);
139 for (unsigned int j = 0; j < m_nY; ++j) {
140 m_mesh[i][j].resize(m_nZ);
141 for (unsigned int k = 0; k < m_nZ; ++k) {
142 m_mesh[i][j][k].ex = 0.;
143 m_mesh[i][j][k].ey = 0.;
144 m_mesh[i][j][k].ez = 0.;
145 m_mesh[i][j][k].v = 0.;
146 m_mesh[i][j][k].region = -1;
147 }
148 }
149 }
150 m_hasMesh = true;
151}
152
153bool ComponentVoxel::LoadData(const std::string filename, std::string format,
154 const bool withPotential, const bool withRegion,
155 const double scaleX, const double scaleE,
156 const double scaleP) {
157
158 if (!m_hasMesh) {
159 std::cerr << m_className << "::LoadData:\n";
160 std::cerr << " Mesh is not set. Call SetMesh first.\n";
161 return false;
162 }
163 ready = false;
164 m_hasPotential = m_hasField = false;
165 m_pMin = m_pMax = 0.;
166 if (withPotential) {
167 m_pMin = 1.;
168 m_pMax = -1.;
169 }
170
171 unsigned int nValues = 0;
172 std::vector<std::vector<std::vector<bool> > > isSet;
173 isSet.resize(m_nX);
174 for (unsigned int i = 0; i < m_nX; ++i) {
175 isSet[i].resize(m_nY);
176 for (unsigned int j = 0; j < m_nY; ++j) {
177 isSet[i][j].resize(m_nZ, false);
178 }
179 }
180 std::ifstream infile;
181 infile.open(filename.c_str(), std::ios::in);
182 if (!infile) {
183 std::cerr << m_className << "::LoadData:\n";
184 std::cerr << " Could not open file " << filename << ".\n";
185 return false;
186 }
187
188 std::transform(format.begin(), format.end(), format.begin(), toupper);
189 unsigned int fmt = 0;
190 if (format == "XY") {
191 fmt = 1;
192 } else if (format == "XYZ") {
193 fmt = 2;
194 } else if (format == "IJ") {
195 fmt = 3;
196 } else if (format == "IJK") {
197 fmt = 4;
198 } else {
199 std::cerr << m_className << "::LoadData:\n";
200 std::cerr << " Unkown format (" << format << ").\n";
201 return false;
202 }
203 std::string line;
204 unsigned int nLines = 0;
205 bool bad = false;
206 while (!infile.fail()) {
207 // Read one line.
208 std::getline(infile, line);
209 ++nLines;
210 // Strip white space from beginning of line.
211 line.erase(line.begin(),
212 std::find_if(line.begin(), line.end(),
213 not1(std::ptr_fun<int, int>(isspace))));
214 // Skip empty lines.
215 if (line.empty()) continue;
216 // Skip comments.
217 if (line[0] == '#') continue;
218 if (line[0] == '/' && line[1] == '/') continue;
219 unsigned int i = 0;
220 unsigned int j = 0;
221 unsigned int k = 0;
222 double ex = 0.;
223 double ey = 0.;
224 double ez = 0.;
225 double v = 0.;
226 int region = 0;
227 std::istringstream data;
228 data.str(line);
229 if (fmt == 1) {
230 // "XY"
231 double x, y;
232 data >> x >> y;
233 if (data.fail()) {
234 std::cerr << m_className << "::LoadData:\n";
235 std::cerr << " Error reading line " << nLines << ".\n";
236 std::cerr << " Cannot retrieve element coordinates.\n";
237 bad = true;
238 break;
239 }
240 x *= scaleX;
241 y *= scaleX;
242 const double z = 0.5 * (m_zMin + m_zMax);
243 bool xMirrored, yMirrored, zMirrored;
244 if (!GetElement(x, y, z, i, j, k, xMirrored, yMirrored, zMirrored)) {
245 std::cerr << m_className << "::LoadData:\n";
246 std::cerr << " Error reading line " << nLines << ".\n";
247 std::cerr << " Point is outside mesh.\n";
248 bad = true;
249 break;
250 }
251 } else if (fmt == 2) {
252 // "XYZ"
253 double x, y, z;
254 data >> x >> y >> z;
255 if (data.fail()) {
256 std::cerr << m_className << "::LoadData:\n";
257 std::cerr << " Error reading line " << nLines << ".\n";
258 std::cerr << " Cannot retrieve element coordinates.\n";
259 bad = true;
260 break;
261 }
262 x *= scaleX;
263 y *= scaleX;
264 z *= scaleX;
265 bool xMirrored, yMirrored, zMirrored;
266 if (!GetElement(x, y, z, i, j, k, xMirrored, yMirrored, zMirrored)) {
267 std::cerr << m_className << "::LoadData:\n";
268 std::cerr << " Error reading line " << nLines << ".\n";
269 std::cerr << " Point is outside mesh.\n";
270 bad = true;
271 break;
272 }
273 } else if (fmt == 3) {
274 // "IJ"
275 k = 0;
276 data >> i >> j;
277 if (data.fail()) {
278 std::cerr << m_className << "::LoadData:\n";
279 std::cerr << " Error reading line " << nLines << ".\n";
280 std::cerr << " Cannot retrieve element index.\n";
281 bad = true;
282 break;
283 }
284 } else if (fmt == 4) {
285 // "IJK"
286 data >> i >> j >> k;
287 if (data.fail()) {
288 std::cerr << m_className << "::LoadData:\n";
289 std::cerr << " Error reading line " << nLines << ".\n";
290 std::cerr << " Cannot retrieve element index.\n";
291 bad = true;
292 break;
293 }
294 }
295 // Check the indices.
296 if (i >= m_nX || j >= m_nY || k >= m_nZ) {
297 std::cerr << m_className << "::LoadData:\n";
298 std::cerr << " Error reading line " << nLines << ".\n";
299 std::cerr << " Index (" << i << ", " << j << ", " << k
300 << ") out of range.\n";
301 continue;
302 }
303 if (isSet[i][j][k]) {
304 std::cerr << m_className << "::LoadData:\n";
305 std::cerr << " Error reading line " << nLines << ".\n";
306 std::cerr << " Mesh element (" << i << ", " << j << ", " << k
307 << ") has already been set.\n";
308 continue;
309 }
310 // Get the electric field values.
311 if (fmt == 1 || fmt == 3) {
312 // Two-dimensional field-map
313 ez = 0.;
314 data >> ex >> ey;
315 } else {
316 data >> ex >> ey >> ez;
317 }
318 if (data.fail()) {
319 std::cerr << m_className << "::LoadData:\n";
320 std::cerr << " Error reading line " << nLines << ".\n";
321 std::cerr << " Cannot read electric field values.\n";
322 bad = true;
323 break;
324 }
325 ex *= scaleE;
326 ey *= scaleE;
327 ez *= scaleE;
328 if (withPotential) {
329 data >> v;
330 if (data.fail()) {
331 std::cerr << m_className << "::LoadData:\n";
332 std::cerr << " Error reading line " << nLines << ".\n";
333 std::cerr << " Cannot read potential.\n";
334 bad = true;
335 break;
336 }
337 v *= scaleP;
338 if (m_pMin > m_pMax) {
339 // First value.
340 m_pMin = v;
341 m_pMax = v;
342 } else {
343 if (v < m_pMin) m_pMin = v;
344 if (v > m_pMax) m_pMax = v;
345 }
346 }
347 if (withRegion) {
348 data >> region;
349 if (data.fail()) {
350 std::cerr << m_className << "::LoadData:\n";
351 std::cerr << " Error reading line " << nLines << ".\n";
352 std::cerr << " Cannot read region.\n";
353 bad = true;
354 break;
355 }
356 }
357 if (fmt == 1 || fmt == 3) {
358 // Two-dimensional field-map
359 for (unsigned int kk = 0; kk < m_nZ; ++kk) {
360 m_mesh[i][j][kk].ex = ex;
361 m_mesh[i][j][kk].ey = ey;
362 m_mesh[i][j][kk].ez = ez;
363 m_mesh[i][j][kk].v = v;
364 m_mesh[i][j][kk].region = region;
365 isSet[i][j][kk] = true;
366 }
367 } else {
368 m_mesh[i][j][k].ex = ex;
369 m_mesh[i][j][k].ey = ey;
370 m_mesh[i][j][k].ez = ez;
371 m_mesh[i][j][k].v = v;
372 m_mesh[i][j][k].region = region;
373 isSet[i][j][k] = true;
374 }
375 ++nValues;
376 }
377 if (bad) return false;
378 std::cout << m_className << "::LoadData:\n";
379 std::cout << " Read " << nValues << " values from file " << filename
380 << ".\n";
381 unsigned int nExpected = m_nX * m_nY;
382 if (fmt == 2 || fmt == 4) nExpected *= m_nZ;
383 if (nExpected != nValues) {
384 std::cerr << m_className << "::LoadData:\n";
385 std::cerr << " Expected " << nExpected << " values.\n";
386 }
387 ready = true;
388 return true;
389}
390
391bool ComponentVoxel::GetBoundingBox(double& xmin, double& ymin, double& zmin,
392 double& xmax, double& ymax, double& zmax) {
393
394 if (!ready) return false;
395 if (xPeriodic || xMirrorPeriodic) {
396 xmin = -INFINITY;
397 xmax = +INFINITY;
398 } else {
399 xmin = m_xMin;
400 xmax = m_xMax;
401 }
402
403 if (yPeriodic || yMirrorPeriodic) {
404 ymin = -INFINITY;
405 ymax = +INFINITY;
406 } else {
407 ymin = m_yMin;
408 ymax = m_yMax;
409 }
410
411 if (zPeriodic || zMirrorPeriodic) {
412 zmin = -INFINITY;
413 zmax = +INFINITY;
414 } else {
415 zmin = m_zMin;
416 zmax = m_zMax;
417 }
418 return true;
419}
420
421bool ComponentVoxel::GetVoltageRange(double& vmin, double& vmax) {
422
423 if (!ready) return false;
424 vmin = m_pMin;
425 vmax = m_pMax;
426 return true;
427}
428
429bool ComponentVoxel::GetElectricFieldRange(double& exmin, double& exmax,
430 double& eymin, double& eymax,
431 double& ezmin, double& ezmax) {
432
433 if (!ready) {
434 std::cerr << m_className << "::GetElectricFieldRange:\n";
435 std::cerr << " Field map not available.\n";
436 return false;
437 }
438 bool gotValue = false;
439 for (unsigned int i = 0; i < m_nX; ++i) {
440 for (unsigned int j = 0; j < m_nY; ++j) {
441 for (unsigned int k = 0; k < m_nZ; ++k) {
442 if (!gotValue) {
443 exmin = m_mesh[i][j][k].ex;
444 exmax = m_mesh[i][j][k].ex;
445 eymin = m_mesh[i][j][k].ey;
446 eymax = m_mesh[i][j][k].ey;
447 ezmin = m_mesh[i][j][k].ez;
448 ezmax = m_mesh[i][j][k].ez;
449 gotValue = true;
450 continue;
451 }
452 if (m_mesh[i][j][k].ex < exmin) exmin = m_mesh[i][j][k].ex;
453 if (m_mesh[i][j][k].ex > exmax) exmax = m_mesh[i][j][k].ex;
454 if (m_mesh[i][j][k].ey < eymin) eymin = m_mesh[i][j][k].ey;
455 if (m_mesh[i][j][k].ey > eymax) eymax = m_mesh[i][j][k].ey;
456 if (m_mesh[i][j][k].ez < ezmin) ezmin = m_mesh[i][j][k].ez;
457 if (m_mesh[i][j][k].ez > ezmax) ezmax = m_mesh[i][j][k].ez;
458 }
459 }
460 }
461 return true;
462}
463
465
466 // Do not proceed if not properly initialised.
467 if (!ready) {
468 std::cerr << m_className << "::PrintRegions:\n";
469 std::cerr << " Field map not yet initialised.\n";
470 return;
471 }
472
473 if (m_media.size() < 1) {
474 std::cerr << m_className << "::PrintRegions:\n";
475 std::cerr << " No regions are currently defined.\n";
476 return;
477 }
478
479 std::cout << m_className << "::PrintRegions:\n";
480 if (m_media.size() == 1) {
481 std::cout << " 1 region is defined.\n";
482 } else {
483 std::cout << " " << m_media.size() << " regions are defined.\n";
484 }
485 std::cout << " Index Medium\n";
486 std::map<int, Medium*>::iterator it;
487 for (it = m_media.begin(); it != m_media.end(); ++it) {
488 const int i = (*it).first;
489 Medium* m = (*it).second;
490 std::cout << " " << i << " ";
491 if (m == NULL) {
492 std::cout << " none\n";
493 } else {
494 std::cout << " " << m->GetName() << "\n";
495 }
496 }
497}
498
499void ComponentVoxel::SetMedium(const int i, Medium* m) {
500
501 if (m == NULL) {
502 std::cerr << m_className << "::SetMedium:\n";
503 std::cerr << " Warning: medium pointer is null.\n";
504 }
505 m_media[i] = m;
506}
507
508Medium* ComponentVoxel::GetMedium(const unsigned int& i) {
509
510 if (m_media.count(i) < 1) {
511 std::cerr << m_className << "::GetMedium:\n";
512 std::cerr << " Medium " << i << " does not exist.\n";
513 return NULL;
514 }
515
516 return m_media[i];
517}
518
519bool ComponentVoxel::GetElement(const double xi, const double yi,
520 const double zi, unsigned int& i,
521 unsigned int& j, unsigned int& k,
522 bool& xMirrored, bool& yMirrored,
523 bool& zMirrored) {
524
525 if (!m_hasMesh) {
526 std::cerr << m_className << "::GetElement:\n";
527 std::cerr << " Mesh is not set.\n";
528 return false;
529 }
530
531 double x = xi, y = yi, z = zi;
532 xMirrored = yMirrored = zMirrored = false;
533 // In case of periodicity, reduce to the basic cell.
534 const double cellsx = m_xMax - m_xMin;
535 if (xPeriodic) {
536 x = m_xMin + fmod(x - m_xMin, cellsx);
537 if (x < m_xMin) x += cellsx;
538 } else if (xMirrorPeriodic) {
539 double xNew = m_xMin + fmod(x - m_xMin, cellsx);
540 if (xNew < m_xMin) xNew += cellsx;
541 int nx = int(floor(0.5 + (xNew - x) / cellsx));
542 if (nx != 2 * (nx / 2)) {
543 xNew = m_xMin + m_xMax - xNew;
544 xMirrored = true;
545 }
546 x = xNew;
547 }
548 // Check if the point is outside the mesh.
549 if (x < m_xMin || x > m_xMax) return false;
550
551 const double cellsy = m_yMax - m_yMin;
552 if (yPeriodic) {
553 y = m_yMin + fmod(y - m_yMin, cellsy);
554 if (y < m_yMin) y += cellsy;
555 } else if (yMirrorPeriodic) {
556 double yNew = m_yMin + fmod(y - m_yMin, cellsy);
557 if (yNew < m_yMin) yNew += cellsy;
558 int ny = int(floor(0.5 + (yNew - y) / cellsy));
559 if (ny != 2 * (ny / 2)) {
560 yNew = m_yMin + m_yMax - yNew;
561 yMirrored = true;
562 }
563 y = yNew;
564 }
565 // Check if the point is outside the mesh.
566 if (y < m_yMin || y > m_yMax) return false;
567
568 const double cellsz = m_zMax - m_xMin;
569 if (zPeriodic) {
570 z = m_zMin + fmod(z - m_zMin, cellsz);
571 if (z < m_zMin) z += cellsz;
572 } else if (zMirrorPeriodic) {
573 double zNew = m_zMin + fmod(z - m_zMin, cellsz);
574 if (zNew < m_zMin) zNew += cellsz;
575 int nz = int(floor(0.5 + (zNew - z) / cellsz));
576 if (nz != 2 * (nz / 2)) {
577 zNew = m_zMin + m_zMax - zNew;
578 zMirrored = true;
579 }
580 z = zNew;
581 }
582 // Check if the point is outside the mesh.
583 if (z < m_zMin || z > m_zMax) return false;
584
585 // Get the indices.
586 const double dx = (m_xMax - m_xMin) / m_nX;
587 const double dy = (m_yMax - m_yMin) / m_nY;
588 const double dz = (m_zMax - m_zMin) / m_nZ;
589 i = (unsigned int)((x - m_xMin) / dx);
590 j = (unsigned int)((y - m_yMin) / dy);
591 k = (unsigned int)((z - m_zMin) / dz);
592 if (i >= m_nX) i = m_nX - 1;
593 if (j >= m_nY) j = m_nY - 1;
594 if (k >= m_nZ) k = m_nZ - 1;
595 return true;
596}
597
598bool ComponentVoxel::GetElement(const unsigned int i, const unsigned int j,
599 const unsigned int k, double& v, double& ex,
600 double& ey, double& ez) {
601
602 v = ex = ey = ez = 0.;
603 if (!ready) {
604 if (!m_hasMesh) {
605 std::cerr << m_className << "::GetElement:\n";
606 std::cerr << " Mesh not set.\n";
607 return false;
608 }
609 std::cerr << m_className << "::GetElement:\n";
610 std::cerr << " Fiel map not set.\n";
611 return false;
612 }
613 if (i >= m_nX || j >= m_nY || k >= m_nZ) {
614 std::cerr << m_className << "::GetElement:\n";
615 std::cerr << " Element index out of range.\n";
616 return false;
617 }
618 v = m_mesh[i][j][k].v;
619 ex = m_mesh[i][j][k].ex;
620 ey = m_mesh[i][j][k].ey;
621 ez = m_mesh[i][j][k].ez;
622 return true;
623}
624
625void ComponentVoxel::Reset() {
626
627 m_mesh.clear();
628 m_nX = m_nY = m_nZ = 0;
629 m_xMin = m_yMin = m_zMin = 0.;
630 m_xMax = m_yMax = m_zMax = 0.;
631 m_pMin = m_pMax = 0.;
632 m_media.clear();
633
634 m_hasMesh = false;
635 m_hasPotential = false;
636 m_hasField = false;
637
638 ready = false;
639}
640
641void ComponentVoxel::UpdatePeriodicity() {
642
643 if (!ready) {
644 std::cerr << m_className << "::UpdatePeriodicity:\n";
645 std::cerr << " Field map not available.\n";
646 return;
647 }
648
649 // Check for conflicts.
650 if (xPeriodic && xMirrorPeriodic) {
651 std::cerr << m_className << "::UpdatePeriodicity:\n";
652 std::cerr << " Both simple and mirror periodicity\n";
653 std::cerr << " along x requested; reset.\n";
654 xPeriodic = xMirrorPeriodic = false;
655 }
656
657 if (yPeriodic && yMirrorPeriodic) {
658 std::cerr << m_className << "::UpdatePeriodicity:\n";
659 std::cerr << " Both simple and mirror periodicity\n";
660 std::cerr << " along y requested; reset.\n";
661 yPeriodic = yMirrorPeriodic = false;
662 }
663
664 if (zPeriodic && zMirrorPeriodic) {
665 std::cerr << m_className << "::UpdatePeriodicity:\n";
666 std::cerr << " Both simple and mirror periodicity\n";
667 std::cerr << " along z requested; reset.\n";
668 zPeriodic = zMirrorPeriodic = false;
669 }
670
672 std::cerr << m_className << "::UpdatePeriodicity:\n";
673 std::cerr << " Axial symmetry is not supported; reset.\n";
675 }
676
678 std::cerr << m_className << "::UpdatePeriodicity:\n";
679 std::cerr << " Rotation symmetry is not supported; reset.\n";
681 }
682}
683}
void SetMedium(const int i, Medium *m)
bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
Medium * GetMedium(const double &x, const double &y, const double &z)
bool GetElectricFieldRange(double &exmin, double &exmax, double &eymin, double &eymax, double &ezmin, double &ezmax)
bool GetVoltageRange(double &vmin, double &vmax)
bool GetElement(const double xi, const double yi, const double zi, unsigned int &i, unsigned int &j, unsigned int &k, bool &xMirrored, bool &yMirrored, bool &zMirrored)
void ElectricField(const double x, const double y, const double z, double &ex, double &ey, double &ez, double &v, Medium *&m, int &status)
void SetMesh(const unsigned int nx, const unsigned int ny, const unsigned int nz, const double xmin, const double xmax, const double ymin, const double ymax, const double zmin, const double zmax)
bool LoadData(const std::string filename, std::string format, const bool withPotential, const bool withRegion, const double scaleX=1., const double scaleE=1., const double scaleP=1.)
std::string GetName() const
Definition: Medium.hh:22