1 package org.lcsim.geometry.field;
2
3 import hep.physics.vec.BasicHep3Vector;
4 import java.io.BufferedReader;
5 import java.io.File;
6 import java.io.FileReader;
7 import java.io.IOException;
8 import org.jdom.Element;
9 import org.jdom.JDOMException;
10 import java.net.URL;
11 import org.lcsim.util.cache.FileCache;
12 import static java.lang.Math.abs;
13 import static java.lang.Math.sqrt;
14 import static java.lang.Math.atan2;
15 import static java.lang.Math.sin;
16 import static java.lang.Math.cos;
17
18
19
20
21
22 public class RZFieldMap extends AbstractFieldMap
23 {
24 private int numBinsR;
25 private int numBinsZ;
26
27 private double gridSizeR;
28 private double gridSizeZ;
29
30 private double maxZ;
31 private double maxR;
32 private double maxRSquared;
33
34 private String location;
35
36 private double[][] BrArray;
37 private double[][] BzArray;
38
39 public RZFieldMap(Element node) throws JDOMException
40 {
41 super(node);
42
43 numBinsR = node.getAttribute("numBinsR").getIntValue();
44
45 if (numBinsR < 2)
46 {
47 throw new JDOMException("numBinsR is invalid: " + numBinsR);
48 }
49
50 numBinsZ = node.getAttribute("numBinsZ").getIntValue();
51
52 if (numBinsZ < 2)
53 {
54 throw new JDOMException("numBinsZ is invalid: " + numBinsZ);
55 }
56
57
58 gridSizeR = node.getAttribute("gridSizeR").getDoubleValue() * 10;
59 gridSizeZ = node.getAttribute("gridSizeZ").getDoubleValue() * 10;
60
61 maxR = ( numBinsR - 1 ) * gridSizeR;
62 maxZ = ( numBinsZ - 1 ) * gridSizeZ;
63 maxRSquared = maxR*maxR;
64
65 BrArray = new double[numBinsZ][numBinsR];
66 BzArray = new double[numBinsZ][numBinsR];
67
68 location = node.getAttribute("url").getValue();
69
70 try
71 {
72 readFieldMap();
73 }
74 catch (Exception e)
75 {
76 throw new RuntimeException("Error reading field map from " + location, e);
77 }
78 }
79
80 private void readFieldMap() throws IOException
81 {
82 readFieldMap(this.location);
83 }
84
85 private void readFieldMap(String location) throws IOException
86 {
87 FileCache cache = new FileCache();
88 File file = cache.getCachedFile(new URL(location));
89
90 BufferedReader reader = new BufferedReader(new FileReader(file));
91
92 for (;;)
93 {
94 String line = reader.readLine();
95 if (line == null) break;
96 String[] chunks = line.trim().split(" +");
97
98 if ( chunks.length > 0 )
99 {
100 if ( chunks.length != 4 )
101 {
102 throw new IOException("Invalid RZ field map line: " + line);
103 }
104
105
106 double z = Double.parseDouble(chunks[0]) * 10;
107 double r = Double.parseDouble(chunks[1]) * 10;
108
109
110 double Bz = Double.parseDouble(chunks[2]) / 10;
111 double Br = Double.parseDouble(chunks[3]) / 10;
112
113 int iz= (int) ((z + 0.0001)/gridSizeZ);
114 int ir=(int) ((r + 0.0001)/gridSizeR);
115
116 if ( iz > ( numBinsZ - 1) )
117 {
118 throw new IOException("z bin out of range: " + iz);
119 }
120
121 if ( ir > ( numBinsR - 1) )
122 {
123 throw new IOException("r bin out of range:" + ir);
124 }
125
126 BzArray[iz][ir] = Bz;
127 BrArray[iz][ir] = Br;
128 }
129 }
130 }
131
132 void getField(double x, double y, double z, BasicHep3Vector field)
133 {
134 double rSquared = x*x + y*y;
135
136 double hz = 0;
137 double hr = 0;
138
139 if(abs(z)>maxZ || rSquared>maxRSquared)
140 {
141 field.setV(0,0,0);
142 return;
143 }
144 double r = sqrt(rSquared);
145
146 int iz = (int) ((abs(z)+0.001)/gridSizeZ);
147 int ir = (int) ((r+0.001)/gridSizeR);
148
149
150 if(iz<0 || ir>numBinsR)
151 {
152 field.setV(0,0,0);
153 return;
154 }
155
156 int izfar = 0;
157 if(iz>=numBinsZ)
158 {
159 izfar = 1;
160 iz = numBinsZ;
161 }
162
163 double bz0 = BzArray[iz][ir];
164 double br0 = BrArray[iz][ir];
165
166 double delz = 0.;
167 double delr = 0.;
168
169 double brdz = 0.;
170 double brdr = 0.;
171
172 if(r>0.0)
173 {
174 delr = r - ((float)ir) * gridSizeR;
175 brdz = (BrArray[iz+1][ir]-br0)/gridSizeZ;
176 brdr = (BrArray[iz][ir+1]-br0)/gridSizeR;
177 }
178
179 delz = abs(z) - ((float)iz) * gridSizeZ;
180
181 double bzdz = (BzArray[iz+1][ir]-bz0)/gridSizeZ;
182 double bzdr = (BzArray[iz][ir+1]-bz0)/gridSizeR;
183
184 if(izfar==1)
185 {
186 hz = bz0+bzdr*delr;
187 hr = br0+brdr*delr;
188 }
189 else
190 {
191 hz = bz0+bzdz*delz+bzdr*delr;
192 hr = br0+brdz*delz+brdr*delr;
193 }
194
195 if(z<0.0) hr = -hr;
196
197 double theta = atan2(y, x);
198 double hx = hr * cos(theta);
199 double hy = hr * sin(theta);
200
201 field.setV(hx,hy,hz);
202 }
203
204 public final int getNumBinsR()
205 {
206 return numBinsR;
207 }
208
209 public final int getNumBinsZ()
210 {
211 return numBinsZ;
212 }
213
214 public final double getGridSizeR()
215 {
216 return gridSizeR;
217 }
218
219 public final double getGridSizeZ()
220 {
221 return gridSizeZ;
222 }
223
224 public final double getMaxZ()
225 {
226 return maxZ;
227 }
228
229 public final double getMaxR()
230 {
231 return maxR;
232 }
233 }