neBEM
The steps for obtaining an electrostatic field solution using neBEM are:
- Build the device geometry.
- Create different components of the device geometry.
- Set boundary conditions for each component.
- Associate a medium (conductor, dielectric, gas) to each component.
- Initialize neBEM.
- Pass the geometry to neBEM.
- Specify discretization requirements.
- Solve the field problem.
For example, by using the following portion of RPCbyneBEM.C, we build a simplified RPC (without button spacers).
MediumPlastic glass;
glass.SetDielectricConstant(10.0);
// Geometry.
GeometrySimple geo;
SolidBox box1(0, 0, -0.52, 5, 5, 0.01); // top graphite
box1.SetBoundaryPotential(1000.);
geo.AddSolid(&box1, &graphite);
SolidBox box2(0, 0, -0.5, 5, 5, 0.1); // top glass
box2.SetBoundaryDielectric();
geo.AddSolid(&box2, &glass);
SolidBox box3(0, 0, 0.5, 5, 5, 0.1); // bottom glass
box3.SetBoundaryDielectric();
geo.AddSolid(&box3, &glass);
SolidBox box4(0, 0, 0.52, 5, 5, 0.01); // bottom graphite
box4.SetBoundaryPotential(-1000.);
geo.AddSolid(&box4, &graphite);
SolidBox box5(-5, 0, 0, 0.1, 5, 0.4); // side spacer 1
box5.SetBoundaryDielectric();
geo.AddSolid(&box5, &glass);
SolidBox box6(5, 0, 0, 0.1, 5, 0.4); // side spacer 2
box6.SetBoundaryDielectric();
geo.AddSolid(&box6, &glass);
SolidBox box7(0., -5., 0., 4.9, 0.1, 0.4); // side spacer 3
box7.SetBoundaryDielectric();
geo.AddSolid(&box7, &glass);
SolidBox box8(0., 5., 0., 4.9, 0.1, 0.4); // side spacer 4
box8.SetBoundaryDielectric();
geo.AddSolid(&box8, &glass);
Here, we have created one thin graphite layer on top of a dielectric box. Similarly, the bottom glass plate with another thin graphite layer below it is created. Finally, the side spacers, all made of glass, are placed. Each component has its own boundary condition and material associated to it. Please note that the dielectric components need the following line
box2.SetBoundaryDielectric();
This device geometry can now be solved for electrostatics using the following segment of the code.
ComponentNeBem3d nebem;
nebem.SetGeometry(&geo);
nebem.SetTargetElementSize(0.005);
nebem.SetMinMaxNumberOfElements(3, 15);
nebem.Initialise();
Let us consider another example where a geometry of a biconical GEM is created and solved for electrostatics. Here, besides creating holes, we also use the useful concept of periodic repetitions.
SolidBox cathode(drftx, drfty, drftz, lenLX/2.0, lenLY/2.0, drftLZ/2.0);
cathode.SetBoundaryPotential(drftV);
geo.AddSolid(&cathode, &Cu);
SolidHole topCu(upcprx, upcpry, upcprz, maxdia/2.0, maxdia/2.0, lenLX/2.0, lenLY/2.0, upcprLZ/2.0);
topCu.SetSectors(3);
topCu.SetBoundaryPotential(upcprV);
geo.AddSolid(&topCu, &Cu);
SolidHole topKapton(kptx, kpty, (kptz+(kptLZ/4.0)), maxdia/2.0, mindia/2.0, lenLX/2.0, lenLY/2.0, kptLZ/4.0);
topKapton.SetSectors(3);
topKapton.SetBoundaryDielectric();
geo.AddSolid(&topKapton, &Kp);
SolidHole btmKapton(kptx, kpty, (kptz-(kptLZ/4.0)), mindia/2.0, maxdia/2.0, lenLX/2.0, lenLY/2.0, kptLZ/4.0);
btmKapton.SetSectors(3);
btmKapton.SetBoundaryDielectric();
geo.AddSolid(&btmKapton, &Kp);
SolidHole btmCu(lwcprx, lwcpry, lwcprz, maxdia/2.0, maxdia/2.0, lenLX/2.0, lenLY/2.0, lwcprLZ/2.0);
btmCu.SetSectors(3);
btmCu.SetBoundaryPotential(lwcprV);
geo.AddSolid(&btmCu, &Cu);
SolidBox anode(anodex, anodey, anodez, lenLX/2.0, lenLY/2.0, anodeLZ/2.0);
anode.SetBoundaryPotential(anodeV);
geo.AddSolid(&anode, &Cu)
Please note that
- A
SolidHole
object can have two different radii (maxdia, mindia). Combining two such holes, we have created a kapton foil with biconical hole. - A hole is represented by a polygon. The number of sides of the polygon is controlled as in
This geometry is solved by using the following code segment:
topCu.SetSectors(3);
double tgtElSize = 10.e-4;
int minEl = 3, maxEl = 5;
int xcopy = 10, ycopy = 10, zcopy = 0;
ComponentNeBem3d nebem;
nebem.SetGeometry(&geo);
nebem.SetTargetElementSize(tgtElSize);
nebem.SetMinMaxNumberOfElements(minEl, maxEl);
nebem.SetPeriodicityX(lenLX);
nebem.SetPeriodicityY(lenLY);
nebem.SetPeriodicCopies(xcopy, ycopy, zcopy);
nebem.UseLUInversion();
// nebem.EnableDebugging();
nebem.Initialise();
The new functions that are of particular importance here are those that control the number of periodic repetitions of the base device geometry.
nebem.SetPeriodicityX(lenLX);
nebem.SetPeriodicityY(lenLY);
nebem.SetPeriodicCopies(xcopy, ycopy, zcopy);
and the one that controls the matrix decomposition method
nebem.UseLUInversion();
Finally, for creating a simple MWPC geometry, we can use (from MWPCbyneBEM.C):
// Geometry.
GeometrySimple geo;
SolidBox box1(0, 0, -0.5, 5., 5., 0.1);
box1.SetBoundaryPotential(0.);
SolidBox box2(0, 0, 0.5, 5., 5., 0.1);
box2.SetBoundaryPotential(0.);
geo.AddSolid(&box1, &Cu);
geo.AddSolid(&box2, &Cu);
const double radius = 0.1;
const double halflength = 5.;
std::vector<SolidWire*> wires(5, nullptr);
for (int i = 0; i < 5; ++i) {
int j = i - 2;
double xpos = 0.0 + (double)j*1.;
wires[i] = new SolidWire(xpos, 0.0, 0.0, radius, halflength, 0, 1, 0);
wires[i]->SetBoundaryPotential(1000.0);
geo.AddSolid(wires[i], &Cu);
}
In general, using ROOT for graphical display is fine for the development phase. During this phase, very coarse discretization and very few periodic repetition are usually used and the execution is over quickly. However, for production runs, it is better to get the data in field output files and examine them offline. For the biconical GEM, if we want to have plain text output files, the following segment can be used:
// field on surface
std::ofstream fldfile;
fldfile.open("FieldSurface.out");
int nx = 101, nz = 101;
double zoffset = 100.0e-4;
double delx = lenLX / (double)(nx - 1);
double delz = ((upcprz+zoffset) - (lwcprz-zoffset)) / (double)(nz - 1);
double yp = 0.0;
Medium* medium = nullptr;
double ex = 0., ey = 0., ez = 0., e = 0.0, v = 0.;
int status = 0;
for (int ix = 0; ix < nx; ++ix) {
double xp = (-lenLX / 2.0) + ix*delx;
for (int iz = 0; iz < nz; ++iz) {
double zp = (lwcprz-zoffset) + iz*delz;
nebem.ElectricField(xp, yp, zp, ex, ey, ez, v, medium, status);
e = sqrt(ex*ex + ey*ey + ez*ez);
fldfile << xp << " " << yp << " " << zp << " " << ex << " " << ey << " " << ez << " " << e << " " << v << " " << medium << " " << status << std::endl;
} // iz loop
fldfile << std::endl;
} // ix loop
fldfile.close();
Source files
The source code of these example applications can be found in Examples/neBEM.