Garfield++ 5.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
ReTriM.c
Go to the documentation of this file.
1/*
2(c) 2005, Supratik Mukhopadhayay, Nayana Majumdar
3*/
4
5#include <stdio.h>
6#include <time.h>
7#include <unistd.h>
8
9#include "Isles.h"
10#include "NR.h"
11#include "Vector.h"
12#include "neBEM.h"
13#include "neBEMInterface.h"
14
15#define MyPI 3.14159265358979323846
16
17#ifdef __cplusplus
18namespace neBEM {
19#endif
20
21// GCS: global coordinate system
22// PCS: primitive coordinate system
23// ECS: element coordinate system
24
25// How do we decide on the number of elements, in each direction, appropriate
26// for a given surface?
27// Since no linear element is being considered, no assumption is being made
28// regarding a linear element for the time being.
29// shall we return the pointer to the element array here? That seems to be
30// more intuitive!
31// Note that for the right triangle, the second vertex (vertex[1], since the
32// vector begins from 0) is the 90 degree corner.
33int SurfaceElements(int prim, int nvertex, double xvert[], double yvert[],
34 double zvert[], double xnorm, double ynorm, double znorm,
35 int volref1, int volref2, int inttype, double potential,
36 double charge, double lambda, int NbSegX, int NbSegZ) {
37 // Decide the geometry of this primitive - if it is a rectangle, our job is
38 // greatly simplified. To begin with, we check the number of vertices to
39 // take the decision automatically.
40 // Note that a triangle is the next best bet. All other primitive will have to
41 // be reduced to rectangles (as many as possible) and triangles.
42 // Incidentally, a PrimType (determined in neBEMReadGeom (neBEMInterface.c))
43 // determines whether the primitive is a surface (2D) or a wire (1D),
44 // for a given surface, SurfShape determines whether it is a triangle,
45 // rectangle, or any other polygon besides these two (square is, of course, a
46 // special case of rectangle)
47 int fstatus;
48 switch (nvertex) {
49 case 3: // triangle
50 fstatus = DiscretizeTriangle(prim, nvertex, xvert, yvert, zvert, xnorm,
51 ynorm, znorm, volref1, volref2, inttype,
52 potential, charge, lambda, NbSegX, NbSegZ);
53 // assert(fstatus == 0);
54 if (fstatus != 0) {
55 neBEMMessage("SurfaceElements - DiscretizeTriangle");
56 return -1;
57 }
58 break;
59
60 case 4: // rectangle
61 fstatus = DiscretizeRectangle(prim, nvertex, xvert, yvert, zvert, xnorm,
62 ynorm, znorm, volref1, volref2, inttype,
63 potential, charge, lambda, NbSegX, NbSegZ);
64 // assert(fstatus == 0);
65 if (fstatus != 0) {
66 neBEMMessage("SurfaceElements - DiscretizeRectangle");
67 return -1;
68 }
69 break;
70
71 default:
72 printf("nvertex out of bounds in SurfaceElements ... exiting ...\n");
73 exit(-1);
74 }
75
76 return (0);
77} // end of SurfaceElements
78
79// Analyze wire and break up into smaller wire elements
80// How do we decide on the number of elements? Currently, it is based on user
81// inputs that need to be made automatic and adaptive
82int WireElements(int prim, int nvertex, double xvert[], double yvert[],
83 double zvert[], double radius, int volref1, int volref2,
84 int inttype, double potential, double charge, double lambda,
85 int NbSegs) {
86 int fstatus;
87
88 switch (nvertex) {
89 case 2: // wire
90 fstatus =
91 DiscretizeWire(prim, nvertex, xvert, yvert, zvert, radius, volref1,
92 volref2, inttype, potential, charge, lambda, NbSegs);
93 // assert(fstatus == 0);
94 if (fstatus != 0) {
95 neBEMMessage("WireElements - DiscretizeWire");
96 return -1;
97 }
98 break;
99
100 default:
101 printf("nvertex out of bounds in WireElements ... exiting ...\n");
102 exit(-1);
103 }
104
105 return (0);
106} // end of WireElement
107
108// Try to set up elements on this primitive such that the average element area
109// is close to what has been requested.
110// If the number of elements is too small (<5), over-ride and have 5*5 elements
111// If the size of the element is too small (<MINDIST2), or a side of the element
112// is too small (<MINDIST), over-ride 5*5 and create elements (3*3) and (1*1)
113// such that they are of acceptable size and shape (the latter, if possible)
114// If the primitive is smaller than MINDIST * MINDIST, report and quit
115// If the number of elements is more than a limit, make the element size
116// larger than that requested. Report the incidences.
117// Since, for a surface primitive, the larger number between Coord1Seg and
118// Coord2Seg is used for the longer arm (look for OverSmart in
119// DiscretizeTriangle and DiscretizeRectagnle), the aspect ratio problem is
120// expected to be taken care of to a large extent.
121int AnalyzePrimitive(int prim, int *NbSegCoord1, int *NbSegCoord2) {
122 int fstatus;
123
124 switch (NbVertices[prim]) {
125 case 2: // wire
126 fstatus = AnalyzeWire(prim, NbSegCoord1);
127 *NbSegCoord2 = 0;
128 // assert(fstatus == 0);
129 if (fstatus != 0) {
130 neBEMMessage("AnalyzePrimitive - AnalyzeWire");
131 return -1;
132 }
133 return (2);
134 break;
135 case 3: // triangle
136 fstatus = AnalyzeSurface(prim, NbSegCoord1, NbSegCoord2);
137 // assert(fstatus == 0);
138 if (fstatus != 0) {
139 neBEMMessage("AnalyzePrimitive - AnalyzeSurface");
140 return -1;
141 }
142 return (3);
143 break;
144 case 4: // rectangle
145 fstatus = AnalyzeSurface(prim, NbSegCoord1, NbSegCoord2);
146 // assert(fstatus == 0);
147 if (fstatus != 0) {
148 neBEMMessage("AnalyzePrimitive - AnalyzeSurface");
149 return -1;
150 }
151 return (4);
152 break;
153 default: // no shape!
154 return (0);
155 }
156} // end of AnalyzePrimitive
157
158int AnalyzeWire(int prim, int *NbSeg) {
159 int nb = *NbSeg;
160
161 if (nb < 1) // absurd! use the trio: target, min, max
162 {
163 double lWire = (XVertex[prim][1] - XVertex[prim][0]) *
164 (XVertex[prim][1] - XVertex[prim][0]) +
165 (YVertex[prim][1] - YVertex[prim][0]) *
166 (YVertex[prim][1] - YVertex[prim][0]) +
167 (ZVertex[prim][1] - ZVertex[prim][0]) *
168 (ZVertex[prim][1] - ZVertex[prim][0]);
169 lWire = sqrt(lWire);
170
171 nb = (int)(lWire / ElementLengthRqstd);
172
173 if ((nb > MinNbElementsOnLength) &&
174 (nb < MaxNbElementsOnLength)) { // nothing to be done
175 }
176 // Check whether the length of the wire primitive is long enough
177 else if (lWire < MINDIST) {
178 nb = 1;
179 fprintf(fMeshLog, "Wire element too small on primitive %d!\n", prim);
180 } // if lWire < MINDIST
181 // Need to have at least MinNbElementsOnLength elements per wire primitive
182 else if (nb < MinNbElementsOnLength) {
184 double ellength = lWire / (double)nb;
185 if (ellength <
186 MINDIST) // which may not be possible if the length is small
187 {
188 nb = (int)(lWire / MINDIST);
189 if (nb < 1) // However, it is necessary to have at least one element!
190 {
191 nb = 1;
192 fprintf(fMeshLog, "Wire element very small on primitive %d!\n", prim);
193 }
194 }
195 } // if nb < MinNbElementsOnLength
196 else if (nb > MaxNbElementsOnLength) {
198 fprintf(fMeshLog, "Too many elements on wire primitive %d!\n", prim);
199 fprintf(fMeshLog, "Number of elements reduced to maximum allowed %d\n",
201 } // if nb > MaxNbElementsOnLength
202
203 *NbSeg = nb;
204
205 fprintf(fMeshLog, "Number of elements on wire primitive %d is %d.\n\n",
206 prim, *NbSeg);
207 } else { // number of dicretization specified by user
208 double lWire = (XVertex[prim][1] - XVertex[prim][0]) *
209 (XVertex[prim][1] - XVertex[prim][0]) +
210 (YVertex[prim][1] - YVertex[prim][0]) *
211 (YVertex[prim][1] - YVertex[prim][0]) +
212 (ZVertex[prim][1] - ZVertex[prim][0]) *
213 (ZVertex[prim][1] - ZVertex[prim][0]);
214 lWire = sqrt(lWire);
215
216 double ellength = lWire / (double)nb;
217
218 if (lWire < MINDIST) // at least one element is a necessity
219 {
220 nb = 1;
221 fprintf(fMeshLog, "Fatal: Wire element too small on primitive %d!\n",
222 prim);
223 } // if lWire < MINDIST
224 else if (ellength < MINDIST) // element length more than twice MINDIST
225 {
226 nb = (int)(lWire / (2.0 * MINDIST));
227 if (nb < 1) {
228 nb = 1;
229 fprintf(fMeshLog, "Fatal: Wire element too small on primitive %d!\n",
230 prim);
231 }
232 } // if ellength < MINDIST
233
234 *NbSeg = nb;
235
236 fprintf(fMeshLog, "Number of elements on wire primitive %d is %d.\n\n",
237 prim, *NbSeg);
238 }
239
240 if (nb)
241 return 0;
242 else
243 return -1;
244} // AnalyzeWire ends
245
246int AnalyzeSurface(int prim, int *NbSegCoord1, int *NbSegCoord2) {
247 int nb1 = *NbSegCoord1, nb2 = *NbSegCoord2;
248
249 if ((nb1 < 1) || (nb2 < 1)) // absurd! use the trio: target, min, max
250 {
251 // Triangle primitives have their right angle on vertex 1
252 double l1 = (XVertex[prim][0] - XVertex[prim][1]) *
253 (XVertex[prim][0] - XVertex[prim][1]) +
254 (YVertex[prim][0] - YVertex[prim][1]) *
255 (YVertex[prim][0] - YVertex[prim][1]) +
256 (ZVertex[prim][0] - ZVertex[prim][1]) *
257 (ZVertex[prim][0] - ZVertex[prim][1]);
258 l1 = sqrt(l1);
259 double l2 = (XVertex[prim][2] - XVertex[prim][1]) *
260 (XVertex[prim][2] - XVertex[prim][1]) +
261 (YVertex[prim][2] - YVertex[prim][1]) *
262 (YVertex[prim][2] - YVertex[prim][1]) +
263 (ZVertex[prim][2] - ZVertex[prim][1]) *
264 (ZVertex[prim][2] - ZVertex[prim][1]);
265 l2 = sqrt(l2);
266
267 // We can use the lengths independently and forget about area
268 // for the time being
269
270 // double area = l1 * l2;
271
272 nb1 = (int)(l1 / ElementLengthRqstd);
273 if ((nb1 > MinNbElementsOnLength) && (nb1 < MaxNbElementsOnLength)) {
274 // nothing to be done
275 } else if (l1 < MINDIST) {
276 fprintf(fMeshLog, "Length1 too small on primitive %d!\n", prim);
277 nb1 = 1;
278 } else if (nb1 < MinNbElementsOnLength) {
279 // Need to have at least MinNbElementsOnLength elements per wire primitive
281 double ellength = l1 / (double)nb1;
282 // which may not be possible if the length is small
283 if (ellength < MINDIST) {
284 nb1 = (int)(l1 / MINDIST);
285 // However, it is necessary to have at least one element!
286 if (nb1 < 1) {
287 fprintf(fMeshLog, "Length1 very small on primitive %d!\n", prim);
288 nb1 = 1;
289 }
290 }
291 } // else if nb1 < MinNbElementsOnLength
292
293 if (nb1 > MaxNbElementsOnLength) {
294 fprintf(fMeshLog, "Too many elements on Length1 for primitive %d!\n",
295 prim);
296 fprintf(fMeshLog, "Number of elements reduced to maximum allowed %d\n",
299 }
300
301 nb2 = (int)(l2 / ElementLengthRqstd);
302 if ((nb2 > MinNbElementsOnLength) && (nb2 < MaxNbElementsOnLength)) {
303 // nothing to be done
304 } else if (l2 < MINDIST) {
305 fprintf(fMeshLog, "Length2 element too small on primitive %d!\n", prim);
306 nb2 = 1;
307 } else if (nb2 < MinNbElementsOnLength) {
308 // Need to have at least MinNbElementsOnLength elements per wire primitive
310 double ellength = l2 / (double)nb2;
311 // which may not be possible if the length is small
312 if (ellength < MINDIST) {
313 // However, it is necessary to have at least one element!
314 nb2 = (int)(l2 / MINDIST);
315 if (nb2 < 1) {
316 fprintf(fMeshLog, "Length2 element very small on primitive %d!\n",
317 prim);
318 nb2 = 1;
319 }
320 }
321 } // else if nb2 < MinNbElementsOnLength
322
323 if (nb2 > MaxNbElementsOnLength) {
324 fprintf(fMeshLog, "Too many elements on Length2 of primitive %d!\n",
325 prim);
326 fprintf(fMeshLog, "Number of elements reduced to maximum allowed %d\n",
329 }
330
331 *NbSegCoord1 = nb1;
332 *NbSegCoord2 = nb2;
333
334 fprintf(fMeshLog,
335 "Number of elements on surface primitive %d is %d X %d.\n\n", prim,
336 *NbSegCoord1, *NbSegCoord2);
337 } else { // number of discretization specified by the user
338 // Triangle primitives have their right angle on the vertex 1
339 double l1 = (XVertex[prim][0] - XVertex[prim][1]) *
340 (XVertex[prim][0] - XVertex[prim][1]) +
341 (YVertex[prim][0] - YVertex[prim][1]) *
342 (YVertex[prim][0] - YVertex[prim][1]) +
343 (ZVertex[prim][0] - ZVertex[prim][1]) *
344 (ZVertex[prim][0] - ZVertex[prim][1]);
345 l1 = sqrt(l1);
346 double l2 = (XVertex[prim][2] - XVertex[prim][1]) *
347 (XVertex[prim][2] - XVertex[prim][1]) +
348 (YVertex[prim][2] - YVertex[prim][1]) *
349 (YVertex[prim][2] - YVertex[prim][1]) +
350 (ZVertex[prim][2] - ZVertex[prim][1]) *
351 (ZVertex[prim][2] - ZVertex[prim][1]);
352 l2 = sqrt(l2);
353
354 if (l1 > l2) {
355 if (nb2 > nb1) {
356 // swap numbers to allow larger number to larger side
357 int tmpnb = nb1;
358 nb1 = nb2;
359 nb2 = tmpnb;
360 }
361 } // if l1 > l2
362
363 double ellength1 = l1 / (double)nb1;
364 double ellength2 = l2 / (double)nb2;
365
366 if (l1 < MINDIST) {
367 nb1 = 1;
368 fprintf(fMeshLog, "Fatal: Side length l1 too small! prim: %d\n", prim);
369 } else if (ellength1 < MINDIST) // element length more than twice MINDIST
370 {
371 nb1 = (int)(l1 / (2.0 * MINDIST));
372 if (nb1 < 1) {
373 nb1 = 1;
374 fprintf(fMeshLog, "Fatal: Side length l1 too small on primitive %d!\n",
375 prim);
376 }
377 } // if ellength1 < MINDIST
378
379 if (l2 < MINDIST) {
380 nb2 = 1;
381 fprintf(fMeshLog, "Fatal: Side length l2 too small! prim: %d\n", prim);
382 } else if (ellength2 < MINDIST) // element length more than twice MINDIST
383 {
384 nb2 = (int)(l2 / (2.0 * MINDIST));
385 if (nb2 < 1) {
386 nb2 = 1;
387 fprintf(fMeshLog, "Fatal: Side length l2 too small on primitive %d!\n",
388 prim);
389 }
390 } // if ellength2 < MINDIST
391
392 *NbSegCoord1 = nb1;
393 *NbSegCoord2 = nb2;
394
395 fprintf(fMeshLog,
396 "Number of elements on surface primitive %d is %d X %d.\n\n", prim,
397 *NbSegCoord1, *NbSegCoord2);
398 }
399
400 if ((nb1 > 0) && (nb2 > 0))
401 return 0;
402 else
403 return -1;
404} // AnalyzeSurface ends
405
406// Discretize wire into linear wire elements
407int DiscretizeWire(int prim, int nvertex, double xvert[], double yvert[],
408 double zvert[], double radius, int volref1, int volref2,
409 int inttype, double potential, double charge, double lambda,
410 int NbSegs) {
411 int WireParentObj, WireEType;
412 double WireR, WireL;
413 double WireLambda, WireV;
414 double WireElX, WireElY, WireElZ, WireElL;
415 DirnCosn3D PrimDirnCosn; // direction cosine of the current primitive
416
417 char gpElem[256];
418 FILE *fPrim, *fElem, *fgpPrim, *fgpElem;
419
420 // Check inputs
421 if (PrimType[prim] != 2) {
422 neBEMMessage("DiscretizeWire - PrimType in DiscretizeWire");
423 return -1;
424 }
425 if (nvertex != 2) {
426 neBEMMessage("DiscretizeWire - nvertex in DiscretizeWire");
427 return -1;
428 }
429 if (radius < MINDIST) {
430 neBEMMessage("DiscretizeWire - radius in DiscretizeWire");
431 return -1;
432 }
433 if (NbSegs <= 0) {
434 neBEMMessage("DiscretizeWire - NbSegs in DiscretizeWire");
435 return -1;
436 }
437
439 printf("nvertex: %d\n", nvertex);
440 for (int vert = 0; vert < nvertex; ++vert) {
441 printf("vert: %d, x: %lg, y: %lg, z: %lg\n", vert, xvert[vert],
442 yvert[vert], zvert[vert]);
443 }
444 printf("radius: %lg\n", radius);
445 } // if OptPrintVertexAndNormal
446
447 // necessary for separating filenames
448 char primstr[10];
449 snprintf(primstr, 10, "%d", prim);
450
451 // in order to avoid warning messages
452 fPrim = NULL;
453 fElem = NULL;
454 fgpElem = NULL;
455
456 WireParentObj = 1; // ParentObj not being used now
457
458 WireL = sqrt((xvert[1] - xvert[0]) * (xvert[1] - xvert[0]) // length of wire
459 + (yvert[1] - yvert[0]) * (yvert[1] - yvert[0]) +
460 (zvert[1] - zvert[0]) * (zvert[1] - zvert[0]));
461 WireR = radius;
462 WireElL = WireL / NbSegs; // length of each wire element
463
464 // Direction cosines along the wire - note difference from surface primitives!
465 // The direction along the wire is considered to be the z axis of the LCS
466 // So, let us fix that axial vector first
467 PrimDirnCosn.ZUnit.X = (xvert[1] - xvert[0]) / WireL; // useful
468 PrimDirnCosn.ZUnit.Y = (yvert[1] - yvert[0]) / WireL;
469 PrimDirnCosn.ZUnit.Z = (zvert[1] - zvert[0]) / WireL; // useful
470 // Next, let us find out the coefficients of a plane that passes through the
471 // wire centroid and is normal to the axis of the wire. This is basically the
472 // mid-plane of the cylindrical wire
473 // Any vector OR on the plane normal to the axial direction satisfies
474 // \vec{OR} . \vec{OA} = 0
475 // where O is the wire centroid, A is a point on the axis and R is a point on
476 // the cylindrical surface of the wire. \vec{OA} can be easily replaced by the
477 // axial vector that is equivalent to the vector PrimDirnCosn.ZUnit
478 // The equation of the plane can be shown to be:
479 // XCoef * X + YCoef * Y + ZCoef * Z = Const
480 // double XCoef, YCoef, ZCoef, Const; - not needed any more
481 // double rnorm;
482 // Point3D O, R;
483 // Vector3D OR;
484 // O = CreatePoint3D(WireX, WireY, WireZ);
485 {
486 Vector3D XUnit, YUnit, ZUnit;
487 ZUnit.X = PrimDirnCosn.ZUnit.X;
488 ZUnit.Y = PrimDirnCosn.ZUnit.Y;
489 ZUnit.Z = PrimDirnCosn.ZUnit.Z;
490
491 /* old code - abs instead of fabs??!!
492 XCoef = ZUnit.X;
493 YCoef = ZUnit.Y;
494 ZCoef = ZUnit.Z;
495 double WireX = 0.5 * (xvert[1] + xvert[0]);
496 double WireY = 0.5 * (yvert[1] + yvert[0]);
497 double WireZ = 0.5 * (zvert[1] + zvert[0]);
498 Const = WireX * ZUnit.X + WireY * ZUnit.Y + WireZ * ZUnit.Z;
499 if(abs(XCoef) < 1.0e-12) // X can be anything!
500 {
501 XUnit.X = 1.0;
502 XUnit.Y = 0.0;
503 XUnit.Z = 0.0;
504 YUnit = Vector3DCrossProduct(ZUnit, XUnit);
505 }
506 else
507 {
508 // For a point on the above surface where both Y and Z are zero
509 O = CreatePoint3D(WireX, WireY, WireZ);
510 R = CreatePoint3D(Const, 0, 0);
511 // Create the vector joining O and R; find X and Y unit vectors
512 OR = CreateDistanceVector3D(O,R);
513 XUnit = UnitVector3D(OR);
514 YUnit = Vector3DCrossProduct(ZUnit, XUnit);
515 }
516 old code */
517
518 // replaced following Rob's suggestions (used functions instead of direct
519 // evaluation, although the latter is probably faster)
520 // x-Axis: orthogonal in the 2 largest components.
521 if (fabs(ZUnit.X) >= fabs(ZUnit.Z) && fabs(ZUnit.Y) >= fabs(ZUnit.Z)) {
522 XUnit.X = -ZUnit.Y;
523 XUnit.Y = ZUnit.X;
524 XUnit.Z = 0.0;
525 } else if (fabs(ZUnit.X) >= fabs(ZUnit.Y) &&
526 fabs(ZUnit.Z) >= fabs(ZUnit.Y)) {
527 XUnit.X = -ZUnit.Z;
528 XUnit.Y = 0.0;
529 XUnit.Z = ZUnit.X;
530 } else {
531 XUnit.X = 0.0;
532 XUnit.Y = ZUnit.Z;
533 XUnit.Z = -ZUnit.Y;
534 }
535 XUnit = UnitVector3D(&XUnit);
536
537 // y-Axis: vectorial product of axes 1 and 2.
538 YUnit = Vector3DCrossProduct(&ZUnit, &XUnit);
539 YUnit = UnitVector3D(&YUnit);
540 // end of replacement
541
542 PrimDirnCosn.XUnit.X = XUnit.X;
543 PrimDirnCosn.XUnit.Y = XUnit.Y;
544 PrimDirnCosn.XUnit.Z = XUnit.Z;
545 PrimDirnCosn.YUnit.X = YUnit.X;
546 PrimDirnCosn.YUnit.Y = YUnit.Y;
547 PrimDirnCosn.YUnit.Z = YUnit.Z;
548 } // X and Y direction cosines computed
549
550 // primitive direction cosine assignments
551 PrimDC[prim].XUnit.X = PrimDirnCosn.XUnit.X;
552 PrimDC[prim].XUnit.Y = PrimDirnCosn.XUnit.Y;
553 PrimDC[prim].XUnit.Z = PrimDirnCosn.XUnit.Z;
554 PrimDC[prim].YUnit.X = PrimDirnCosn.YUnit.X;
555 PrimDC[prim].YUnit.Y = PrimDirnCosn.YUnit.Y;
556 PrimDC[prim].YUnit.Z = PrimDirnCosn.YUnit.Z;
557 PrimDC[prim].ZUnit.X = PrimDirnCosn.ZUnit.X;
558 PrimDC[prim].ZUnit.Y = PrimDirnCosn.ZUnit.Y;
559 PrimDC[prim].ZUnit.Z = PrimDirnCosn.ZUnit.Z;
560
561 // primitive origin: also the barycenter for a wire element
562 PrimOriginX[prim] = 0.5 * (xvert[0] + xvert[1]);
563 PrimOriginY[prim] = 0.5 * (yvert[0] + yvert[1]);
564 PrimOriginZ[prim] = 0.5 * (zvert[0] + zvert[1]);
565 PrimLX[prim] = WireR; // radius for wire
566 PrimLZ[prim] = WireL; // length of wire
567
568 WireEType = inttype;
569 WireV = potential;
570 WireLambda = lambda;
571
572 // file output for a primitive
573 if (OptPrimitiveFiles) {
574 char OutPrim[256];
575 strcpy(OutPrim, ModelOutDir);
576 strcat(OutPrim, "/Primitives/Primitive");
577 strcat(OutPrim, primstr);
578 strcat(OutPrim, ".out");
579 fPrim = fopen(OutPrim, "w");
580 if (fPrim == NULL) {
581 neBEMMessage("DiscretizeWire - OutPrim");
582 return -1;
583 }
584 fprintf(fPrim, "#prim: %d, nvertex: %d\n", prim, nvertex);
585 fprintf(fPrim, "Node1: %lg\t%lg\t%lg\n", xvert[0], yvert[0], zvert[0]);
586 fprintf(fPrim, "Node2: %lg\t%lg\t%lg\n", xvert[1], yvert[1], zvert[1]);
587 fprintf(fPrim, "PrimOrigin: %lg\t%lg\t%lg\n", PrimOriginX[prim],
588 PrimOriginY[prim], PrimOriginZ[prim]);
589 fprintf(fPrim, "Primitive lengths: %lg\t%lg\n", PrimLX[prim], PrimLZ[prim]);
590 fprintf(fPrim, "#DirnCosn: \n");
591 fprintf(fPrim, "%lg, %lg, %lg\n", PrimDirnCosn.XUnit.X,
592 PrimDirnCosn.XUnit.Y, PrimDirnCosn.XUnit.Z);
593 fprintf(fPrim, "%lg, %lg, %lg\n", PrimDirnCosn.YUnit.X,
594 PrimDirnCosn.YUnit.Y, PrimDirnCosn.YUnit.Z);
595 fprintf(fPrim, "%lg, %lg, %lg\n", PrimDirnCosn.ZUnit.X,
596 PrimDirnCosn.ZUnit.Y, PrimDirnCosn.ZUnit.Z);
597 fprintf(fPrim, "#volref1: %d, volref2: %d\n", volref1, volref2);
598 fprintf(fPrim, "#NbSegs: %d\n", NbSegs);
599 fprintf(fPrim, "#ParentObj: %d\tEType: %d\n", WireParentObj, WireEType);
600 fprintf(fPrim, "#WireR: %lg\tWireL: %lg\n", WireR, WireL);
601 fprintf(fPrim, "#SurfLambda: %lg\tSurfV: %lg\n", WireLambda, WireV);
602 }
603
604 // necessary for gnuplot
606 char gpPrim[256];
607 strcpy(gpPrim, MeshOutDir);
608 strcat(gpPrim, "/GViewDir/gpPrim");
609 strcat(gpPrim, primstr);
610 strcat(gpPrim, ".out");
611 fgpPrim = fopen(gpPrim, "w");
612 if (fgpPrim == NULL) {
613 neBEMMessage("DiscretizeWire - OutgpPrim");
614 fclose(fPrim);
615 return -1;
616 }
617 fprintf(fgpPrim, "%g\t%g\t%g\n\n", xvert[0], yvert[0], zvert[0]);
618 fprintf(fgpPrim, "%g\t%g\t%g\n\n", xvert[1], yvert[1], zvert[1]);
619 fclose(fgpPrim);
620
621 if (prim == 1)
622 fprintf(fgnuPrim, " '%s\' w l", gpPrim);
623 else
624 fprintf(fgnuPrim, ", \\\n \'%s\' w l", gpPrim);
625 }
626
627 // file outputs for elements on primitive
628 if (OptElementFiles) {
629 char OutElem[256];
630 strcpy(OutElem, MeshOutDir);
631 strcat(OutElem, "/Elements/ElemOnPrim");
632 strcat(OutElem, primstr);
633 strcat(OutElem, ".out");
634 fElem = fopen(OutElem, "w");
635 if (fElem == NULL) {
636 neBEMMessage("DiscretizeWire - OutElem");
637 return -1;
638 }
639 }
640 // gnuplot friendly file outputs for elements on primitive
642 strcpy(gpElem, MeshOutDir);
643 strcat(gpElem, "/GViewDir/gpElemOnPrim");
644 strcat(gpElem, primstr);
645 strcat(gpElem, ".out");
646 fgpElem = fopen(gpElem, "w");
647 if (fgpElem == NULL) {
648 neBEMMessage("DiscretizeWire - OutgpElem");
649 if (fElem) fclose(fElem);
650 return -1;
651 }
652 }
653
654 double xincr = (xvert[1] - xvert[0]) / (double)NbSegs;
655 double yincr = (yvert[1] - yvert[0]) / (double)NbSegs;
656 double zincr = (zvert[1] - zvert[0]) / (double)NbSegs;
657
658 ElementBgn[prim] = EleCntr + 1;
659 double xv0, yv0, zv0, xv1, yv1, zv1;
660 for (int seg = 1; seg <= NbSegs; ++seg) {
661 xv0 = xvert[0] + ((double)seg - 1.0) * xincr;
662 yv0 = yvert[0] + ((double)seg - 1.0) * yincr;
663 zv0 = zvert[0] + ((double)seg - 1.0) * zincr;
664 xv1 = xvert[0] + ((double)seg) * xincr;
665 yv1 = yvert[0] + ((double)seg) * yincr;
666 zv1 = zvert[0] + ((double)seg) * zincr;
667 WireElX = xvert[0] + ((double)seg - 1.0) * xincr + 0.5 * xincr;
668 WireElY = yvert[0] + ((double)seg - 1.0) * yincr + 0.5 * yincr;
669 WireElZ = zvert[0] + ((double)seg - 1.0) * zincr + 0.5 * zincr;
670
671 // Assign element values and write in the file
672 // If element counter exceeds the maximum allowed number of elements, warn!
673 ++EleCntr;
674 if (EleCntr > NbElements) {
675 neBEMMessage("DiscretizeWire - EleCntr more than NbElements!");
676 if (fgpElem) fclose(fgpElem);
677 if (fElem) fclose(fElem);
678 return -1;
679 }
680
681 (EleArr + EleCntr - 1)->DeviceNb =
682 1; // At present, there is only one device
683 (EleArr + EleCntr - 1)->ComponentNb = WireParentObj;
684 (EleArr + EleCntr - 1)->PrimitiveNb = prim;
685 (EleArr + EleCntr - 1)->Id = EleCntr;
686 (EleArr + EleCntr - 1)->G.Type = 2; // linear (wire) here
687 (EleArr + EleCntr - 1)->G.Origin.X = WireElX;
688 (EleArr + EleCntr - 1)->G.Origin.Y = WireElY;
689 (EleArr + EleCntr - 1)->G.Origin.Z = WireElZ;
690 (EleArr + EleCntr - 1)->G.Vertex[0].X = xv0;
691 (EleArr + EleCntr - 1)->G.Vertex[0].Y = yv0;
692 (EleArr + EleCntr - 1)->G.Vertex[0].Z = zv0;
693 (EleArr + EleCntr - 1)->G.Vertex[1].X = xv1;
694 (EleArr + EleCntr - 1)->G.Vertex[1].Y = yv1;
695 (EleArr + EleCntr - 1)->G.Vertex[1].Z = zv1;
696 (EleArr + EleCntr - 1)->G.LX = WireR; // radius of the wire element
697 (EleArr + EleCntr - 1)->G.LZ = WireElL; // wire element length
698 (EleArr + EleCntr - 1)->G.dA = 2.0 * MyPI * (EleArr + EleCntr - 1)->G.LX *
699 (EleArr + EleCntr - 1)->G.LZ;
700 (EleArr + EleCntr - 1)->G.DC.XUnit.X = PrimDirnCosn.XUnit.X;
701 (EleArr + EleCntr - 1)->G.DC.XUnit.Y = PrimDirnCosn.XUnit.Y;
702 (EleArr + EleCntr - 1)->G.DC.XUnit.Z = PrimDirnCosn.XUnit.Z;
703 (EleArr + EleCntr - 1)->G.DC.YUnit.X = PrimDirnCosn.YUnit.X;
704 (EleArr + EleCntr - 1)->G.DC.YUnit.Y = PrimDirnCosn.YUnit.Y;
705 (EleArr + EleCntr - 1)->G.DC.YUnit.Z = PrimDirnCosn.YUnit.Z;
706 (EleArr + EleCntr - 1)->G.DC.ZUnit.X = PrimDirnCosn.ZUnit.X;
707 (EleArr + EleCntr - 1)->G.DC.ZUnit.Y = PrimDirnCosn.ZUnit.Y;
708 (EleArr + EleCntr - 1)->G.DC.ZUnit.Z = PrimDirnCosn.ZUnit.Z;
709 (EleArr + EleCntr - 1)->E.Type = WireEType;
710 (EleArr + EleCntr - 1)->E.Lambda = WireLambda;
711 (EleArr + EleCntr - 1)->Solution = 0.0;
712 (EleArr + EleCntr - 1)->Assigned = charge;
713 (EleArr + EleCntr - 1)->BC.NbOfBCs = 1; // assume one BC per element
714 (EleArr + EleCntr - 1)->BC.CollPt.X =
715 (EleArr + EleCntr - 1)->G.Origin.X; // modify
716 (EleArr + EleCntr - 1)->BC.CollPt.Y =
717 (EleArr + EleCntr - 1)->G.Origin.Y; // to be on
718 (EleArr + EleCntr - 1)->BC.CollPt.Z =
719 (EleArr + EleCntr - 1)->G.Origin.Z; // surface?
720
721 // File operations begin
722 // rfw = fwrite(&Ele, sizeof(Element), 1, fpEle);
723 // printf("Return of fwrite is %d\n", rfw);
724
725 if (OptElementFiles) {
726 fprintf(fElem, "##Element Counter: %d\n", EleCntr);
727 fprintf(fElem, "#DevNb\tCompNb\tPrimNb\tId\n");
728 fprintf(fElem, "%d\t%d\t%d\t%d\n", (EleArr + EleCntr - 1)->DeviceNb,
729 (EleArr + EleCntr - 1)->ComponentNb,
730 (EleArr + EleCntr - 1)->PrimitiveNb, (EleArr + EleCntr - 1)->Id);
731 fprintf(fElem, "#GType\tX\tY\tZ\tLX\tLZ\tdA\n");
732 fprintf(fElem, "%d\t%.16lg\t%.16lg\t%.16lg\t%.16lg\t%.16lg\t%.16lg\n",
733 (EleArr + EleCntr - 1)->G.Type,
734 (EleArr + EleCntr - 1)->G.Origin.X,
735 (EleArr + EleCntr - 1)->G.Origin.Y,
736 (EleArr + EleCntr - 1)->G.Origin.Z, (EleArr + EleCntr - 1)->G.LX,
737 (EleArr + EleCntr - 1)->G.LZ, (EleArr + EleCntr - 1)->G.dA);
738 fprintf(fElem, "#DirnCosn: \n");
739 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.XUnit.X,
740 (EleArr + EleCntr - 1)->G.DC.XUnit.Y,
741 (EleArr + EleCntr - 1)->G.DC.XUnit.Z);
742 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.YUnit.X,
743 (EleArr + EleCntr - 1)->G.DC.YUnit.Y,
744 (EleArr + EleCntr - 1)->G.DC.YUnit.Z);
745 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.ZUnit.X,
746 (EleArr + EleCntr - 1)->G.DC.ZUnit.Y,
747 (EleArr + EleCntr - 1)->G.DC.ZUnit.Z);
748 fprintf(fElem, "#EType\tLambda\n");
749 fprintf(fElem, "%d\t%lg\n", (EleArr + EleCntr - 1)->E.Type,
750 (EleArr + EleCntr - 1)->E.Lambda);
751 fprintf(fElem, "#NbBCs\tCPX\tCPY\tCPZ\tValue\n");
752 fprintf(fElem, "%d\t%.16lg\t%.16lg\t%.16lg\t%lg\n",
753 (EleArr + EleCntr - 1)->BC.NbOfBCs,
754 (EleArr + EleCntr - 1)->BC.CollPt.X,
755 (EleArr + EleCntr - 1)->BC.CollPt.Y,
756 (EleArr + EleCntr - 1)->BC.CollPt.Z,
757 (EleArr + EleCntr - 1)->BC.Value);
758 } // if OptElementFiles
759 //
760 // mark centroid
762 fprintf(fgpElem, "%g\t%g\t%g\n", (EleArr + EleCntr - 1)->BC.CollPt.X,
763 (EleArr + EleCntr - 1)->BC.CollPt.Y,
764 (EleArr + EleCntr - 1)->BC.CollPt.Z);
765 } // if OptElementFiles
766 // File operations end
767 } // seg loop for wire elements
768 ElementEnd[prim] = EleCntr;
769 NbElmntsOnPrim[prim] = ElementEnd[prim] - ElementBgn[prim] + 1;
770
771 if (OptPrimitiveFiles) {
772 fprintf(fPrim, "Element begin: %d, Element end: %d\n", ElementBgn[prim],
773 ElementEnd[prim]);
774 fprintf(fPrim, "Number of elements on primitive: %d\n",
775 NbElmntsOnPrim[prim]);
776 fclose(fPrim);
777 }
778
779 if (OptElementFiles) fclose(fElem);
780 if (OptGnuplot && OptGnuplotElements) fclose(fgpElem);
781
782 return (0);
783} // end of DiscretizeWire
784
785// NbSegX is considered to be the number of rectangular + one triangular
786// elements into which the base of the triangular primitive is divided.
787// NbSegZ is the total number of elements into which the height is divided.
788int DiscretizeTriangle(int prim, int nvertex, double xvert[], double yvert[],
789 double zvert[], double xnorm, double ynorm, double znorm,
790 int volref1, int volref2, int inttype, double potential,
791 double charge, double lambda, int NbSegX, int NbSegZ) {
792 int SurfParentObj, SurfEType;
793 double SurfX, SurfY, SurfZ, SurfLX, SurfLZ;
794 double SurfElX, SurfElY, SurfElZ, SurfElLX, SurfElLZ;
795 DirnCosn3D PrimDirnCosn; // direction cosine of the current primitive
796
797 char gpElem[256], gpMesh[256];
798 FILE *fPrim, *fElem, *fgpPrim, *fgpElem, *fgpMesh;
799
800 // Check inputs
801 if ((NbSegX <= 0) || (NbSegZ <= 0)) {
802 printf("segmentation input wrong in DiscretizeTriangle ...\n");
803 return -1;
804 }
805
807 printf("nvertex: %d\n", nvertex);
808 for (int vert = 0; vert < nvertex; ++vert) {
809 printf("vert: %d, x: %lg, y: %lg, z: %lg\n", vert, xvert[vert],
810 yvert[vert], zvert[vert]);
811 }
812 printf("Normal: %lg, %lg, %lg\n", xnorm, ynorm, znorm);
813 } // if OptPrintVertexAndNormal
814
815 // necessary for separating filenames
816 char primstr[10];
817 snprintf(primstr, 10, "%d", prim);
818
819 // in order to avoid warning messages
820 fPrim = NULL;
821 fElem = NULL;
822 fgpMesh = NULL;
823 fgpElem = NULL;
824
825 // Compute all the properties of this surface
826 // Boundary types from 1 to 7 have been defined
827 SurfParentObj = 1;
828 SurfEType = inttype;
829 if ((SurfEType <= 0) || (SurfEType >= 8)) {
830 printf("Wrong SurfEType for prim %d\n", prim);
831 exit(-1);
832 }
833 // Origin of the local coordinate center is at the right angle corner
834 SurfX = xvert[1];
835 SurfY = yvert[1];
836 SurfZ = zvert[1];
837
838 // Find the proper direction cosines first - little more tricky that in the
839 // rectangular case
840 int flagDC = 0; // DC has not been ascertained as yet
841 // We begin with trial 1: one of the possible orientations
842 // Intially, the lengths are necessary
843 // lengths of the sides - note that right angle corner is [1]-th element
844 SurfLX = sqrt((xvert[0] - xvert[1]) * (xvert[0] - xvert[1]) +
845 (yvert[0] - yvert[1]) * (yvert[0] - yvert[1]) +
846 (zvert[0] - zvert[1]) * (zvert[0] - zvert[1]));
847 SurfLZ = sqrt((xvert[2] - xvert[1]) * (xvert[2] - xvert[1]) +
848 (yvert[2] - yvert[1]) * (yvert[2] - yvert[1]) +
849 (zvert[2] - zvert[1]) * (zvert[2] - zvert[1]));
850 // Direction cosines - note that right angle corner is [1]-th element
851 PrimDirnCosn.XUnit.X = (xvert[0] - xvert[1]) / SurfLX;
852 PrimDirnCosn.XUnit.Y = (yvert[0] - yvert[1]) / SurfLX;
853 PrimDirnCosn.XUnit.Z = (zvert[0] - zvert[1]) / SurfLX;
854 PrimDirnCosn.ZUnit.X = (xvert[2] - xvert[1]) / SurfLZ;
855 PrimDirnCosn.ZUnit.Y = (yvert[2] - yvert[1]) / SurfLZ;
856 PrimDirnCosn.ZUnit.Z = (zvert[2] - zvert[1]) / SurfLZ;
857 PrimDirnCosn.YUnit =
858 Vector3DCrossProduct(&PrimDirnCosn.ZUnit, &PrimDirnCosn.XUnit);
859 if ((fabs(PrimDirnCosn.YUnit.X - xnorm) <= 1.0e-3) &&
860 (fabs(PrimDirnCosn.YUnit.Y - ynorm) <= 1.0e-3) &&
861 (fabs(PrimDirnCosn.YUnit.Z - znorm) <= 1.0e-3))
862 flagDC = 1;
863 if (DebugLevel == 202) {
864 printf("First attempt: \n");
865 PrintDirnCosn3D(PrimDirnCosn);
866 printf("\n");
867 }
868
869 if (!flagDC) // if DC search is unsuccessful, try the other orientation
870 {
871 SurfLX = sqrt((xvert[2] - xvert[1]) * (xvert[2] - xvert[1]) +
872 (yvert[2] - yvert[1]) * (yvert[2] - yvert[1]) +
873 (zvert[2] - zvert[1]) * (zvert[2] - zvert[1]));
874 SurfLZ = sqrt((xvert[0] - xvert[1]) * (xvert[0] - xvert[1]) +
875 (yvert[0] - yvert[1]) * (yvert[0] - yvert[1]) +
876 (zvert[0] - zvert[1]) * (zvert[0] - zvert[1]));
877 // Direction cosines - note that right angle corner is [1]-th element
878 PrimDirnCosn.XUnit.X = (xvert[2] - xvert[1]) / SurfLX;
879 PrimDirnCosn.XUnit.Y = (yvert[2] - yvert[1]) / SurfLX;
880 PrimDirnCosn.XUnit.Z = (zvert[2] - zvert[1]) / SurfLX;
881 PrimDirnCosn.ZUnit.X = (xvert[0] - xvert[1]) / SurfLZ;
882 PrimDirnCosn.ZUnit.Y = (yvert[0] - yvert[1]) / SurfLZ;
883 PrimDirnCosn.ZUnit.Z = (zvert[0] - zvert[1]) / SurfLZ;
884 PrimDirnCosn.YUnit =
885 Vector3DCrossProduct(&PrimDirnCosn.ZUnit, &PrimDirnCosn.XUnit);
886 if ((fabs(PrimDirnCosn.YUnit.X - xnorm) <= 1.0e-3) &&
887 (fabs(PrimDirnCosn.YUnit.Y - ynorm) <= 1.0e-3) &&
888 (fabs(PrimDirnCosn.YUnit.Z - znorm) <= 1.0e-3))
889 flagDC = 2;
890 if (DebugLevel == 202) {
891 printf("Second attempt: \n");
892 PrintDirnCosn3D(PrimDirnCosn);
893 printf("\n");
894 }
895 }
896
897 if (!flagDC) // No other possibility, DC search failed!!!
898 {
899 printf("Triangle DC problem ... returning ...\n");
900 // getchar();
901 return -1;
902 }
903
904 // primitive direction cosine assignments
905 PrimDC[prim].XUnit.X = PrimDirnCosn.XUnit.X;
906 PrimDC[prim].XUnit.Y = PrimDirnCosn.XUnit.Y;
907 PrimDC[prim].XUnit.Z = PrimDirnCosn.XUnit.Z;
908 PrimDC[prim].YUnit.X = PrimDirnCosn.YUnit.X;
909 PrimDC[prim].YUnit.Y = PrimDirnCosn.YUnit.Y;
910 PrimDC[prim].YUnit.Z = PrimDirnCosn.YUnit.Z;
911 PrimDC[prim].ZUnit.X = PrimDirnCosn.ZUnit.X;
912 PrimDC[prim].ZUnit.Y = PrimDirnCosn.ZUnit.Y;
913 PrimDC[prim].ZUnit.Z = PrimDirnCosn.ZUnit.Z;
914
915 // primitive origin - for a triangle, origin is at the right corner
916 PrimOriginX[prim] = SurfX;
917 PrimOriginY[prim] = SurfY;
918 PrimOriginZ[prim] = SurfZ;
919 PrimLX[prim] = SurfLX;
920 PrimLZ[prim] = SurfLZ;
921 if (flagDC == 1) {
922 int tmpVolRef1 = VolRef1[prim];
923 VolRef1[prim] = VolRef2[prim];
924 VolRef2[prim] = tmpVolRef1;
925 int tmpEpsilon1 = Epsilon1[prim];
926 Epsilon1[prim] = Epsilon2[prim];
927 Epsilon2[prim] = tmpEpsilon1;
928 }
929
930 double SurfLambda = lambda;
931 double SurfV = potential;
932
933 // file output for a primitive
934 if (OptPrimitiveFiles) {
935 char OutPrim[256];
936 strcpy(OutPrim, ModelOutDir);
937 strcat(OutPrim, "/Primitives/Primitive");
938 strcat(OutPrim, primstr);
939 strcat(OutPrim, ".out");
940 fPrim = fopen(OutPrim, "w");
941 if (fPrim == NULL) {
942 neBEMMessage("DiscretizeTriangle - OutPrim");
943 return -1;
944 }
945 fprintf(fPrim, "#prim: %d, nvertex: %d\n", prim, nvertex);
946 fprintf(fPrim, "Node1: %lg\t%lg\t%lg\n", xvert[0], yvert[0], zvert[0]);
947 fprintf(fPrim, "Node2: %lg\t%lg\t%lg\n", xvert[1], yvert[1], zvert[1]);
948 fprintf(fPrim, "Node3: %lg\t%lg\t%lg\n", xvert[2], yvert[2], zvert[2]);
949 fprintf(fPrim, "PrimOrigin: %lg\t%lg\t%lg\n", PrimOriginX[prim],
950 PrimOriginY[prim], PrimOriginZ[prim]);
951 fprintf(fPrim, "Primitive lengths: %lg\t%lg\n", PrimLX[prim], PrimLZ[prim]);
952 fprintf(fPrim, "Norm: %lg\t%lg\t%lg\n", xnorm, ynorm, znorm);
953 fprintf(fPrim, "#volref1: %d, volref2: %d\n", volref1, volref2);
954 fprintf(fPrim, "#NbSegX: %d, NbSegZ: %d (check note!)\n", NbSegX, NbSegZ);
955 fprintf(fPrim, "#ParentObj: %d\tEType: %d\n", SurfParentObj, SurfEType);
956 fprintf(fPrim, "#SurfX\tSurfY\tSurfZ\tSurfLX\tSurfLZ (Rt. Corner)\n");
957 fprintf(fPrim, "%lg\t%lg\t%lg\t%lg\t%lg\n", SurfX, SurfY, SurfZ, SurfLX,
958 SurfLZ);
959 fprintf(fPrim, "#DirnCosn: \n");
960 fprintf(fPrim, "%lg, %lg, %lg\n", PrimDirnCosn.XUnit.X,
961 PrimDirnCosn.XUnit.Y, PrimDirnCosn.XUnit.Z);
962 fprintf(fPrim, "%lg, %lg, %lg\n", PrimDirnCosn.YUnit.X,
963 PrimDirnCosn.YUnit.Y, PrimDirnCosn.YUnit.Z);
964 fprintf(fPrim, "%lg, %lg, %lg\n", PrimDirnCosn.ZUnit.X,
965 PrimDirnCosn.ZUnit.Y, PrimDirnCosn.ZUnit.Z);
966 fprintf(fPrim, "#SurfLambda: %lg\tSurfV: %lg\n", SurfLambda, SurfV);
967 }
968
969 // necessary for gnuplot
971 char gpPrim[256];
972 strcpy(gpPrim, MeshOutDir);
973 strcat(gpPrim, "/GViewDir/gpPrim");
974 strcat(gpPrim, primstr);
975 strcat(gpPrim, ".out");
976 fgpPrim = fopen(gpPrim, "w");
977 if (fgpPrim == NULL) {
978 neBEMMessage("DiscretizeTriangle - OutgpPrim");
979 fclose(fPrim);
980 return -1;
981 }
982 fprintf(fgpPrim, "%g\t%g\t%g\n\n", xvert[0], yvert[0], zvert[0]);
983 fprintf(fgpPrim, "%g\t%g\t%g\n\n", xvert[1], yvert[1], zvert[1]);
984 fprintf(fgpPrim, "%g\t%g\t%g\n\n", xvert[2], yvert[2], zvert[2]);
985 fprintf(fgpPrim, "%g\t%g\t%g\n", xvert[0], yvert[0], zvert[0]);
986 fclose(fgpPrim);
987
988 if (prim == 1)
989 fprintf(fgnuPrim, " '%s\' w l", gpPrim);
990 else
991 fprintf(fgnuPrim, ", \\\n \'%s\' w l", gpPrim);
992 }
993
994 // file outputs for elements on primitive
995 if (OptElementFiles) {
996 char OutElem[256];
997 strcpy(OutElem, MeshOutDir);
998 strcat(OutElem, "/Elements/ElemOnPrim");
999 strcat(OutElem, primstr);
1000 strcat(OutElem, ".out");
1001 fElem = fopen(OutElem, "w");
1002 if (fElem == NULL) {
1003 neBEMMessage("DiscretizeTriangle - OutElem");
1004 return -1;
1005 }
1006 }
1007 // gnuplot friendly file outputs for elements on primitive
1009 strcpy(gpElem, MeshOutDir);
1010 strcat(gpElem, "/GViewDir/gpElemOnPrim");
1011 strcat(gpElem, primstr);
1012 strcat(gpElem, ".out");
1013 fgpElem = fopen(gpElem, "w");
1014 // assert(fgpElem != NULL);
1015 if (fgpElem == NULL) {
1016 neBEMMessage("DiscretizeTriangle - OutgpElem");
1017 if (fElem) fclose(fElem);
1018 return -1;
1019 }
1020 // gnuplot friendly file outputs for elements on primitive
1021 strcpy(gpMesh, MeshOutDir);
1022 strcat(gpMesh, "/GViewDir/gpMeshOnPrim");
1023 strcat(gpMesh, primstr);
1024 strcat(gpMesh, ".out");
1025 fgpMesh = fopen(gpMesh, "w");
1026 if (fgpMesh == NULL) {
1027 neBEMMessage("DiscretizeTriangle - OutgpMesh");
1028 fclose(fgpElem);
1029 if (fElem) fclose(fElem);
1030 return -1;
1031 }
1032 }
1033
1034 // Compute element positions (CGs) in primitive local coordinate system (PCS).
1035 // Then map these CGs to the global coordinate system.
1036 // (xav, 0, zav) is the CG of an element wrt the primitive coordinate system
1037 // From this, we find the offset of the element from the primitive CG in the
1038 // global coordinate system by just rotating the displacement vector
1039 // (0,0,0) -> (xav,0,zav) using the known DCM of the surface.
1040 // This rotated vector (now in the global system) is then added to the
1041 // position vector of the primitive CG (always in the global system) to get
1042 // the CG of the element in the global system.
1043
1044 // Consult note for clarifications on the discretization algorithm.
1045 // SurfElLX is true for the lowest row of elements, but indicative of the
1046 // other rows
1047 // Make sure that the larger number is being used to discretize the longer
1048 // side - can be OverSmart in certain cases - there may be cases where
1049 // smaller number of elements suffice for a longer side
1050 if (NbSegX == NbSegZ) {
1051 SurfElLX = SurfLX / NbSegX; // element sizes
1052 SurfElLZ = SurfLZ / NbSegZ;
1053 } else if (NbSegX > NbSegZ) {
1054 if (SurfLX > SurfLZ) {
1055 SurfElLX = SurfLX / NbSegX; // element sizes
1056 SurfElLZ = SurfLZ / NbSegZ;
1057 } else // interchange NbSegX and NbSegZ
1058 {
1059 int tmp = NbSegZ;
1060 NbSegZ = NbSegX;
1061 NbSegX = tmp;
1062 SurfElLX = SurfLX / NbSegX; // element sizes
1063 SurfElLZ = SurfLZ / NbSegZ;
1064 }
1065 } // NbSegX > NbSegZ
1066 else // NbSegX < NbSegZ
1067 {
1068 if (SurfLX < SurfLZ) {
1069 SurfElLX = SurfLX / NbSegX; // element sizes
1070 SurfElLZ = SurfLZ / NbSegZ;
1071 } else // interchange NbSegX and NbSegZ
1072 {
1073 int tmp = NbSegZ;
1074 NbSegZ = NbSegX;
1075 NbSegX = tmp;
1076 SurfElLX = SurfLX / NbSegX; // element sizes
1077 SurfElLZ = SurfLZ / NbSegZ;
1078 }
1079 }
1080
1081 // Analysis of element aspect ratio.
1082 // Note that we can afford only to reduce the total number of elements.
1083 // Otherwise, we'll have to realloc `EleArr' array.
1084 // Later, we'll make the corrections such that the total number of elements
1085 // remain close to the originally intended value.
1086 double AR = SurfElLX / SurfElLZ; // indicative element aspect ratio
1087 if (OptPrimitiveFiles) {
1088 fprintf(fPrim,
1089 "Using the input, the aspect ratio of the elements on prim: %d\n",
1090 prim);
1091 fprintf(fPrim,
1092 "NbSegX: %d, SurfElLX: %lg, NbSegZ: %d, SurfElLZ: %lg, AR: %lg\n",
1093 NbSegX, SurfElLX, NbSegZ, SurfElLZ, AR);
1094 }
1095 if (AR > 10.0) // NbSegZ needs to be reduced
1096 {
1097 double tmpElLZ = SurfElLX / 10.0;
1098 NbSegZ = (int)(SurfLZ / tmpElLZ);
1099 if (NbSegZ <= 0) NbSegZ = 1;
1100 SurfElLZ = SurfLZ / NbSegZ;
1101 }
1102 if (AR < 0.1) // NbSegX need to be reduced
1103 {
1104 double tmpElLX = SurfElLZ * 0.1;
1105 NbSegX = (int)(SurfLX / tmpElLX);
1106 if (NbSegX <= 0) NbSegX = 1;
1107 SurfElLX = SurfLX / NbSegX;
1108 }
1109 AR = SurfElLX / SurfElLZ; // indicative element aspect ratio
1110 if (OptPrimitiveFiles) {
1111 fprintf(fPrim, "After analyzing the likely aspect ratio of the elements\n");
1112 fprintf(fPrim,
1113 "NbSegX: %d, SurfElLX: %lg, NbSegZ: %d, SurfElLZ: %lg, AR: %lg\n",
1114 NbSegX, SurfElLX, NbSegZ, SurfElLZ, AR);
1115 }
1116
1117 // The top-most right angle triangle is a lone element on the highest row, its
1118 // properties being determined irrespective of the others. Despite that, this
1119 // element is being treated as one among the others, especially to facilitate
1120 // element indexing, file output etc.
1121 // Each row, thus, has at least one triangle, and possibly several rectangular
1122 // elements. All the elements in any given row has the same SurfElLZ as has
1123 // been determined above.
1124 // First we create the triangular element and then move on to create the
1125 // rectangular ones.
1126 double xv0, yv0, zv0, xv1, yv1, zv1, xv2, yv2, zv2;
1127 ElementBgn[prim] = EleCntr + 1;
1128 for (int k = 1; k <= NbSegZ; ++k) // consider the k-th row
1129 {
1130 double grad = (SurfLZ / SurfLX);
1131 double zlopt = (k - 1) * SurfElLZ;
1132 double zhipt = (k)*SurfElLZ;
1133 double xlopt = (SurfLZ - zlopt) / grad; // used again on 21 Feb 2014
1134 double xhipt = (SurfLZ - zhipt) / grad;
1135
1136 // the triangular element on the k-th row can now be specified in PCS
1137 double xtorigin = xhipt;
1138 double ytorigin = 0.0;
1139 double ztorigin = zlopt;
1140 { // Separate block for position rotation - local2global
1141 Point3D localDisp, globalDisp;
1142
1143 localDisp.X = xtorigin;
1144 localDisp.Y = ytorigin;
1145 localDisp.Z = ztorigin;
1146 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1147 SurfElX =
1148 SurfX + globalDisp.X; // these are the coords in GCS of origin of
1149 SurfElY =
1150 SurfY + globalDisp.Y; // the triangluar element under consideration
1151 SurfElZ = SurfZ + globalDisp.Z;
1152 } // vector rotation over
1153
1154 // Assign element values and write in the file
1155 ++EleCntr;
1156 if (EleCntr > NbElements) {
1157 neBEMMessage("DiscretizeTriangle - EleCntr more than NbElements 1!");
1158 if (fgpElem) fclose(fgpElem);
1159 if (fgpMesh) fclose(fgpMesh);
1160 return -1;
1161 }
1162
1163 (EleArr + EleCntr - 1)->DeviceNb =
1164 1; // At present, there is only one device
1165 (EleArr + EleCntr - 1)->ComponentNb = SurfParentObj;
1166 (EleArr + EleCntr - 1)->PrimitiveNb = prim;
1167 (EleArr + EleCntr - 1)->Id = EleCntr;
1168 (EleArr + EleCntr - 1)->G.Type = 3; // triangular here
1169 (EleArr + EleCntr - 1)->G.Origin.X = SurfElX;
1170 (EleArr + EleCntr - 1)->G.Origin.Y = SurfElY;
1171 (EleArr + EleCntr - 1)->G.Origin.Z = SurfElZ;
1172 // (EleArr+EleCntr-1)->G.LX = SurfElLX; // previously written as xlopt -
1173 // xhipt;
1174 (EleArr + EleCntr - 1)->G.LX =
1175 xlopt - xhipt; // back to old ways on 21 Feb 2014
1176 (EleArr + EleCntr - 1)->G.LZ = SurfElLZ;
1177 (EleArr + EleCntr - 1)->G.LZ =
1178 zhipt - zlopt; // to be on the safe side, 21/2/14
1179 (EleArr + EleCntr - 1)->G.dA =
1180 0.5 * (EleArr + EleCntr - 1)->G.LX * (EleArr + EleCntr - 1)->G.LZ;
1181 // Safe to use the direction cosines obtained for the triangular primitive
1182 // since they are bound to remain unchanged for the rectangular sub-elements
1183 (EleArr + EleCntr - 1)->G.DC.XUnit.X = PrimDirnCosn.XUnit.X;
1184 (EleArr + EleCntr - 1)->G.DC.XUnit.Y = PrimDirnCosn.XUnit.Y;
1185 (EleArr + EleCntr - 1)->G.DC.XUnit.Z = PrimDirnCosn.XUnit.Z;
1186 (EleArr + EleCntr - 1)->G.DC.YUnit.X = PrimDirnCosn.YUnit.X;
1187 (EleArr + EleCntr - 1)->G.DC.YUnit.Y = PrimDirnCosn.YUnit.Y;
1188 (EleArr + EleCntr - 1)->G.DC.YUnit.Z = PrimDirnCosn.YUnit.Z;
1189 (EleArr + EleCntr - 1)->G.DC.ZUnit.X = PrimDirnCosn.ZUnit.X;
1190 (EleArr + EleCntr - 1)->G.DC.ZUnit.Y = PrimDirnCosn.ZUnit.Y;
1191 (EleArr + EleCntr - 1)->G.DC.ZUnit.Z = PrimDirnCosn.ZUnit.Z;
1192 (EleArr + EleCntr - 1)->E.Type = SurfEType;
1193 (EleArr + EleCntr - 1)->E.Lambda = SurfLambda;
1194 (EleArr + EleCntr - 1)->Solution = 0.0;
1195 (EleArr + EleCntr - 1)->Assigned = charge;
1196 // Boundary condition is applied at the barycenter, not at the origin
1197 // of the element coordinate system (ECS) which is at the right corner
1198 (EleArr + EleCntr - 1)->BC.NbOfBCs = 1; // assume one BC per element
1199
1200 xv0 = (EleArr + EleCntr - 1)->G.Origin.X;
1201 yv0 = (EleArr + EleCntr - 1)->G.Origin.Y;
1202 zv0 = (EleArr + EleCntr - 1)->G.Origin.Z;
1203 xv1 = (EleArr + EleCntr - 1)->G.Origin.X +
1204 (EleArr + EleCntr - 1)->G.LX * (EleArr + EleCntr - 1)->G.DC.XUnit.X;
1205 yv1 = (EleArr + EleCntr - 1)->G.Origin.Y +
1206 (EleArr + EleCntr - 1)->G.LX * (EleArr + EleCntr - 1)->G.DC.XUnit.Y;
1207 zv1 = (EleArr + EleCntr - 1)->G.Origin.Z +
1208 (EleArr + EleCntr - 1)->G.LX * (EleArr + EleCntr - 1)->G.DC.XUnit.Z;
1209 xv2 = (EleArr + EleCntr - 1)->G.Origin.X +
1210 (EleArr + EleCntr - 1)->G.LZ * (EleArr + EleCntr - 1)->G.DC.ZUnit.X;
1211 yv2 = (EleArr + EleCntr - 1)->G.Origin.Y +
1212 (EleArr + EleCntr - 1)->G.LZ * (EleArr + EleCntr - 1)->G.DC.ZUnit.Y;
1213 zv2 = (EleArr + EleCntr - 1)->G.Origin.Z +
1214 (EleArr + EleCntr - 1)->G.LZ * (EleArr + EleCntr - 1)->G.DC.ZUnit.Z;
1215 // assign vertices of the element
1216 (EleArr + EleCntr - 1)->G.Vertex[0].X = xv0;
1217 (EleArr + EleCntr - 1)->G.Vertex[0].Y = yv0;
1218 (EleArr + EleCntr - 1)->G.Vertex[0].Z = zv0;
1219 (EleArr + EleCntr - 1)->G.Vertex[1].X = xv1;
1220 (EleArr + EleCntr - 1)->G.Vertex[1].Y = yv1;
1221 (EleArr + EleCntr - 1)->G.Vertex[1].Z = zv1;
1222 (EleArr + EleCntr - 1)->G.Vertex[2].X = xv2;
1223 (EleArr + EleCntr - 1)->G.Vertex[2].Y = yv2;
1224 (EleArr + EleCntr - 1)->G.Vertex[2].Z = zv2;
1225 (EleArr + EleCntr - 1)->G.Vertex[3].X = 0.0;
1226 (EleArr + EleCntr - 1)->G.Vertex[3].Y = 0.0;
1227 (EleArr + EleCntr - 1)->G.Vertex[3].Z = 0.0;
1228
1229 if (DebugLevel == 201) {
1230 printf("Primitive nb: %d\n", (EleArr + EleCntr - 1)->PrimitiveNb);
1231 printf("Element id: %d\n", (EleArr + EleCntr - 1)->Id);
1232 printf("Element X, Y, Z: %lg %lg %lg\n",
1233 (EleArr + EleCntr - 1)->G.Origin.X,
1234 (EleArr + EleCntr - 1)->G.Origin.Y,
1235 (EleArr + EleCntr - 1)->G.Origin.Z);
1236 printf("Element LX, LZ: %lg %lg\n", (EleArr + EleCntr - 1)->G.LX,
1237 (EleArr + EleCntr - 1)->G.LZ);
1238 printf("Element (primitive) X axis dirn cosines: %lg, %lg, %lg\n",
1239 PrimDirnCosn.XUnit.X, PrimDirnCosn.XUnit.Y, PrimDirnCosn.XUnit.Z);
1240 printf("Element (primitive) Y axis dirn cosines: %lg, %lg, %lg\n",
1241 PrimDirnCosn.YUnit.X, PrimDirnCosn.YUnit.Y, PrimDirnCosn.YUnit.Z);
1242 printf("Element (primitive) Z axis dirn cosines: %lg, %lg, %lg\n",
1243 PrimDirnCosn.ZUnit.X, PrimDirnCosn.ZUnit.Y, PrimDirnCosn.ZUnit.Z);
1244 }
1245 // Following are the location in the ECS
1246 double dxl = (EleArr + EleCntr - 1)->G.LX / 3.0;
1247 double dyl = 0.0;
1248 double dzl = (EleArr + EleCntr - 1)->G.LZ / 3.0;
1249 { // Separate block for position rotation - local2global
1250 Point3D localDisp, globalDisp;
1251
1252 localDisp.X = dxl;
1253 localDisp.Y = dyl;
1254 localDisp.Z = dzl;
1255 if (DebugLevel == 201) {
1256 printf("Element dxl, dxy, dxz: %lg %lg %lg\n", localDisp.X, localDisp.Y,
1257 localDisp.Z);
1258 }
1259
1260 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1261 (EleArr + EleCntr - 1)->BC.CollPt.X =
1262 (EleArr + EleCntr - 1)->G.Origin.X + globalDisp.X;
1263 (EleArr + EleCntr - 1)->BC.CollPt.Y =
1264 (EleArr + EleCntr - 1)->G.Origin.Y + globalDisp.Y;
1265 (EleArr + EleCntr - 1)->BC.CollPt.Z =
1266 (EleArr + EleCntr - 1)->G.Origin.Z + globalDisp.Z;
1267 if (DebugLevel == 201) {
1268 printf("Element global dxl, dxy, dxz: %lg %lg %lg\n", globalDisp.X,
1269 globalDisp.Y, globalDisp.Z);
1270 printf("Element BCX, BCY, BCZ: %lg %lg %lg\n",
1271 (EleArr + EleCntr - 1)->BC.CollPt.X,
1272 (EleArr + EleCntr - 1)->BC.CollPt.Y,
1273 (EleArr + EleCntr - 1)->BC.CollPt.Z);
1274 }
1275 } // vector rotation over
1276 // (EleArr+EleCntr-1)->BC.Value = SurfV; // assigned in BoundaryConditions
1277
1278 if (OptElementFiles) {
1279 fprintf(fElem, "##Element Counter: %d\n", EleCntr);
1280 fprintf(fElem, "#DevNb\tCompNb\tPrimNb\tId\n");
1281 fprintf(fElem, "%d\t%d\t%d\t%d\n", (EleArr + EleCntr - 1)->DeviceNb,
1282 (EleArr + EleCntr - 1)->ComponentNb,
1283 (EleArr + EleCntr - 1)->PrimitiveNb, (EleArr + EleCntr - 1)->Id);
1284 fprintf(fElem, "#GType\tX\tY\tZ\tLX\tLZ\tdA\n");
1285 fprintf(fElem, "%d\t%.16lg\t%.16lg\t%.16lg\t%.16lg\t%.16lg\t%.16lg\n",
1286 (EleArr + EleCntr - 1)->G.Type,
1287 (EleArr + EleCntr - 1)->G.Origin.X,
1288 (EleArr + EleCntr - 1)->G.Origin.Y,
1289 (EleArr + EleCntr - 1)->G.Origin.Z, (EleArr + EleCntr - 1)->G.LX,
1290 (EleArr + EleCntr - 1)->G.LZ, (EleArr + EleCntr - 1)->G.dA);
1291 fprintf(fElem, "#DirnCosn: \n");
1292 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.XUnit.X,
1293 (EleArr + EleCntr - 1)->G.DC.XUnit.Y,
1294 (EleArr + EleCntr - 1)->G.DC.XUnit.Z);
1295 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.YUnit.X,
1296 (EleArr + EleCntr - 1)->G.DC.YUnit.Y,
1297 (EleArr + EleCntr - 1)->G.DC.YUnit.Z);
1298 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.ZUnit.X,
1299 (EleArr + EleCntr - 1)->G.DC.ZUnit.Y,
1300 (EleArr + EleCntr - 1)->G.DC.ZUnit.Z);
1301 fprintf(fElem, "#EType\tLambda\n");
1302 fprintf(fElem, "%d\t%lg\n", (EleArr + EleCntr - 1)->E.Type,
1303 (EleArr + EleCntr - 1)->E.Lambda);
1304 fprintf(fElem, "#NbBCs\tCPX\tCPY\tCPZ\tValue\n");
1305 fprintf(fElem, "%d\t%.16lg\t%.16lg\t%.16lg\t%lg\n",
1306 (EleArr + EleCntr - 1)->BC.NbOfBCs,
1307 (EleArr + EleCntr - 1)->BC.CollPt.X,
1308 (EleArr + EleCntr - 1)->BC.CollPt.Y,
1309 (EleArr + EleCntr - 1)->BC.CollPt.Z,
1310 (EleArr + EleCntr - 1)->BC.Value);
1311 } // if OptElementFiles
1312
1313 // mark bary-center and draw mesh
1315 fprintf(fgpElem, "%g\t%g\t%g\n", (EleArr + EleCntr - 1)->BC.CollPt.X,
1316 (EleArr + EleCntr - 1)->BC.CollPt.Y,
1317 (EleArr + EleCntr - 1)->BC.CollPt.Z);
1318
1319 // draw mesh
1320 // assign vertices of the element
1321 xv0 = (EleArr + EleCntr - 1)->G.Vertex[0].X;
1322 yv0 = (EleArr + EleCntr - 1)->G.Vertex[0].Y;
1323 zv0 = (EleArr + EleCntr - 1)->G.Vertex[0].Z;
1324 xv1 = (EleArr + EleCntr - 1)->G.Vertex[1].X;
1325 yv1 = (EleArr + EleCntr - 1)->G.Vertex[1].Y;
1326 zv1 = (EleArr + EleCntr - 1)->G.Vertex[1].Z;
1327 xv2 = (EleArr + EleCntr - 1)->G.Vertex[2].X;
1328 yv2 = (EleArr + EleCntr - 1)->G.Vertex[2].Y;
1329 zv2 = (EleArr + EleCntr - 1)->G.Vertex[2].Z;
1330
1331 fprintf(fgpMesh, "%g\t%g\t%g\n", xv0, yv0, zv0);
1332 fprintf(fgpMesh, "%g\t%g\t%g\n", xv1, yv1, zv1);
1333 fprintf(fgpMesh, "%g\t%g\t%g\n", xv2, yv2, zv2);
1334 fprintf(fgpMesh, "%g\t%g\t%g\n\n", xv0, yv0, zv0);
1335 } // if OptGnuplotElements
1336
1337 if (k == NbSegZ) // no rectangular element on this row
1338 continue;
1339
1340 // determine NbSegXOnThisRow and ElLXOnThisRow for the rectagnular elements
1341 // and then loop.
1342 double RowLX = xhipt; // the triangular portion is left outside the slice
1343 int NbSegXOnThisRow;
1344 double ElLXOnThisRow;
1345 if (RowLX <= SurfElLX) {
1346 NbSegXOnThisRow = 1;
1347 ElLXOnThisRow = RowLX;
1348 } else {
1349 NbSegXOnThisRow = (int)(RowLX / SurfElLX);
1350 ElLXOnThisRow = RowLX / NbSegXOnThisRow;
1351 }
1352 double x0, y0, z0, x1, y1, z1, x2, y2, z2, x3, y3, z3;
1353 for (int i = 1; i <= NbSegXOnThisRow; ++i) {
1354 double xorigin = (i - 1) * ElLXOnThisRow + 0.5 * ElLXOnThisRow; // PCS
1355 double yorigin = 0.0; // centroid of the rectagnular element
1356 double zorigin = 0.5 * (zlopt + zhipt);
1357 // printf("k: %d, i: %d, xo: %lg, yo: %lg, zo: %lg\n", k, i,
1358 // xorigin, yorigin, zorigin);
1359 // printf("xlopt: %lg, zlopt: %lg, xhipt: %lg, zhipt: %lg\n",
1360 // xlopt, zlopt, xhipt, zhipt);
1361
1362 { // Separate block for vector rotation
1363 Point3D localDisp, globalDisp;
1364
1365 localDisp.X = xorigin;
1366 localDisp.Y = yorigin;
1367 localDisp.Z = zorigin;
1368 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1369 SurfElX = SurfX + globalDisp.X; // GCS
1370 SurfElY = SurfY + globalDisp.Y;
1371 SurfElZ = SurfZ + globalDisp.Z;
1372 } // vector rotation over
1373 // printf("SurfX: %lg, SurfY: %lg, SurfZ: %lg\n",
1374 // SurfX, SurfY, SurfZ);
1375 // printf("SurfElX: %lg, SurfElY: %lg, SurfElZ: %lg\n",
1376 // SurfElX, SurfElY, SurfElZ);
1377
1378 // Assign element values and write in the file
1379 ++EleCntr;
1380 if (EleCntr > NbElements) {
1381 neBEMMessage("DiscretizeTriangle - EleCntr more than NbElements 2!");
1382 return -1;
1383 }
1384
1385 (EleArr + EleCntr - 1)->DeviceNb =
1386 1; // At present, there is only one device
1387 (EleArr + EleCntr - 1)->ComponentNb = SurfParentObj;
1388 (EleArr + EleCntr - 1)->PrimitiveNb = prim;
1389 (EleArr + EleCntr - 1)->Id = EleCntr;
1390 (EleArr + EleCntr - 1)->G.Type = 4; // rectagnular here
1391 (EleArr + EleCntr - 1)->G.Origin.X = SurfElX;
1392 (EleArr + EleCntr - 1)->G.Origin.Y = SurfElY;
1393 (EleArr + EleCntr - 1)->G.Origin.Z = SurfElZ;
1394 (EleArr + EleCntr - 1)->G.LX = ElLXOnThisRow;
1395 (EleArr + EleCntr - 1)->G.LZ = SurfElLZ;
1396 (EleArr + EleCntr - 1)->G.LZ =
1397 zhipt - zlopt; // to be on the safe side! 21/2/14
1398 (EleArr + EleCntr - 1)->G.dA =
1399 (EleArr + EleCntr - 1)->G.LX * (EleArr + EleCntr - 1)->G.LZ;
1400 // Safe to use the direction cosines obtained for the triangular primitive
1401 // since they are bound to remain unchanged for the triangular
1402 // sub-elements
1403 (EleArr + EleCntr - 1)->G.DC.XUnit.X = PrimDirnCosn.XUnit.X;
1404 (EleArr + EleCntr - 1)->G.DC.XUnit.Y = PrimDirnCosn.XUnit.Y;
1405 (EleArr + EleCntr - 1)->G.DC.XUnit.Z = PrimDirnCosn.XUnit.Z;
1406 (EleArr + EleCntr - 1)->G.DC.YUnit.X = PrimDirnCosn.YUnit.X;
1407 (EleArr + EleCntr - 1)->G.DC.YUnit.Y = PrimDirnCosn.YUnit.Y;
1408 (EleArr + EleCntr - 1)->G.DC.YUnit.Z = PrimDirnCosn.YUnit.Z;
1409 (EleArr + EleCntr - 1)->G.DC.ZUnit.X = PrimDirnCosn.ZUnit.X;
1410 (EleArr + EleCntr - 1)->G.DC.ZUnit.Y = PrimDirnCosn.ZUnit.Y;
1411 (EleArr + EleCntr - 1)->G.DC.ZUnit.Z = PrimDirnCosn.ZUnit.Z;
1412 (EleArr + EleCntr - 1)->E.Type = SurfEType;
1413 (EleArr + EleCntr - 1)->E.Lambda = SurfLambda;
1414 (EleArr + EleCntr - 1)->Solution = 0.0;
1415 (EleArr + EleCntr - 1)->Assigned = charge;
1416 // Boundary condition is applied at the origin for this rectangular
1417 // element coordinate system (ECS)
1418 (EleArr + EleCntr - 1)->BC.NbOfBCs = 1; // assume one BC per element
1419 // Following are the location in the ECS
1420 (EleArr + EleCntr - 1)->BC.CollPt.X = (EleArr + EleCntr - 1)->G.Origin.X;
1421 (EleArr + EleCntr - 1)->BC.CollPt.Y = (EleArr + EleCntr - 1)->G.Origin.Y;
1422 (EleArr + EleCntr - 1)->BC.CollPt.Z = (EleArr + EleCntr - 1)->G.Origin.Z;
1423 // find element vertices
1424 // 1) displacement vector in the ECS is first identified
1425 // 2) this vector is transformed to the GCS
1426 // 3) the global displacement vector, when added to the centroid in GCS,
1427 // gives the node positions in GCS.
1428 x0 = -0.5 *
1429 (EleArr + EleCntr - 1)->G.LX; // xyz displacement of node wrt ECS
1430 y0 = 0.0;
1431 z0 = -0.5 * (EleArr + EleCntr - 1)->G.LZ;
1432 { // Separate block for position rotation - local2global
1433 Point3D localDisp, globalDisp;
1434
1435 localDisp.X = x0;
1436 localDisp.Y = y0;
1437 localDisp.Z = z0; // displacement in GCS
1438 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1439 x0 = (EleArr + EleCntr - 1)->G.Origin.X +
1440 globalDisp.X; // xyz position in GCS
1441 y0 = (EleArr + EleCntr - 1)->G.Origin.Y + globalDisp.Y;
1442 z0 = (EleArr + EleCntr - 1)->G.Origin.Z + globalDisp.Z;
1443 } // position rotation over
1444
1445 x1 = 0.5 * (EleArr + EleCntr - 1)->G.LX;
1446 y1 = 0.0;
1447 z1 = -0.5 * (EleArr + EleCntr - 1)->G.LZ;
1448 { // Separate block for position rotation - local2global
1449 Point3D localDisp, globalDisp;
1450
1451 localDisp.X = x1;
1452 localDisp.Y = y1;
1453 localDisp.Z = z1;
1454 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1455 x1 = (EleArr + EleCntr - 1)->G.Origin.X + globalDisp.X;
1456 y1 = (EleArr + EleCntr - 1)->G.Origin.Y + globalDisp.Y;
1457 z1 = (EleArr + EleCntr - 1)->G.Origin.Z + globalDisp.Z;
1458 } // position rotation over
1459
1460 x2 = 0.5 * (EleArr + EleCntr - 1)->G.LX;
1461 y2 = 0.0;
1462 z2 = 0.5 * (EleArr + EleCntr - 1)->G.LZ;
1463 { // Separate block for position rotation - local2global
1464 Point3D localDisp, globalDisp;
1465
1466 localDisp.X = x2;
1467 localDisp.Y = y2;
1468 localDisp.Z = z2;
1469 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1470 x2 = (EleArr + EleCntr - 1)->G.Origin.X + globalDisp.X;
1471 y2 = (EleArr + EleCntr - 1)->G.Origin.Y + globalDisp.Y;
1472 z2 = (EleArr + EleCntr - 1)->G.Origin.Z + globalDisp.Z;
1473 } // position rotation over
1474
1475 x3 = -0.5 * (EleArr + EleCntr - 1)->G.LX;
1476 y3 = 0.0;
1477 z3 = 0.5 * (EleArr + EleCntr - 1)->G.LZ;
1478 { // Separate block for position rotation - local2global
1479 Point3D localDisp, globalDisp;
1480
1481 localDisp.X = x3;
1482 localDisp.Y = y3;
1483 localDisp.Z = z3;
1484 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1485 x3 = (EleArr + EleCntr - 1)->G.Origin.X + globalDisp.X;
1486 y3 = (EleArr + EleCntr - 1)->G.Origin.Y + globalDisp.Y;
1487 z3 = (EleArr + EleCntr - 1)->G.Origin.Z + globalDisp.Z;
1488 } // position rotation over
1489
1490 // assign vertices of the element
1491 (EleArr + EleCntr - 1)->G.Vertex[0].X = x0;
1492 (EleArr + EleCntr - 1)->G.Vertex[0].Y = y0;
1493 (EleArr + EleCntr - 1)->G.Vertex[0].Z = z0;
1494 (EleArr + EleCntr - 1)->G.Vertex[1].X = x1;
1495 (EleArr + EleCntr - 1)->G.Vertex[1].Y = y1;
1496 (EleArr + EleCntr - 1)->G.Vertex[1].Z = z1;
1497 (EleArr + EleCntr - 1)->G.Vertex[2].X = x2;
1498 (EleArr + EleCntr - 1)->G.Vertex[2].Y = y2;
1499 (EleArr + EleCntr - 1)->G.Vertex[2].Z = z2;
1500 (EleArr + EleCntr - 1)->G.Vertex[3].X = x3;
1501 (EleArr + EleCntr - 1)->G.Vertex[3].Y = y3;
1502 (EleArr + EleCntr - 1)->G.Vertex[3].Z = z3;
1503
1504 if (OptElementFiles) {
1505 fprintf(fElem, "##Element Counter: %d\n", EleCntr);
1506 fprintf(fElem, "#DevNb\tCompNb\tPrimNb\tId\n");
1507 fprintf(fElem, "%d\t%d\t%d\t%d\n", (EleArr + EleCntr - 1)->DeviceNb,
1508 (EleArr + EleCntr - 1)->ComponentNb,
1509 (EleArr + EleCntr - 1)->PrimitiveNb,
1510 (EleArr + EleCntr - 1)->Id);
1511 fprintf(fElem, "#GType\tX\tY\tZ\tLX\tLZ\tdA\n");
1512 fprintf(
1513 fElem, "%d\t%.16lg\t%.16lg\t%.16lg\t%.16lg\t%.16lg\t%.16lg\n",
1514 (EleArr + EleCntr - 1)->G.Type, (EleArr + EleCntr - 1)->G.Origin.X,
1515 (EleArr + EleCntr - 1)->G.Origin.Y,
1516 (EleArr + EleCntr - 1)->G.Origin.Z, (EleArr + EleCntr - 1)->G.LX,
1517 (EleArr + EleCntr - 1)->G.LZ, (EleArr + EleCntr - 1)->G.dA);
1518 fprintf(fElem, "#DirnCosn: \n");
1519 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.XUnit.X,
1520 (EleArr + EleCntr - 1)->G.DC.XUnit.Y,
1521 (EleArr + EleCntr - 1)->G.DC.XUnit.Z);
1522 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.YUnit.X,
1523 (EleArr + EleCntr - 1)->G.DC.YUnit.Y,
1524 (EleArr + EleCntr - 1)->G.DC.YUnit.Z);
1525 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.ZUnit.X,
1526 (EleArr + EleCntr - 1)->G.DC.ZUnit.Y,
1527 (EleArr + EleCntr - 1)->G.DC.ZUnit.Z);
1528 fprintf(fElem, "#EType\tLambda\n");
1529 fprintf(fElem, "%d\t%lg\n", (EleArr + EleCntr - 1)->E.Type,
1530 (EleArr + EleCntr - 1)->E.Lambda);
1531 fprintf(fElem, "#NbBCs\tCPX\tCPY\tCPZ\tValue\n");
1532 fprintf(fElem, "%d\t%.16lg\t%.16lg\t%.16lg\t%lg\n",
1533 (EleArr + EleCntr - 1)->BC.NbOfBCs,
1534 (EleArr + EleCntr - 1)->BC.CollPt.X,
1535 (EleArr + EleCntr - 1)->BC.CollPt.Y,
1536 (EleArr + EleCntr - 1)->BC.CollPt.Z,
1537 (EleArr + EleCntr - 1)->BC.Value);
1538 } // if OptElementFiles
1539
1540 // draw centroid and mesh
1542 fprintf(fgpElem, "%g\t%g\t%g\n", (EleArr + EleCntr - 1)->BC.CollPt.X,
1543 (EleArr + EleCntr - 1)->BC.CollPt.Y,
1544 (EleArr + EleCntr - 1)->BC.CollPt.Z);
1545 } // if OptGnuplot && OptGnuplotElements
1546
1548 fprintf(fgpMesh, "%g\t%g\t%g\n\n", x0, y0, z0);
1549 fprintf(fgpMesh, "%g\t%g\t%g\n\n", x1, y1, z1);
1550 fprintf(fgpMesh, "%g\t%g\t%g\n\n", x2, y2, z2);
1551 fprintf(fgpMesh, "%g\t%g\t%g\n\n", x3, y3, z3);
1552 fprintf(fgpMesh, "%g\t%g\t%g\n\n", x0, y0, z0);
1553 } // if OptGnuplot && OptGnuplotElements
1554 } // for i
1555 } // for k
1556 ElementEnd[prim] = EleCntr;
1557 NbElmntsOnPrim[prim] = ElementEnd[prim] - ElementBgn[prim] + 1;
1558
1559 if (OptPrimitiveFiles) {
1560 fprintf(fPrim, "Element begin: %d, Element end: %d\n", ElementBgn[prim],
1561 ElementEnd[prim]);
1562 fprintf(fPrim, "Number of elements on primitive: %d\n",
1563 NbElmntsOnPrim[prim]);
1564 fclose(fPrim);
1565 }
1566
1568 if (prim == 1)
1569 fprintf(fgnuElem, " '%s\' w p", gpElem);
1570 else
1571 fprintf(fgnuElem, ", \\\n \'%s\' w p", gpElem);
1572 if (prim == 1) {
1573 fprintf(fgnuMesh, " '%s\' w l", gpMesh);
1574 fprintf(fgnuMesh, ", \\\n \'%s\' w p ps 1", gpElem);
1575 } else {
1576 fprintf(fgnuMesh, ", \\\n \'%s\' w l", gpMesh);
1577 fprintf(fgnuMesh, ", \\\n \'%s\' w p ps 1", gpElem);
1578 }
1579
1580 fclose(fgpElem);
1581 fclose(fgpMesh);
1582 } // if OptGnuplot && OptGnuplotElements
1583
1584 if (OptElementFiles) fclose(fElem);
1585
1586 return (0);
1587} // end of DiscretizeTriangles
1588
1589// It may be noted here that the direction cosines of a given primitive are
1590// the same as those of the elements residing on it. There is only a chage
1591// of origin associated here.
1592int DiscretizeRectangle(int prim, int nvertex, double xvert[], double yvert[],
1593 double zvert[], double xnorm, double ynorm,
1594 double znorm, int volref1, int volref2, int inttype,
1595 double potential, double charge, double lambda,
1596 int NbSegX, int NbSegZ) {
1597 int SurfParentObj, SurfEType;
1598 double SurfX, SurfY, SurfZ, SurfLX, SurfLZ;
1599 double SurfElX, SurfElY, SurfElZ, SurfElLX, SurfElLZ;
1600 DirnCosn3D PrimDirnCosn; // direction cosine of the current primitive
1601
1602 char gpElem[256], gpMesh[256];
1603 FILE *fPrim, *fElem, *fgpPrim, *fgpElem, *fgpMesh;
1604
1605 // Check inputs
1606 if ((NbSegX <= 0) || (NbSegZ <= 0)) {
1607 printf("segmentation input wrong in DiscretizeRectangle ...\n");
1608 return -1;
1609 }
1610
1612 printf("nvertex: %d\n", nvertex);
1613 for (int vert = 0; vert < nvertex; ++vert) {
1614 printf("vert: %d, x: %lg, y: %lg, z: %lg\n", vert, xvert[vert],
1615 yvert[vert], zvert[vert]);
1616 }
1617 printf("Normal: %lg, %lg, %lg\n", xnorm, ynorm, znorm);
1618 } // if OptPrintVertexAndNormal
1619
1620 // necessary for separating filenames
1621 char primstr[10];
1622 snprintf(primstr, 10, "%d", prim);
1623
1624 // in order to avoid warning messages
1625 fPrim = NULL;
1626 fElem = NULL;
1627 fgpMesh = NULL;
1628 fgpElem = NULL;
1629
1630 // Get volume information, to begin with
1631 // int shape, material, boundarytype;
1632 // double eps, potential, charge;
1633 // neBEMVolumeDescription(volref1, &shape, &material,
1634 // &eps, &potential, &charge, &boundarytype);
1635
1636 // compute all the properties of this surface
1637 SurfParentObj = 1;
1638 SurfEType = inttype;
1639 if (SurfEType == 0) {
1640 printf("Wrong SurfEType for prim %d\n", prim);
1641 exit(-1);
1642 }
1643 // centroid of the local coordinate system
1644 SurfX = 0.25 * (xvert[0] + xvert[1] + xvert[2] + xvert[3]);
1645 SurfY = 0.25 * (yvert[0] + yvert[1] + yvert[2] + yvert[3]);
1646 SurfZ = 0.25 * (zvert[0] + zvert[1] + zvert[2] + zvert[3]);
1647 // lengths of the sides
1648 SurfLX = sqrt((xvert[1] - xvert[0]) * (xvert[1] - xvert[0]) +
1649 (yvert[1] - yvert[0]) * (yvert[1] - yvert[0]) +
1650 (zvert[1] - zvert[0]) * (zvert[1] - zvert[0]));
1651 SurfLZ = sqrt((xvert[2] - xvert[1]) * (xvert[2] - xvert[1]) +
1652 (yvert[2] - yvert[1]) * (yvert[2] - yvert[1]) +
1653 (zvert[2] - zvert[1]) * (zvert[2] - zvert[1]));
1654 // Direction cosines
1655 PrimDirnCosn.XUnit.X = (xvert[1] - xvert[0]) / SurfLX;
1656 PrimDirnCosn.XUnit.Y = (yvert[1] - yvert[0]) / SurfLX;
1657 PrimDirnCosn.XUnit.Z = (zvert[1] - zvert[0]) / SurfLX;
1658 PrimDirnCosn.YUnit.X = xnorm;
1659 PrimDirnCosn.YUnit.Y = ynorm;
1660 PrimDirnCosn.YUnit.Z = znorm;
1661 PrimDirnCosn.ZUnit =
1662 Vector3DCrossProduct(&PrimDirnCosn.XUnit, &PrimDirnCosn.YUnit);
1663
1664 // primitive direction cosine assignments
1665 PrimDC[prim].XUnit.X = PrimDirnCosn.XUnit.X;
1666 PrimDC[prim].XUnit.Y = PrimDirnCosn.XUnit.Y;
1667 PrimDC[prim].XUnit.Z = PrimDirnCosn.XUnit.Z;
1668 PrimDC[prim].YUnit.X = PrimDirnCosn.YUnit.X;
1669 PrimDC[prim].YUnit.Y = PrimDirnCosn.YUnit.Y;
1670 PrimDC[prim].YUnit.Z = PrimDirnCosn.YUnit.Z;
1671 PrimDC[prim].ZUnit.X = PrimDirnCosn.ZUnit.X;
1672 PrimDC[prim].ZUnit.Y = PrimDirnCosn.ZUnit.Y;
1673 PrimDC[prim].ZUnit.Z = PrimDirnCosn.ZUnit.Z;
1674
1675 // primitive origin: also the barcenter for a rectangular element
1676 PrimOriginX[prim] = SurfX;
1677 PrimOriginY[prim] = SurfY;
1678 PrimOriginZ[prim] = SurfZ;
1679 PrimLX[prim] = SurfLX;
1680 PrimLZ[prim] = SurfLZ;
1681
1682 double SurfLambda = lambda;
1683 double SurfV = potential;
1684
1685 // file output for a primitive
1686 if (OptPrimitiveFiles) {
1687 char OutPrim[256];
1688 strcpy(OutPrim, ModelOutDir);
1689 strcat(OutPrim, "/Primitives/Primitive");
1690 strcat(OutPrim, primstr);
1691 strcat(OutPrim, ".out");
1692 fPrim = fopen(OutPrim, "w");
1693 if (fPrim == NULL) {
1694 neBEMMessage("DiscretizeRectangle - OutPrim");
1695 return -1;
1696 }
1697 fprintf(fPrim, "#prim: %d, nvertex: %d\n", prim, nvertex);
1698 fprintf(fPrim, "Node1: %lg\t%lg\t%lg\n", xvert[0], yvert[0], zvert[0]);
1699 fprintf(fPrim, "Node2: %lg\t%lg\t%lg\n", xvert[1], yvert[1], zvert[1]);
1700 fprintf(fPrim, "Node3: %lg\t%lg\t%lg\n", xvert[2], yvert[2], zvert[2]);
1701 fprintf(fPrim, "Node4: %lg\t%lg\t%lg\n", xvert[3], yvert[3], zvert[3]);
1702 fprintf(fPrim, "PrimOrigin: %lg\t%lg\t%lg\n", PrimOriginX[prim],
1703 PrimOriginY[prim], PrimOriginZ[prim]);
1704 fprintf(fPrim, "Primitive lengths: %lg\t%lg\n", PrimLX[prim], PrimLZ[prim]);
1705 fprintf(fPrim, "Norm: %lg\t%lg\t%lg\n", xnorm, ynorm, znorm);
1706 fprintf(fPrim, "#volref1: %d, volref2: %d\n", volref1, volref2);
1707 fprintf(fPrim, "#NbSegX: %d, NbSegZ: %d\n", NbSegX, NbSegZ);
1708 fprintf(fPrim, "#ParentObj: %d\tEType: %d\n", SurfParentObj, SurfEType);
1709 fprintf(fPrim, "#SurfX\tSurfY\tSurfZ\tSurfLZ\tSurfLZ\n");
1710 fprintf(fPrim, "%lg\t%lg\t%lg\t%lg\t%lg\n", SurfX, SurfY, SurfZ, SurfLX,
1711 SurfLZ);
1712 // fprintf(fPrim, "#SurfRX: %lg\tSurfRY: %lg\tSurfRZ: %lg\n",
1713 // SurfRX, SurfRY, SurfRZ);
1714 fprintf(fPrim, "#DirnCosn: \n");
1715 fprintf(fPrim, "%lg, %lg, %lg\n", PrimDirnCosn.XUnit.X,
1716 PrimDirnCosn.XUnit.Y, PrimDirnCosn.XUnit.Z);
1717 fprintf(fPrim, "%lg, %lg, %lg\n", PrimDirnCosn.YUnit.X,
1718 PrimDirnCosn.YUnit.Y, PrimDirnCosn.YUnit.Z);
1719 fprintf(fPrim, "%lg, %lg, %lg\n", PrimDirnCosn.ZUnit.X,
1720 PrimDirnCosn.ZUnit.Y, PrimDirnCosn.ZUnit.Z);
1721 fprintf(fPrim, "#SurfLambda: %lg\tSurfV: %lg\n", SurfLambda, SurfV);
1722 } // if OptPrimitiveFiles
1723
1724 // necessary for gnuplot
1726 char gpPrim[256];
1727 strcpy(gpPrim, MeshOutDir);
1728 strcat(gpPrim, "/GViewDir/gpPrim");
1729 strcat(gpPrim, primstr);
1730 strcat(gpPrim, ".out");
1731 fgpPrim = fopen(gpPrim, "w");
1732 if (fgpPrim == NULL) {
1733 neBEMMessage("DiscretizeRectangle - OutgpPrim");
1734 fclose(fPrim);
1735 return -1;
1736 }
1737 fprintf(fgpPrim, "%g\t%g\t%g\n\n", xvert[0], yvert[0], zvert[0]);
1738 fprintf(fgpPrim, "%g\t%g\t%g\n\n", xvert[1], yvert[1], zvert[1]);
1739 fprintf(fgpPrim, "%g\t%g\t%g\n\n", xvert[2], yvert[2], zvert[2]);
1740 fprintf(fgpPrim, "%g\t%g\t%g\n\n", xvert[3], yvert[3], zvert[3]);
1741 fprintf(fgpPrim, "%g\t%g\t%g\n", xvert[0], yvert[0], zvert[0]);
1742 fclose(fgpPrim);
1743
1744 if (prim == 1)
1745 fprintf(fgnuPrim, " '%s\' w l", gpPrim);
1746 else
1747 fprintf(fgnuPrim, ", \\\n \'%s\' w l", gpPrim);
1748 } // if OptGnuplot && OptGnuplotPrimitives
1749
1750 // file outputs for elements on primitive
1751 if (OptElementFiles) {
1752 char OutElem[256];
1753 strcpy(OutElem, MeshOutDir);
1754 strcat(OutElem, "/Elements/ElemOnPrim");
1755 strcat(OutElem, primstr);
1756 strcat(OutElem, ".out");
1757 fElem = fopen(OutElem, "w");
1758 // assert(fElem != NULL);
1759 if (fElem == NULL) {
1760 neBEMMessage("DiscretizeRectangle - OutElem");
1761 return -1;
1762 }
1763 } // if OptElementFiles
1764
1765 // gnuplot friendly file outputs for elements on primitive
1767 strcpy(gpElem, MeshOutDir);
1768 strcat(gpElem, "/GViewDir/gpElemOnPrim");
1769 strcat(gpElem, primstr);
1770 strcat(gpElem, ".out");
1771 fgpElem = fopen(gpElem, "w");
1772 // assert(fgpElem != NULL);
1773 if (fgpElem == NULL) {
1774 neBEMMessage("DiscretizeRectangle - OutgpElem");
1775 if (fElem) fclose(fElem);
1776 return -1;
1777 }
1778 // gnuplot friendly file outputs for elements on primitive
1779 strcpy(gpMesh, MeshOutDir);
1780 strcat(gpMesh, "/GViewDir/gpMeshOnPrim");
1781 strcat(gpMesh, primstr);
1782 strcat(gpMesh, ".out");
1783 fgpMesh = fopen(gpMesh, "w");
1784 if (fgpMesh == NULL) {
1785 neBEMMessage("DiscretizeRectangle - OutgpMesh");
1786 fclose(fgpElem);
1787 return -1;
1788 }
1789 } // if OptGnuplot && OptElements
1790
1791 // Compute element positions (CGs) in the primitive local coordinate system.
1792 // Then map these CGs to the global coordinate system.
1793 // (xav, 0, zav) is the CG of an element wrt the primitive coordinate system
1794 // From this, we find the offset of the element from the primitive CG in the
1795 // global coordinate system by just rotating the displacement vector
1796 // (0,0,0) -> (xav,0,zav) using the known DCM of the surface.
1797 // This rotated vector (now in the global system) is then added to the
1798 // position vector of the primitive CG (always in the global system) to get
1799 // the CG of the element in the global system. Make sure that the larger
1800 // number is being used to discretize the longer side - can be OverSmart in
1801 // certain cases - there may be cases where smaller number of elements suffice
1802 // for a longer side
1803 if (NbSegX == NbSegZ) {
1804 SurfElLX = SurfLX / NbSegX; // element sizes
1805 SurfElLZ = SurfLZ / NbSegZ;
1806 } else if (NbSegX > NbSegZ) {
1807 if (SurfLX > SurfLZ) {
1808 SurfElLX = SurfLX / NbSegX; // element sizes
1809 SurfElLZ = SurfLZ / NbSegZ;
1810 } else // interchange NbSegX and NbSegZ
1811 {
1812 int tmp = NbSegZ;
1813 NbSegZ = NbSegX;
1814 NbSegX = tmp;
1815 SurfElLX = SurfLX / NbSegX; // element sizes
1816 SurfElLZ = SurfLZ / NbSegZ;
1817 }
1818 } // NbSegX > NbSegZ
1819 else // NbSegX < NbSegZ
1820 {
1821 if (SurfLX < SurfLZ) {
1822 SurfElLX = SurfLX / NbSegX; // element sizes
1823 SurfElLZ = SurfLZ / NbSegZ;
1824 } else // interchange NbSegX and NbSegZ
1825 {
1826 int tmp = NbSegZ;
1827 NbSegZ = NbSegX;
1828 NbSegX = tmp;
1829 SurfElLX = SurfLX / NbSegX; // element sizes
1830 SurfElLZ = SurfLZ / NbSegZ;
1831 }
1832 }
1833
1834 // Analysis of element aspect ratio.
1835 // Note that we can afford only to reduce the total number of elements.
1836 // Otherwise, we'll have to realloc `EleArr' array.
1837 // Later, we'll make the corrections such that the total number of elements
1838 // remain close to the originally intended value.
1839 double AR = SurfElLX / SurfElLZ; // indicative element aspect ratio
1840 if (OptPrimitiveFiles) {
1841 fprintf(fPrim,
1842 "Using the input, the aspect ratio of the elements on prim: %d\n",
1843 prim);
1844 fprintf(fPrim,
1845 "NbSegX: %d, SurfElLX: %lg, NbSegZ: %d, SurfElLZ: %lg, AR: %lg\n",
1846 NbSegX, SurfElLX, NbSegZ, SurfElLZ, AR);
1847 }
1848 if (AR > 10.0) // NbSegZ needs to be reduced
1849 {
1850 double tmpElLZ = SurfElLX / 10.0;
1851 NbSegZ = (int)(SurfLZ / tmpElLZ);
1852 if (NbSegZ <= 0) NbSegZ = 1;
1853 SurfElLZ = SurfLZ / NbSegZ;
1854 }
1855 if (AR < 0.1) // NbSegX need to be reduced
1856 {
1857 double tmpElLX = SurfElLZ * 0.1;
1858 NbSegX = (int)(SurfLX / tmpElLX);
1859 if (NbSegX <= 0) NbSegX = 1;
1860 SurfElLX = SurfLX / NbSegX;
1861 }
1862 AR = SurfElLX / SurfElLZ; // indicative element aspect ratio
1863 if (OptPrimitiveFiles) {
1864 fprintf(fPrim, "After analyzing the aspect ratio of the elements\n");
1865 fprintf(fPrim,
1866 "NbSegX: %d, SurfElLX: %lg, NbSegZ: %d, SurfElLZ: %lg, AR: %lg\n",
1867 NbSegX, SurfElLX, NbSegZ, SurfElLZ, AR);
1868 }
1869
1870 double x0, y0, z0, x1, y1, z1, x2, y2, z2, x3, y3, z3, xav, zav;
1871 ElementBgn[prim] = EleCntr + 1;
1872 for (int i = 1; i <= NbSegX; ++i) {
1873 x1 = -SurfLX / 2.0 +
1874 (double)(i - 1) * SurfElLX; // assuming centroid at 0,0,0
1875 x2 = -SurfLX / 2.0 + (double)(i)*SurfElLX;
1876 xav = 0.5 * (x1 + x2);
1877
1878 for (int k = 1; k <= NbSegZ; ++k) {
1879 z1 = -SurfLZ / 2.0 + (double)(k - 1) * SurfElLZ;
1880 z2 = -SurfLZ / 2.0 + (double)(k)*SurfElLZ;
1881 zav = 0.5 * (z1 + z2);
1882
1883 { // Separate block for position rotation - local2global
1884 Point3D localDisp, globalDisp;
1885
1886 localDisp.X = xav;
1887 localDisp.Y = 0.0;
1888 localDisp.Z = zav;
1889 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1890 SurfElX = SurfX + globalDisp.X;
1891 SurfElY = SurfY + globalDisp.Y;
1892 SurfElZ = SurfZ + globalDisp.Z;
1893 } // vector rotation over
1894
1895 // Assign element values and write in the file
1896 ++EleCntr;
1897 if (EleCntr > NbElements) {
1898 neBEMMessage("DiscretizeRectangle - EleCntr more than NbElements!");
1899 if (fgpMesh) fclose(fgpMesh);
1900 return -1;
1901 }
1902
1903 (EleArr + EleCntr - 1)->DeviceNb =
1904 1; // At present, there is only one device
1905 (EleArr + EleCntr - 1)->ComponentNb = SurfParentObj;
1906 (EleArr + EleCntr - 1)->PrimitiveNb = prim;
1907 (EleArr + EleCntr - 1)->Id = EleCntr;
1908 (EleArr + EleCntr - 1)->G.Type = 4; // rectangular here
1909 (EleArr + EleCntr - 1)->G.Origin.X = SurfElX;
1910 (EleArr + EleCntr - 1)->G.Origin.Y = SurfElY;
1911 (EleArr + EleCntr - 1)->G.Origin.Z = SurfElZ;
1912 (EleArr + EleCntr - 1)->G.LX = SurfElLX;
1913 (EleArr + EleCntr - 1)->G.LZ = SurfElLZ;
1914 (EleArr + EleCntr - 1)->G.dA =
1915 (EleArr + EleCntr - 1)->G.LX * (EleArr + EleCntr - 1)->G.LZ;
1916 (EleArr + EleCntr - 1)->G.DC.XUnit.X = PrimDirnCosn.XUnit.X;
1917 (EleArr + EleCntr - 1)->G.DC.XUnit.Y = PrimDirnCosn.XUnit.Y;
1918 (EleArr + EleCntr - 1)->G.DC.XUnit.Z = PrimDirnCosn.XUnit.Z;
1919 (EleArr + EleCntr - 1)->G.DC.YUnit.X = PrimDirnCosn.YUnit.X;
1920 (EleArr + EleCntr - 1)->G.DC.YUnit.Y = PrimDirnCosn.YUnit.Y;
1921 (EleArr + EleCntr - 1)->G.DC.YUnit.Z = PrimDirnCosn.YUnit.Z;
1922 (EleArr + EleCntr - 1)->G.DC.ZUnit.X = PrimDirnCosn.ZUnit.X;
1923 (EleArr + EleCntr - 1)->G.DC.ZUnit.Y = PrimDirnCosn.ZUnit.Y;
1924 (EleArr + EleCntr - 1)->G.DC.ZUnit.Z = PrimDirnCosn.ZUnit.Z;
1925 (EleArr + EleCntr - 1)->E.Type = SurfEType;
1926 (EleArr + EleCntr - 1)->E.Lambda = SurfLambda;
1927 (EleArr + EleCntr - 1)->Solution = 0.0;
1928 (EleArr + EleCntr - 1)->Assigned = charge;
1929 (EleArr + EleCntr - 1)->BC.NbOfBCs = 1; // assume one BC per element
1930 (EleArr + EleCntr - 1)->BC.CollPt.X = (EleArr + EleCntr - 1)->G.Origin.X;
1931 (EleArr + EleCntr - 1)->BC.CollPt.Y = (EleArr + EleCntr - 1)->G.Origin.Y;
1932 (EleArr + EleCntr - 1)->BC.CollPt.Z = (EleArr + EleCntr - 1)->G.Origin.Z;
1933
1934 // find element vertices
1935 // 1) displacement vector in the ECS is first identified
1936 // 2) this vector is transformed to the GCS
1937 // 3) the global displacement vector, when added to the centroid in GCS,
1938 // gives the node positions in GCS.
1939 x0 = -0.5 *
1940 (EleArr + EleCntr - 1)->G.LX; // xyz displacement of node wrt ECS
1941 y0 = 0.0;
1942 z0 = -0.5 * (EleArr + EleCntr - 1)->G.LZ;
1943 { // Separate block for position rotation - local2global
1944 Point3D localDisp, globalDisp;
1945
1946 localDisp.X = x0;
1947 localDisp.Y = y0;
1948 localDisp.Z = z0; // displacement in GCS
1949 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1950 x0 = (EleArr + EleCntr - 1)->G.Origin.X +
1951 globalDisp.X; // xyz position in GCS
1952 y0 = (EleArr + EleCntr - 1)->G.Origin.Y + globalDisp.Y;
1953 z0 = (EleArr + EleCntr - 1)->G.Origin.Z + globalDisp.Z;
1954 } // position rotation over
1955
1956 x1 = 0.5 * (EleArr + EleCntr - 1)->G.LX;
1957 y1 = 0.0;
1958 z1 = -0.5 * (EleArr + EleCntr - 1)->G.LZ;
1959 { // Separate block for position rotation - local2global
1960 Point3D localDisp, globalDisp;
1961
1962 localDisp.X = x1;
1963 localDisp.Y = y1;
1964 localDisp.Z = z1;
1965 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1966 x1 = (EleArr + EleCntr - 1)->G.Origin.X + globalDisp.X;
1967 y1 = (EleArr + EleCntr - 1)->G.Origin.Y + globalDisp.Y;
1968 z1 = (EleArr + EleCntr - 1)->G.Origin.Z + globalDisp.Z;
1969 } // position rotation over
1970
1971 x2 = 0.5 * (EleArr + EleCntr - 1)->G.LX;
1972 y2 = 0.0;
1973 z2 = 0.5 * (EleArr + EleCntr - 1)->G.LZ;
1974 { // Separate block for position rotation - local2global
1975 Point3D localDisp, globalDisp;
1976
1977 localDisp.X = x2;
1978 localDisp.Y = y2;
1979 localDisp.Z = z2;
1980 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1981 x2 = (EleArr + EleCntr - 1)->G.Origin.X + globalDisp.X;
1982 y2 = (EleArr + EleCntr - 1)->G.Origin.Y + globalDisp.Y;
1983 z2 = (EleArr + EleCntr - 1)->G.Origin.Z + globalDisp.Z;
1984 } // position rotation over
1985
1986 x3 = -0.5 * (EleArr + EleCntr - 1)->G.LX;
1987 y3 = 0.0;
1988 z3 = 0.5 * (EleArr + EleCntr - 1)->G.LZ;
1989 { // Separate block for position rotation - local2global
1990 Point3D localDisp, globalDisp;
1991
1992 localDisp.X = x3;
1993 localDisp.Y = y3;
1994 localDisp.Z = z3;
1995 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1996 x3 = (EleArr + EleCntr - 1)->G.Origin.X + globalDisp.X;
1997 y3 = (EleArr + EleCntr - 1)->G.Origin.Y + globalDisp.Y;
1998 z3 = (EleArr + EleCntr - 1)->G.Origin.Z + globalDisp.Z;
1999 } // position rotation over
2000
2001 // assign vertices of the element
2002 (EleArr + EleCntr - 1)->G.Vertex[0].X = x0;
2003 (EleArr + EleCntr - 1)->G.Vertex[0].Y = y0;
2004 (EleArr + EleCntr - 1)->G.Vertex[0].Z = z0;
2005 (EleArr + EleCntr - 1)->G.Vertex[1].X = x1;
2006 (EleArr + EleCntr - 1)->G.Vertex[1].Y = y1;
2007 (EleArr + EleCntr - 1)->G.Vertex[1].Z = z1;
2008 (EleArr + EleCntr - 1)->G.Vertex[2].X = x2;
2009 (EleArr + EleCntr - 1)->G.Vertex[2].Y = y2;
2010 (EleArr + EleCntr - 1)->G.Vertex[2].Z = z2;
2011 (EleArr + EleCntr - 1)->G.Vertex[3].X = x3;
2012 (EleArr + EleCntr - 1)->G.Vertex[3].Y = y3;
2013 (EleArr + EleCntr - 1)->G.Vertex[3].Z = z3;
2014
2015 if (OptElementFiles) {
2016 fprintf(fElem, "##Element Counter: %d\n", EleCntr);
2017 fprintf(fElem, "#DevNb\tCompNb\tPrimNb\tId\n");
2018 fprintf(fElem, "%d\t%d\t%d\t%d\n", (EleArr + EleCntr - 1)->DeviceNb,
2019 (EleArr + EleCntr - 1)->ComponentNb,
2020 (EleArr + EleCntr - 1)->PrimitiveNb,
2021 (EleArr + EleCntr - 1)->Id);
2022 fprintf(fElem, "#GType\tX\tY\tZ\tLX\tLZ\tdA\n");
2023 fprintf(
2024 fElem, "%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
2025 (EleArr + EleCntr - 1)->G.Type, (EleArr + EleCntr - 1)->G.Origin.X,
2026 (EleArr + EleCntr - 1)->G.Origin.Y,
2027 (EleArr + EleCntr - 1)->G.Origin.Z, (EleArr + EleCntr - 1)->G.LX,
2028 (EleArr + EleCntr - 1)->G.LZ, (EleArr + EleCntr - 1)->G.dA);
2029 fprintf(fElem, "#DirnCosn: \n");
2030 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.XUnit.X,
2031 (EleArr + EleCntr - 1)->G.DC.XUnit.Y,
2032 (EleArr + EleCntr - 1)->G.DC.XUnit.Z);
2033 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.YUnit.X,
2034 (EleArr + EleCntr - 1)->G.DC.YUnit.Y,
2035 (EleArr + EleCntr - 1)->G.DC.YUnit.Z);
2036 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.ZUnit.X,
2037 (EleArr + EleCntr - 1)->G.DC.ZUnit.Y,
2038 (EleArr + EleCntr - 1)->G.DC.ZUnit.Z);
2039 fprintf(fElem, "#EType\tLambda\n");
2040 fprintf(fElem, "%d\t%lg\n", (EleArr + EleCntr - 1)->E.Type,
2041 (EleArr + EleCntr - 1)->E.Lambda);
2042 fprintf(fElem, "#NbBCs\tCPX\tCPY\tCPZ\tValue\n");
2043 fprintf(fElem, "%d\t%lg\t%lg\t%lg\t%lg\n",
2044 (EleArr + EleCntr - 1)->BC.NbOfBCs,
2045 (EleArr + EleCntr - 1)->BC.CollPt.X,
2046 (EleArr + EleCntr - 1)->BC.CollPt.Y,
2047 (EleArr + EleCntr - 1)->BC.CollPt.Z,
2048 (EleArr + EleCntr - 1)->BC.Value);
2049 } // if OptElementFiles
2050
2051 // mark centroid
2053 fprintf(fgpElem, "%g\t%g\t%g\n", (EleArr + EleCntr - 1)->BC.CollPt.X,
2054 (EleArr + EleCntr - 1)->BC.CollPt.Y,
2055 (EleArr + EleCntr - 1)->BC.CollPt.Z);
2056 } // if OptGnuplot && OptGnuplotElements
2057
2059 fprintf(fgpMesh, "%g\t%g\t%g\n", x0, y0, z0);
2060 fprintf(fgpMesh, "%g\t%g\t%g\n", x1, y1, z1);
2061 fprintf(fgpMesh, "%g\t%g\t%g\n", x2, y2, z2);
2062 fprintf(fgpMesh, "%g\t%g\t%g\n", x3, y3, z3);
2063 fprintf(fgpMesh, "%g\t%g\t%g\n\n", x0, y0, z0);
2064 /*
2065 fprintf(fgpMesh, "%g\t%g\t%g\t%d\n", x0, y0, z0, 1);
2066 fprintf(fgpMesh, "%g\t%g\t%g\t%d\n\n", x1, y1, z1, 2);
2067 fprintf(fgpMesh, "%g\t%g\t%g\t%d\n", x2, y2, z2, 1);
2068 fprintf(fgpMesh, "%g\t%g\t%g\t%d\n\n\n", x2, y2, z2, 2);
2069 fprintf(fgpMesh, "%g\t%g\t%g\t%d\n", x0, y0, z0, 1);
2070 fprintf(fgpMesh, "%g\t%g\t%g\t%d\n\n", x3, y3, z3, 2);
2071 fprintf(fgpMesh, "%g\t%g\t%g\t%d\n", x2, y2, z2, 1);
2072 fprintf(fgpMesh, "%g\t%g\t%g\t%d\n\n\n", x2, y2, z2, 2);
2073 */
2074 } // if(OptGnuplot && OptGnuplotElements)
2075 } // for k
2076 } // for i
2077 ElementEnd[prim] = EleCntr;
2078 NbElmntsOnPrim[prim] = ElementEnd[prim] - ElementBgn[prim] + 1;
2079
2080 if (OptPrimitiveFiles) {
2081 fprintf(fPrim, "Element begin: %d, Element end: %d\n", ElementBgn[prim],
2082 ElementEnd[prim]);
2083 fprintf(fPrim, "Number of elements on primitive: %d\n",
2084 NbElmntsOnPrim[prim]);
2085 fclose(fPrim);
2086 }
2087
2088 if (OptElementFiles) fclose(fElem);
2089
2091 if (prim == 1)
2092 fprintf(fgnuElem, " '%s\' w p", gpElem);
2093 else
2094 fprintf(fgnuElem, ", \\\n \'%s\' w p", gpElem);
2095 if (prim == 1) {
2096 fprintf(fgnuMesh, " '%s\' w l", gpMesh);
2097 fprintf(fgnuMesh, ", \\\n \'%s\' w p ps 1", gpElem);
2098 } else {
2099 fprintf(fgnuMesh, ", \\\n \'%s\' w l", gpMesh);
2100 fprintf(fgnuMesh, ", \\\n \'%s\' w p ps 1", gpElem);
2101 }
2102
2103 fclose(fgpElem);
2104 fclose(fgpMesh);
2105 }
2106
2107 return (0);
2108} // end of DiscretizeRectangle
2109
2110int DiscretizePolygon(int /*prim*/, int /*nvertex*/, double /*xvert*/[],
2111 double /*yvert*/[], double /*zvert*/[], double /*xnorm*/,
2112 double /*ynorm*/, double /*znorm*/, int /*volref1*/,
2113 int /*volref2*/, int /*inttype*/, double /*potential*/,
2114 double /*charge*/, double /*lambda*/, int NbSegX,
2115 int NbSegZ) {
2116 // Check inputs
2117 if ((NbSegX <= 0) || (NbSegZ <= 0)) {
2118 printf("segmentation input wrong in DiscretizePolygon ...\n");
2119 return -1;
2120 }
2121
2122 return (0);
2123} // end of DiscretizePolygon
2124
2126 // Loop over all the elements of all the primitives.
2127 // Some of the primitives do not have a boundary condition to be satisfied
2128 // We'll omit these primitives but before doing that we need to know to
2129 // which primitive a particular element belongs to.
2130 // The RHS will also need to be modified to accommodate the presence of
2131 // floating conductors and charged (known) substances.
2132 // Looping on primitives (rather than elements) can save precious time!
2133 for (int ele = 1; ele <= NbElements; ++ele) {
2134 int prim = (EleArr + ele - 1)->PrimitiveNb;
2135 // Note this condition is pure geometry, not electric!
2136 switch (PrimType[prim]) {
2137 case 2:
2138 case 3: // for floating conductor and for dielectric-dielectric intfc
2139 case 4: // the BC is zero (may be modified due to known charges, later)
2140 (EleArr + ele - 1)->BC.Value = ApplPot[prim];
2141 break;
2142
2143 default:
2144 printf("Primitive out of range in BoundaryConditions ... returning\n");
2145 return (-1);
2146 } // switch on PrimType over
2147 } // ele loop over
2148
2149 return (0);
2150} // end of BoundaryConditions
2151
2152// Set up initial conditions (C styling to be fixed)
2154 int fstatus = 0;
2155
2156 // Known charges
2157 if (OptKnCh) {
2158 startClock = clock();
2159 printf("InitialConditions: InitKnownCharges ... ");
2160 fflush(stdout);
2161 fstatus = InitKnownCharges();
2162 if (fstatus != 0) {
2163 neBEMMessage("InitialConditions - InitKnownCharges");
2164 return -1;
2165 }
2166 printf("InitialConditions: InitKnownCharges done!\n");
2167 fflush(stdout);
2168 stopClock = clock();
2170 printf("to InitKnownCharges.\n");
2171 } // if OptKnCh
2172
2173 // Charging up
2174 if (OptChargingUp) {
2175 startClock = clock();
2176 printf("InitialConditions: InitChargingUp ... ");
2177 fflush(stdout);
2178 fstatus = InitChargingUp();
2179 if (fstatus != 0) {
2180 neBEMMessage("InitialConditions - InitChargingUp");
2181 return -1;
2182 }
2183 printf("InitialConditions: InitChargingUp done!\n");
2184 fflush(stdout);
2185 stopClock = clock();
2187 printf("to InitChargingUp.\n");
2188 } // if OptChargingUp
2189
2190 return 0;
2191} // InitialConditions ends
2192
2193// Very important note (Vin):
2194// There are two approaches by which existing charge distributions can be
2195// considered. The first one, neBEMKnownCharges, is the simpler approach
2196// in which the external charges are left as they are. In the second one,
2197// neBEMChargingUp, the charges that have crossed an element of a dielectric
2198// interface, is considered to be sitting on the element. All such accumulated
2199// charges are assigned to that element by suitably modifying
2200// (EleArr+elesrc-1)->Assigned.
2201// However, possible pitfalls such as considering the effects twice, exist.
2202// Hence the code needs to be carefully exampined.
2203// int neBEMKnownCharges(int (*Pt2UserFunction)(void)) - apt for UpdateKnCh
2205 int debugFn = 0;
2206
2207 /*
2208 // How to check that the pointer points to a valid function?
2209 if(Pt2UserFunction == NULL)
2210 {
2211 printf("Not a valid function ... returning ...\n");
2212 return(-1);
2213 }
2214 else
2215 {
2216 // printf("Pt2UserFunction points to %p\n", Pt2UserFunction);
2217 }
2218
2219 // Status of the known charges conditions is meaningful only after the
2220 // element discretization has been completed, i.e., beyond the 5th state.
2221 if(neBEMState >= 5)
2222 { // the following function is declared in the Interface.h.
2223 int fstatus = (*Pt2UserFunction)(); // user to supply function
2224 if(fstatus != 0)
2225 {
2226 neBEMMessage("neBEMKnownCharges - Pt2UserFunction");
2227 return -1;
2228 }
2229 if(neBEMState > 5) // assume LHS and inversion to be over?
2230 neBEMState = 8;
2231 }
2232 else
2233 {
2234 printf("Known charges are meaningful only beyond state 4 ...\n");
2235 printf("returning ...\n");
2236 return(-1);
2237 }
2238 */
2239
2240 // Set up parameters related to known charge calculations
2241 // Electrons and ions can be distributed as points, lines, areas or volumes.
2242 {
2243 FILE *KnChInpFile = fopen("neBEMInp/neBEMKnCh.inp", "r");
2244 if (KnChInpFile == NULL) {
2245 OptKnCh = 0;
2246 printf(
2247 "neBEMKnCh.inp absent ... assuming absence of known charges ...\n");
2248 } else {
2249 fscanf(KnChInpFile, "OptKnCh: %d\n", &OptKnCh);
2250 if (1) printf("OptKnCh: %d\n", OptKnCh);
2251
2252 if (!OptKnCh) printf("OptKnCh = 0 ... assuming no known charges ...\n");
2253
2254 if (OptKnCh) {
2255 char PointKnChFile[256];
2256 char LineKnChFile[256];
2257 char AreaKnChFile[256];
2258 char VolumeKnChFile[256];
2259 double LScaleFactor;
2260 double KnChFactor;
2261
2262 fscanf(KnChInpFile, "NbPointsKnCh: %d\n", &NbPointsKnCh);
2263 fscanf(KnChInpFile, "PointKnChFile: %s\n", PointKnChFile);
2264 fscanf(KnChInpFile, "NbLinesKnCh: %d\n", &NbLinesKnCh);
2265 fscanf(KnChInpFile, "LineKnChFile: %s\n", LineKnChFile);
2266 fscanf(KnChInpFile, "NbAreasKnCh: %d\n", &NbAreasKnCh);
2267 fscanf(KnChInpFile, "AreaKnChFile: %s\n", AreaKnChFile);
2268 fscanf(KnChInpFile, "NbVolumesKnCh: %d\n", &NbVolumesKnCh);
2269 fscanf(KnChInpFile, "VolumeKnChFile: %s\n", VolumeKnChFile);
2270 fscanf(KnChInpFile, "LScaleFactor: %lg\n", &LScaleFactor);
2271 fscanf(KnChInpFile, "KnChFactor: %lg\n", &KnChFactor);
2272 if (1) {
2273 printf("NbPointsKnCh: %d\n", NbPointsKnCh);
2274 printf("PointKnChFile: %s\n", PointKnChFile);
2275 printf("NbLinesKnCh: %d\n", NbLinesKnCh);
2276 printf("LineKnChFile: %s\n", LineKnChFile);
2277 printf("NbAreasKnCh: %d\n", NbAreasKnCh);
2278 printf("AreaKnChFile: %s\n", AreaKnChFile);
2279 printf("NbVolumesKnCh: %d\n", NbVolumesKnCh);
2280 printf("VolumeKnChFile: %s\n", VolumeKnChFile);
2281 printf("LScaleFactor: %lg\n", LScaleFactor);
2282 printf("KnChFactor: %lg\n", KnChFactor);
2283 }
2284
2285 if (NbPointsKnCh) { // Points
2286 if (debugFn)
2287 printf("No. of points with known charges: %d\n", NbPointsKnCh);
2288
2289 FILE *fptrPointKnChFile = fopen(PointKnChFile, "r");
2290 if (fptrPointKnChFile == NULL) {
2291 neBEMMessage("PointKnCh file absent ... returning\n");
2292 fclose(KnChInpFile);
2293 return -10;
2294 }
2295
2296 PointKnChArr =
2297 (PointKnCh *)malloc((NbPointsKnCh + 1) * sizeof(PointKnCh));
2298
2299 for (int point = 0; point <= NbPointsKnCh; ++point) {
2300 // CHECK!!! ele limits start from 0, but all else from 1 to ...
2301 PointKnChArr[point].Nb = 0;
2302 PointKnChArr[point].P.X = 0.0;
2303 PointKnChArr[point].P.Y = 0.0;
2304 PointKnChArr[point].P.Z = 0.0;
2305 PointKnChArr[point].Assigned = 0.0;
2306 }
2307
2308 char header[256];
2309 fgets(header, 256, fptrPointKnChFile); // header
2310
2311 for (int point = 1; point <= NbPointsKnCh; ++point) {
2312 fscanf(fptrPointKnChFile, "%d %lg %lg %lg %lg\n",
2313 &PointKnChArr[point].Nb, &PointKnChArr[point].P.X,
2314 &PointKnChArr[point].P.Y, &PointKnChArr[point].P.Z,
2315 &PointKnChArr[point].Assigned);
2316
2317 PointKnChArr[point].P.X /= LScaleFactor; // convert Garfield cm
2318 PointKnChArr[point].P.Y /= LScaleFactor; // to SI meter
2319 PointKnChArr[point].P.Z /= LScaleFactor; // and similar other
2320 PointKnChArr[point].Assigned *= KnChFactor; // requirements
2321
2322 if (debugFn) {
2323 printf("Nb: %d , X: %lg, Y:%lg, Z:%lg, Assigned:%lg\n",
2324 PointKnChArr[point].Nb, PointKnChArr[point].P.X,
2325 PointKnChArr[point].P.Y, PointKnChArr[point].P.Z,
2326 PointKnChArr[point].Assigned);
2327 }
2328 }
2329
2330 fclose(fptrPointKnChFile);
2331 if (debugFn) printf("done for all points\n");
2332 } // if NbPointsKnCh: Inputs and calculations for points ends
2333
2334 if (NbLinesKnCh) { // Lines
2335 if (debugFn)
2336 printf("No. of lines with known charges: %d\n", NbLinesKnCh);
2337
2338 FILE *fptrLineKnChFile = fopen(LineKnChFile, "r");
2339 if (fptrLineKnChFile == NULL) {
2340 neBEMMessage("LineKnCh file absent ... returning\n");
2341 return -10;
2342 }
2343
2344 LineKnChArr =
2345 (LineKnCh *)malloc((NbLinesKnCh + 1) * sizeof(LineKnCh));
2346
2347 for (int line = 0; line <= NbLinesKnCh; ++line) {
2348 // CHECK!!! ele limits start from 0, but all else from 1 to ...
2349 LineKnChArr[line].Nb = 0;
2350 LineKnChArr[line].Start.X = 0.0;
2351 LineKnChArr[line].Start.Y = 0.0;
2352 LineKnChArr[line].Start.Z = 0.0;
2353 LineKnChArr[line].Stop.X = 0.0;
2354 LineKnChArr[line].Stop.Y = 0.0;
2355 LineKnChArr[line].Stop.Z = 0.0;
2356 LineKnChArr[line].Radius = 0.0;
2357 LineKnChArr[line].Assigned = 0.0;
2358 }
2359
2360 char header[256];
2361 fgets(header, 256, fptrLineKnChFile); // header
2362
2363 for (int line = 1; line <= NbLinesKnCh; ++line) {
2364 fscanf(fptrLineKnChFile, "%d %lg %lg %lg %lg %lg %lg %lg %lg\n",
2365 &LineKnChArr[line].Nb, &LineKnChArr[line].Start.X,
2366 &LineKnChArr[line].Start.Y, &LineKnChArr[line].Start.Z,
2367 &LineKnChArr[line].Stop.X, &LineKnChArr[line].Stop.Y,
2368 &LineKnChArr[line].Stop.Z, &LineKnChArr[line].Radius,
2369 &LineKnChArr[line].Assigned);
2370
2371 LineKnChArr[line].Start.X /= LScaleFactor; // cm to m
2372 LineKnChArr[line].Start.Y /= LScaleFactor; // and similar other
2373 LineKnChArr[line].Start.Z /= LScaleFactor;
2374 LineKnChArr[line].Stop.X /= LScaleFactor;
2375 LineKnChArr[line].Stop.Y /= LScaleFactor;
2376 LineKnChArr[line].Stop.Z /= LScaleFactor;
2377 LineKnChArr[line].Radius /= LScaleFactor;
2378 LineKnChArr[line].Assigned *= LScaleFactor; // Q/cm to Q/m
2379 LineKnChArr[line].Assigned *= KnChFactor;
2380
2381 if (debugFn) {
2382 printf(
2383 "Nb: %d, X1Y1Z1: %lg %lg %lg X2Y2Z2 %lg %lg %lg R: %lg "
2384 "Lmda:%lg\n",
2385 LineKnChArr[line].Nb, LineKnChArr[line].Start.X,
2386 LineKnChArr[line].Start.Y, LineKnChArr[line].Start.Z,
2387 LineKnChArr[line].Stop.X, LineKnChArr[line].Stop.Y,
2388 LineKnChArr[line].Stop.Z, LineKnChArr[line].Radius,
2389 LineKnChArr[line].Assigned);
2390 }
2391 }
2392
2393 fclose(fptrLineKnChFile);
2394 if (debugFn) printf("done for all lines\n");
2395 } // if NbLinesKnCh: Inputs and calculations for lines ends
2396
2397 if (NbAreasKnCh) { // Areas
2398 if (debugFn)
2399 printf("No. of areas with known charges: %d\n", NbAreasKnCh);
2400
2401 FILE *fptrAreaKnChFile = fopen(AreaKnChFile, "r");
2402 if (fptrAreaKnChFile == NULL) {
2403 neBEMMessage("AreaKnCh file absent ... returning\n");
2404 return -10;
2405 }
2406
2407 AreaKnChArr =
2408 (AreaKnCh *)malloc((NbAreasKnCh + 1) * sizeof(AreaKnCh));
2409
2410 for (int area = 0; area <= NbAreasKnCh; ++area) {
2411 // CHECK!!! ele limits start from 0, but all else from 1 to ...
2412 AreaKnChArr[area].Nb = 0;
2413 AreaKnChArr[area].NbVertices = 0;
2414 for (int vert = 1; vert <= (AreaKnChArr + area - 1)->NbVertices;
2415 ++vert) {
2416 (AreaKnChArr + area - 1)->Vertex[vert].X = 0.0;
2417 (AreaKnChArr + area - 1)->Vertex[vert].Y = 0.0;
2418 (AreaKnChArr + area - 1)->Vertex[vert].Z = 0.0;
2419 }
2420 AreaKnChArr[area].Assigned = 0.0;
2421 }
2422
2423 char header[256];
2424 fgets(header, 256, fptrAreaKnChFile); // header
2425
2426 for (int area = 1; area <= NbAreasKnCh; ++area) {
2427 fscanf(fptrAreaKnChFile, "%d %d %le\n",
2428 &(AreaKnChArr + area - 1)->Nb,
2429 &(AreaKnChArr + area - 1)->NbVertices,
2430 &(AreaKnChArr + area - 1)->Assigned);
2431 for (int vert = 1; vert <= (AreaKnChArr + area - 1)->NbVertices;
2432 ++vert) {
2433 fscanf(fptrAreaKnChFile, "%le %le %le\n",
2434 &(AreaKnChArr + area - 1)->Vertex[vert].X,
2435 &(AreaKnChArr + area - 1)->Vertex[vert].Y,
2436 &(AreaKnChArr + area - 1)->Vertex[vert].Z);
2437 }
2438
2439 for (int vert = 1; vert <= (AreaKnChArr + area - 1)->NbVertices;
2440 ++vert) { // cm to m
2441 (AreaKnChArr + area - 1)->Vertex[vert].X /= LScaleFactor;
2442 (AreaKnChArr + area - 1)->Vertex[vert].Y /= LScaleFactor;
2443 (AreaKnChArr + area - 1)->Vertex[vert].Z /= LScaleFactor;
2444 }
2445 AreaKnChArr[area].Assigned *=
2446 (LScaleFactor * LScaleFactor); // cm^2 to m^2
2447 AreaKnChArr[area].Assigned *= KnChFactor;
2448 }
2449
2450 fclose(fptrAreaKnChFile);
2451 if (debugFn) printf("done for all areas\n");
2452 } // if AreasKnCh: Inputs and calculations for areas ends
2453
2454 if (NbVolumesKnCh) { // Volumes
2455 if (debugFn)
2456 printf("No. of volumes with known charges: %d\n", NbVolumesKnCh);
2457
2458 FILE *fptrVolumeKnChFile = fopen(VolumeKnChFile, "r");
2459 if (fptrVolumeKnChFile == NULL) {
2460 neBEMMessage("VolumeKnCh file absent ... returning\n");
2461 return -10;
2462 }
2463
2465 (VolumeKnCh *)malloc((NbVolumesKnCh + 1) * sizeof(VolumeKnCh));
2466
2467 for (int volume = 0; volume <= NbVolumesKnCh; ++volume) {
2468 // CHECK!!! ele limits start from 0, but all else from 1 to ...
2469 VolumeKnChArr[volume].Nb = 0;
2470 VolumeKnChArr[volume].NbVertices = 0;
2471 for (int vert = 1; vert <= (VolumeKnChArr + volume - 1)->NbVertices;
2472 ++vert) {
2473 (VolumeKnChArr + volume - 1)->Vertex[vert].X = 0.0;
2474 (VolumeKnChArr + volume - 1)->Vertex[vert].Y = 0.0;
2475 (VolumeKnChArr + volume - 1)->Vertex[vert].Z = 0.0;
2476 }
2477 VolumeKnChArr[volume].Assigned *=
2478 (LScaleFactor * LScaleFactor * LScaleFactor); // cm^3 to m^3
2479 VolumeKnChArr[volume].Assigned = 0.0;
2480 }
2481
2482 char header[256];
2483 fgets(header, 256, fptrVolumeKnChFile); // header
2484
2485 for (int volume = 1; volume <= NbVolumesKnCh; ++volume) {
2486 fscanf(fptrVolumeKnChFile, "%d %d %le\n",
2487 &(VolumeKnChArr + volume - 1)->Nb,
2488 &(VolumeKnChArr + volume - 1)->NbVertices,
2489 &(VolumeKnChArr + volume - 1)->Assigned);
2490 for (int vert = 1; vert <= (VolumeKnChArr + volume - 1)->NbVertices;
2491 ++vert) {
2492 fscanf(fptrVolumeKnChFile, "%le %le %le\n",
2493 &(VolumeKnChArr + volume - 1)->Vertex[vert].X,
2494 &(VolumeKnChArr + volume - 1)->Vertex[vert].Y,
2495 &(VolumeKnChArr + volume - 1)->Vertex[vert].Z);
2496 }
2497
2498 for (int vert = 1; vert <= (VolumeKnChArr + volume - 1)->NbVertices;
2499 ++vert) { // cm to m
2500 (VolumeKnChArr + volume - 1)->Vertex[vert].X /= LScaleFactor;
2501 (VolumeKnChArr + volume - 1)->Vertex[vert].Y /= LScaleFactor;
2502 (VolumeKnChArr + volume - 1)->Vertex[vert].Z /= LScaleFactor;
2503 }
2504 VolumeKnChArr[volume].Assigned *= KnChFactor;
2505 }
2506
2507 fclose(fptrVolumeKnChFile);
2508 if (debugFn) printf("done for all volumes\n");
2509 } // if NbVolumesKnCh: Inputs and calculations for volumes ends
2510
2511 } // if OptKnCh
2512
2513 fclose(KnChInpFile);
2514 } // else KnChInpFile
2515 } // parameters related to known charge calculations
2516
2517 return (0);
2518} // InitKnownCharges ends
2519
2520// It is quite possible that the elements had a charge assgined to them
2521// even before they are being considered for getting charged up.
2522// Moreover, following the sequence in which the algorithm has been developed,
2523// the same element accumulates the available electrons and then the ions.
2524// The resultant of all three (prior charge, electrons and ions) turns out
2525// to be the assigned charge on the elements, after the execution of this
2526// function.
2528 int debugFn = 0;
2529
2530 // status of elements before being charged up
2531 if (debugFn) {
2532 for (int ele = 1; ele <= NbElements; ++ele) {
2533 printf("ele, Assigned charge: %d, %lg\n", ele,
2534 (EleArr + ele - 1)->Assigned);
2535 }
2536 }
2537
2538 // Set up parameters related to charging-up calculations
2539 // The plan is to distribute the electrons and ions ending in dielectric
2540 // volumes to the elements on the volumes
2541 {
2542 FILE *ChargingUpInpFile = fopen("neBEMInp/neBEMChargingUp.inp", "r");
2543 if (ChargingUpInpFile == NULL) {
2544 printf(
2545 "neBEMChargingUp.inp absent ... assuming no charging up effect "
2546 "...\n");
2547 // assign NbChUpEEle and NbChUpIEle and Prims to be zeros?
2548 } else {
2549 fscanf(ChargingUpInpFile, "OptChargingUp: %d\n", &OptChargingUp);
2550 if (!OptChargingUp)
2551 printf("OptChargingUp = 0 ... assuming no charging up effect ...\n");
2552 if (1) printf("OptChargingUp: %d\n", OptChargingUp);
2553
2554 if (OptChargingUp) {
2555 char ChargingUpEFile[256];
2556 char ChargingUpIFile[256];
2557 double LScaleFactor;
2558 double ChUpFactor;
2559
2560 fscanf(ChargingUpInpFile, "ChargingUpEFile: %s\n", ChargingUpEFile);
2561 fscanf(ChargingUpInpFile, "ChargingUpIFile: %s\n", ChargingUpIFile);
2562 fscanf(ChargingUpInpFile, "LScaleFactor: %lg\n", &LScaleFactor);
2563 fscanf(ChargingUpInpFile, "ChUpFactor: %lg\n", &ChUpFactor);
2564 if (1) {
2565 printf("ChargingUpEFile: %s\n", ChargingUpEFile);
2566 printf("ChargingUpIFile: %s\n", ChargingUpIFile);
2567 printf("LScaleFactor: %lg\n", LScaleFactor);
2568 printf("ChUpFactor: %lg\n", ChUpFactor);
2569 }
2570
2571 { // Calculation for electrons
2572 FILE *fptrChargingUpEFile = fopen(ChargingUpEFile, "r");
2573 if (fptrChargingUpEFile == NULL) {
2574 neBEMMessage("ChargingUpE file absent ... returning\n");
2575 fclose(ChargingUpInpFile);
2576 return -10;
2577 }
2578 int NbOfE = neBEMGetNbOfLines(ChargingUpEFile);
2579 if (NbOfE <= 1) {
2580 neBEMMessage("Too few lines in ChargingUpE ... returning\n");
2581 fclose(fptrChargingUpEFile);
2582 return -11;
2583 }
2584 // initialize
2585 int* NbChUpEonEle = (int *)malloc((NbElements + 1) * sizeof(int));
2586 for (int ele = 0; ele <= NbElements; ++ele) {
2587 // CHECK!!! ele limits start from 0, but all else from 1 to ...
2588 NbChUpEonEle[ele] = 0;
2589 }
2590
2591 // read the header line
2592 char header[256];
2593 fgets(header, 256, fptrChargingUpEFile);
2594
2595 --NbOfE; // one line was for the header
2596 if (debugFn) printf("No. of electrons: %d\n", NbOfE);
2597 char tmpEFile[256];
2598 strcpy(tmpEFile, "/tmp/ElectronTempFile.out");
2599 FILE *ftmpEF = fopen(tmpEFile, "w");
2600 if (ftmpEF == NULL) {
2601 printf("cannot open temporary output file ... returning ...\n");
2602 free(NbChUpEonEle);
2603 return -100;
2604 }
2605 FILE *fPtEChUpMap = fopen("PtEChUpMap.out", "w");
2606 if (fPtEChUpMap == NULL) {
2607 printf("cannot open PtEChUpMap.out file for writing ...\n");
2608 fclose(ftmpEF);
2609 return 110;
2610 }
2611
2612 char label;
2613 int vol, enb; // label, volume and electron number
2614 double xlbend, ylbend, zlbend, xend, yend,
2615 zend; // lbend == Last But END
2616 Point3D
2617 ptintsct; // each electron likely to have an intersection point
2618 for (int electron = 1; electron <= NbOfE; ++electron) {
2619 fscanf(fptrChargingUpEFile, "%c %d %d %lg %lg %lg %lg %lg %lg\n",
2620 &label, &vol, &enb, &xlbend, &xend, &ylbend, &yend, &zlbend,
2621 &zend);
2622 xlbend /= LScaleFactor; // cm to metre
2623 xend /= LScaleFactor; // and similar other
2624 ylbend /= LScaleFactor;
2625 yend /= LScaleFactor;
2626 zlbend /= LScaleFactor;
2627 zend /= LScaleFactor;
2628 ptintsct.X = 0.0;
2629 ptintsct.Y = 0.0;
2630 ptintsct.Z = 0.0; // initialize
2631
2632 // find the parametric equation of this last segment
2633 // if xend < xlbend, swap the directions
2634 // This has not been mentioned as mandatory in Vince's book
2635 // "Geometry for Computer Graphics", but implied in the book "A
2636 // Programmer's Geometry"
2637 if (xend < xlbend) // not implemented now
2638 {
2639 }
2640 double lseg = (xend - xlbend) * (xend - xlbend) +
2641 (yend - ylbend) * (yend - ylbend) +
2642 (zend - zlbend) * (zend - zlbend);
2643 lseg = sqrt(lseg);
2644 double xgrd =
2645 (xend - xlbend) / lseg; // normalized direction vector
2646 double ygrd = (yend - ylbend) / lseg;
2647 double zgrd = (zend - zlbend) / lseg;
2648 if (debugFn) {
2649 printf("\nelectron: %d\n", electron);
2650 printf("xlbend: %lg, ylbend: %lg, zlbend: %lg\n", xlbend, ylbend,
2651 zlbend);
2652 printf("xend: %lg, yend: %lg, zend: %lg\n", xend, yend, zend);
2653 printf("xgrd: %lg, ygrd: %lg, zgrd: %lg\n", xgrd, ygrd, zgrd);
2654 fprintf(ftmpEF, "#e: %d, label: %c, vol: %d\n", electron, label,
2655 vol);
2656 fprintf(ftmpEF, "%lg %lg %lg\n", xlbend, ylbend, zlbend);
2657 fprintf(ftmpEF, "%lg %lg %lg\n", xend, yend, zend);
2658 fprintf(ftmpEF, "#xgrd: %lg, ygrd: %lg, zgrd: %lg\n", xgrd, ygrd,
2659 zgrd);
2660 fprintf(ftmpEF, "\n");
2661 }
2662
2663 // determine which element gets this electron
2664 // At present, the logic is as follow:
2665 // Using the information on the last segment, find out which
2666 // primitive is pierced by it and at which point From the
2667 // intersection point, find out the element number on the primitive
2668 // in a local sense Using the information (start and end elements of
2669 // a given primitive) identify the element in a global sense. This
2670 // approach should be lot more efficient than checking intersection
2671 // element by element.
2672 // The intersection point is computed following algorithm
2673 // implemented in a matlab code (plane_imp_line_par_int_3d.m) Also
2674 // check which primitive in the list is the closet to the end point
2675
2676 double SumOfAngles;
2677 int PrimIntsctd = -1,
2678 EleIntsctd = -1; // intersected primitive & element
2679 int nearestprim = -1; // absurd value
2680 double dist = 1.0e6, mindist = 1.0e6; // absurdly high numbers
2681 // check all primitives
2682 for (int prim = 1; prim <= NbPrimitives; ++prim) {
2683 if (InterfaceType[prim] != 4)
2684 continue; // primitive not a dielectric
2685
2686 int intersect = 0, extrasect = 1; // worst of conditions
2687 int InPrim = 0, InEle = 0;
2688 if (debugFn)
2689 printf("prim: %d, mindist: %lg, nearestprim: %d\n", prim,
2690 mindist, nearestprim);
2691
2692 // Use two nodes at a time to get two independent vectors on
2693 // primitive Get cross-product of these two vector - normal to the
2694 // plane Note that the normal is already associated with the
2695 // primitive of type 3 and 4; 2 is wire and does not have any
2696 // associated normal
2697 if ((PrimType[prim] == 3) || (PrimType[prim] == 4)) {
2698 if (debugFn) {
2699 printf("prim: %d\n", prim);
2700 printf("vertex0: %lg, %lg, %lg\n", XVertex[prim][0],
2701 YVertex[prim][0], ZVertex[prim][0]);
2702 printf("vertex1: %lg, %lg, %lg\n", XVertex[prim][1],
2703 YVertex[prim][1], ZVertex[prim][1]);
2704 printf("vertex2: %lg, %lg, %lg\n", XVertex[prim][2],
2705 YVertex[prim][2], ZVertex[prim][2]);
2706 if (PrimType[prim] == 4) {
2707 printf("vertex3: %lg, %lg, %lg\n", XVertex[prim][3],
2708 YVertex[prim][3], ZVertex[prim][3]);
2709 }
2710 fprintf(ftmpEF, "#prim: %d\n", prim);
2711 fprintf(ftmpEF, "%lg %lg %lg\n", XVertex[prim][0],
2712 YVertex[prim][0], ZVertex[prim][0]);
2713 fprintf(ftmpEF, "%lg %lg %lg\n", XVertex[prim][1],
2714 YVertex[prim][1], ZVertex[prim][1]);
2715 fprintf(ftmpEF, "%lg %lg %lg\n", XVertex[prim][2],
2716 YVertex[prim][2], ZVertex[prim][2]);
2717 if (PrimType[prim] == 4) {
2718 fprintf(ftmpEF, "%lg %lg %lg\n", XVertex[prim][3],
2719 YVertex[prim][3], ZVertex[prim][3]);
2720 }
2721 fprintf(ftmpEF, "%lg %lg %lg\n", XVertex[prim][0],
2722 YVertex[prim][0], ZVertex[prim][0]);
2723 fprintf(ftmpEF, "\n");
2724 fflush(stdout);
2725 } // debugFn
2726
2727 // use a, b, c (normal is ai + bj + ck) at one of the nodes to
2728 // get d ax + by + cz + d = 0 is the equation of the plane
2729 double a = XNorm[prim];
2730 double b = YNorm[prim];
2731 double c = ZNorm[prim];
2732 double d = -a * XVertex[prim][0] - b * YVertex[prim][0] -
2733 c * ZVertex[prim][0];
2734
2735 // distance of the end point to this primitve is
2736 dist = (xend * a + yend * b + zend * c + d) /
2737 sqrt(a * a + b * b + c * c);
2738 dist = fabs(dist); // if only magnitude is required
2739 if (prim == 1) {
2740 mindist = dist;
2741 nearestprim = prim;
2742 }
2743 if ((prim == 1) && debugFn)
2744 printf(
2745 "after prim == 1 check mindist: %lg, nearestprim: %d\n",
2746 mindist, nearestprim);
2747
2748 // Point of intersection
2749 // Algo as on p62 (pdf 81) of Vince - Geometry for Computer
2750 // Graphics 1.5.13 Intersection of a line and a plane Algorithm
2751 // as implemented in plne_imp_line_par_int_3d.m a (nx), b (ny),
2752 // c (nz), d are a, b, c, d vx, vy, vz are xgrd, ygrd and zgrd
2753 // tx, ty, tz are xlbend, ylbend, zlbend
2754 // In the present case, n and v are unit vectors
2755 double norm1 = sqrt(a * a + b * b + c * c);
2756 double norm2 = sqrt(xgrd * xgrd + ygrd * ygrd + zgrd * zgrd);
2757 double denom =
2758 a * xgrd + b * ygrd + c * zgrd; // (vec)n.(vec)v; if 0, ||
2759 double tol =
2760 1.0e-16; // CHECK: -8 in original code; sizes small here
2761 intersect = extrasect = 0;
2762
2763 if (debugFn) {
2764 printf("a, b, c, d, dist: %lg, %lg, %lg, %lg, %lg\n", a, b, c,
2765 d, dist);
2766 printf("vector n: ai + bj + ck\n");
2767 printf("vector v: xgrd, ygrd, zgrd: %lg, %lg, %lg\n", xgrd,
2768 ygrd, zgrd);
2769 printf("norm1, norm2, (vec n . vec v) denom: %lg, %lg, %lg\n",
2770 norm1, norm2, denom);
2771 printf("if vec n . vec v == 0, line and plane parallel\n");
2772 fflush(stdout);
2773 }
2774
2775 if (fabs(denom) < tol * norm1 * norm2) {
2776 // line parallel to the plane
2777 if (fabs(a * xlbend + b * ylbend + c * zlbend + d) <=
2778 1.0e-16) { // CHECK: was == 0.0 in original code
2779 intersect = 1;
2780 extrasect = 0; // line ends on the plane
2781 ptintsct.X = xlbend;
2782 ptintsct.Y = ylbend;
2783 ptintsct.Z = zlbend;
2784 } else {
2785 intersect = 0;
2786 extrasect = 1; // both wrong
2787 ptintsct.X = 0.0; // Wrong to assign 0 values
2788 ptintsct.Y =
2789 0.0; // However, they are never going to be used
2790 ptintsct.Z = 0.0; // since intersect is 0
2791 }
2792 if (debugFn) {
2793 printf("line and plane parallel ...\n");
2794 printf("intersect: %d, extrasect: %d\n", intersect,
2795 extrasect);
2796 printf("intersection point: %lg, %lg, %lg\n", ptintsct.X,
2797 ptintsct.Y, ptintsct.Z);
2798 } // if line and plane are parallel
2799 } else { // if they are not parallel, they must intersect
2800 intersect = 1;
2801 double t =
2802 -(a * xlbend + b * ylbend + c * zlbend + d) / denom;
2803
2804 // check whether t is less than the length of the segment
2805 // and in the correct direction
2806 // If not, then an extrapolated intersection is not of
2807 // interest
2808 if ((t < 0.0) ||
2809 (fabs(t) > fabs(lseg))) // wrong dirn or beyond end
2810 {
2811 extrasect = 1;
2812 ptintsct.X = xlbend + t * xgrd;
2813 ptintsct.Y = ylbend + t * ygrd;
2814 ptintsct.Z = zlbend + t * zgrd;
2815 } else {
2816 extrasect = 0;
2817 ptintsct.X = xlbend + t * xgrd;
2818 ptintsct.Y = ylbend + t * ygrd;
2819 ptintsct.Z = zlbend + t * zgrd;
2820 }
2821 if (debugFn) {
2822 printf("line and plane NOT parallel ...\n");
2823 printf("intersect: %d, extrasect: %d\n", intersect,
2824 extrasect);
2825 printf("intersection point: %lg, %lg, %lg\n", ptintsct.X,
2826 ptintsct.Y, ptintsct.Z);
2827 printf("t, lseg: %lg, %lg\n", t, lseg);
2828 printf(
2829 "for an interesting intersection, lseg > t > 0.0 "
2830 "...\n\n");
2831 fflush(stdout);
2832 } // must intersect
2833 } // if not parallel
2834 } // if PrimType is 3 or 4
2835 else { // this is a wire primitive - assume no charging up issues
2836 dist = -1.0; // an absurd negative distance
2837 intersect = 0;
2838 extrasect = 0;
2839 continue;
2840 } // else PrimType 3 or 4
2841
2842 if (dist < mindist) {
2843 mindist = dist;
2844 nearestprim = prim;
2845 }
2846 if (debugFn)
2847 printf("nearestprim: %d, mindist: %lg\n\n", nearestprim,
2848 mindist);
2849
2850 // implicit assumption: the first primitive that gets pierced by
2851 // the ray is the one that we want. There can be other primitives
2852 // that are pierced by the same ray. So, this logic should be
2853 // refined further
2854 if ((intersect == 1) && (extrasect == 0)) {
2855 // check whether the intersection point is within primitive
2856 // polygon
2857 int nvert = PrimType[prim];
2858 Point3D polynode[4];
2859 polynode[0].X = XVertex[prim][0];
2860 polynode[0].Y = YVertex[prim][0];
2861 polynode[0].Z = ZVertex[prim][0];
2862 polynode[1].X = XVertex[prim][1];
2863 polynode[1].Y = YVertex[prim][1];
2864 polynode[1].Z = ZVertex[prim][1];
2865 polynode[2].X = XVertex[prim][2];
2866 polynode[2].Y = YVertex[prim][2];
2867 polynode[2].Z = ZVertex[prim][2];
2868 if (PrimType[prim] == 4) {
2869 polynode[3].X = XVertex[prim][3];
2870 polynode[3].Y = YVertex[prim][3];
2871 polynode[3].Z = ZVertex[prim][3];
2872 }
2873 // printf("neBEMChkInPoly for primitive %d\n", prim);
2874 SumOfAngles = neBEMChkInPoly(nvert, polynode, ptintsct);
2875 if (fabs(fabs(SumOfAngles) - neBEMtwopi) <= 1.0e-8) {
2876 InPrim = 1;
2877 PrimIntsctd = prim;
2878 }
2879 if (debugFn) {
2880 // print polynode and InPrim
2881 printf("Prim: %d\n", prim);
2882 printf("ptintsct: %lg, %lg, %lg\n", ptintsct.X, ptintsct.Y,
2883 ptintsct.Z);
2884 printf("nvert: %d\n", nvert);
2885 printf("polynode0: %lg, %lg, %lg\n", polynode[0].X,
2886 polynode[0].Y, polynode[0].Z);
2887 printf("polynode1: %lg, %lg, %lg\n", polynode[1].X,
2888 polynode[1].Y, polynode[1].Z);
2889 printf("polynode2: %lg, %lg, %lg\n", polynode[2].X,
2890 polynode[2].Y, polynode[2].Z);
2891 if (nvert == 4) {
2892 printf("polynode3: %lg, %lg, %lg\n", polynode[3].X,
2893 polynode[3].Y, polynode[3].Z);
2894 }
2895 printf("SumOfAngles: %lg, InPrim: %d\n", SumOfAngles, InPrim);
2896 fflush(stdout);
2897 }
2898
2899 if (!InPrim && (prim != NbPrimitives)) {
2900 continue; // check next primitive
2901 }
2902
2903 // Once identified, check in which element belonging to this
2904 // primitive contains the point of intersection
2905 if (InPrim) {
2906 InEle = 0;
2907 for (int ele = ElementBgn[prim]; ele <= ElementEnd[prim];
2908 ++ele) {
2909 nvert = 0;
2910 if ((EleArr + ele - 1)->G.Type == 3) nvert = 3;
2911 if ((EleArr + ele - 1)->G.Type == 4) nvert = 4;
2912 if (!nvert) {
2914 "no vertex in element! ... neBEMKnownCharges ...\n");
2915 fclose(fPtEChUpMap);
2916 return -20;
2917 }
2918
2919 polynode[0].X = (EleArr + ele - 1)->G.Vertex[0].X;
2920 polynode[0].Y = (EleArr + ele - 1)->G.Vertex[0].Y;
2921 polynode[0].Z = (EleArr + ele - 1)->G.Vertex[0].Z;
2922 polynode[1].X = (EleArr + ele - 1)->G.Vertex[1].X;
2923 polynode[1].Y = (EleArr + ele - 1)->G.Vertex[1].Y;
2924 polynode[1].Z = (EleArr + ele - 1)->G.Vertex[1].Z;
2925 polynode[2].X = (EleArr + ele - 1)->G.Vertex[2].X;
2926 polynode[2].Y = (EleArr + ele - 1)->G.Vertex[2].Y;
2927 polynode[2].Z = (EleArr + ele - 1)->G.Vertex[2].Z;
2928 if (nvert == 4) {
2929 polynode[3].X = (EleArr + ele - 1)->G.Vertex[3].X;
2930 polynode[3].Y = (EleArr + ele - 1)->G.Vertex[3].Y;
2931 polynode[3].Z = (EleArr + ele - 1)->G.Vertex[3].Z;
2932 }
2933
2934 // printf("neBEMChkInPoly for element %d\n", ele);
2935 SumOfAngles = neBEMChkInPoly(nvert, polynode, ptintsct);
2936 if (fabs(fabs(SumOfAngles) - neBEMtwopi) <= 1.0e-8)
2937 InEle = 1;
2938 if (debugFn) {
2939 // print polynode and InEle
2940 printf("Ele: %d\n", ele);
2941 printf("ptintsct: %lg, %lg, %lg\n", ptintsct.X,
2942 ptintsct.Y, ptintsct.Z);
2943 printf("nvert: %d\n", nvert);
2944 printf("polynode0: %lg, %lg, %lg\n", polynode[0].X,
2945 polynode[0].Y, polynode[0].Z);
2946 printf("polynode1: %lg, %lg, %lg\n", polynode[1].X,
2947 polynode[1].Y, polynode[1].Z);
2948 printf("polynode2: %lg, %lg, %lg\n", polynode[2].X,
2949 polynode[2].Y, polynode[2].Z);
2950 if (nvert == 4) {
2951 printf("polynode3: %lg, %lg, %lg\n", polynode[3].X,
2952 polynode[3].Y, polynode[3].Z);
2953 }
2954 printf("SumOfAngles: %lg, InEle: %d\n", SumOfAngles,
2955 InEle);
2956 fflush(stdout);
2957 }
2958 if (InEle) {
2959 ptintsct.X = (EleArr + ele - 1)->G.Origin.X;
2960 ptintsct.Y = (EleArr + ele - 1)->G.Origin.Y;
2961 ptintsct.Z = (EleArr + ele - 1)->G.Origin.Z;
2962 // Associate this electron to the identified element
2963 EleIntsctd = ele;
2964 NbChUpEonEle[ele]++;
2965 fprintf(fPtEChUpMap, "%d %lg %lg %lg %d %d %d %d\n",
2966 electron, ptintsct.X, ptintsct.Y, ptintsct.Z,
2967 prim, InPrim, ele, InEle);
2968
2969 if (debugFn) {
2970 printf("# electron: %d\n", electron);
2971 printf("%lg %lg %lg\n", xlbend, ylbend, zlbend);
2972 printf("%lg %lg %lg\n", xend, yend, zend);
2973 printf("%lg, %lg, %lg\n", ptintsct.X, ptintsct.Y,
2974 ptintsct.Z);
2975 printf("# Associated primitive: %d\n", prim);
2976 printf(
2977 "# Associated element and origin: %d, %lg, %lg, "
2978 "%lg\n",
2979 ele, (EleArr + ele - 1)->G.Origin.X,
2980 (EleArr + ele - 1)->G.Origin.Y,
2981 (EleArr + ele - 1)->G.Origin.Z);
2982 printf("#NbChUpEonEle on element: %d\n",
2983 NbChUpEonEle[ele]);
2984 fprintf(ftmpEF, "#Element: %d\n", ele);
2985 fprintf(ftmpEF, "%lg %lg %lg\n", polynode[0].X,
2986 polynode[0].Y, polynode[0].Z);
2987 fprintf(ftmpEF, "%lg %lg %lg\n", polynode[1].X,
2988 polynode[1].Y, polynode[1].Z);
2989 fprintf(ftmpEF, "%lg %lg %lg\n", polynode[2].X,
2990 polynode[2].Y, polynode[2].Z);
2991 if (nvert == 4) {
2992 fprintf(ftmpEF, "%lg %lg %lg\n", polynode[3].X,
2993 polynode[3].Y, polynode[3].Z);
2994 }
2995 fprintf(ftmpEF, "%lg %lg %lg\n", polynode[0].X,
2996 polynode[0].Y, polynode[0].Z);
2997 fprintf(ftmpEF, "\n");
2998 fflush(stdout);
2999 }
3000 break; // desired element has been found!
3001 }
3002 } // for all elements on this primitive
3003
3004 if (InEle)
3005 break;
3006 else {
3008 "Element not identified ... neBEMKnownCharges\n");
3009 return -2;
3010 }
3011 } // if InPrim
3012 } // if intersection and no extrasection
3013
3014 if ((InPrim) && (intersect) && (!extrasect) &&
3015 (InEle)) // all satisfied
3016 break; // do not check any further primtive for this electron
3017
3018 // If, after checking all the primitives, no interstion is found
3019 // valid
3020 if (prim ==
3021 (NbPrimitives)) // end of the list and no intersection
3022 {
3023 int nvert;
3024 Point3D polynode[4];
3025 int nearestele = ElementBgn[nearestprim];
3026 double distele = 1.0e6,
3027 mindistele = 1.0e6; // absurdly high value
3028
3029 if (debugFn) {
3030 printf("prim == (NbPrimitives) ... checking nearest ...\n");
3031 printf("nearestprim: %d, mindist: %lg\n", nearestprim,
3032 mindist);
3033 }
3034
3035 if (mindist <= 10.0e-6) {
3036 PrimIntsctd = nearestprim;
3037 InPrim = 1;
3038 } else {
3039 InPrim = 0;
3040 InEle = 0;
3041 break;
3042 }
3043
3044 for (int ele = ElementBgn[nearestprim]; // check all elements
3045 ele <= ElementEnd[nearestprim]; ++ele) {
3046 nvert = 0;
3047 if ((EleArr + ele - 1)->G.Type == 3) nvert = 3;
3048 if ((EleArr + ele - 1)->G.Type == 4) nvert = 4;
3049 if (!nvert) {
3051 "no vertex element! ... neBEMKnownCharges ...\n");
3052 return -20;
3053 }
3054
3055 /*
3056 polynode[0].X = (EleArr+ele-1)->G.Vertex[0].X;
3057 polynode[0].Y = (EleArr+ele-1)->G.Vertex[0].Y;
3058 polynode[0].Z = (EleArr+ele-1)->G.Vertex[0].Z;
3059 polynode[1].X = (EleArr+ele-1)->G.Vertex[1].X;
3060 polynode[1].Y = (EleArr+ele-1)->G.Vertex[1].Y;
3061 polynode[1].Z = (EleArr+ele-1)->G.Vertex[1].Z;
3062 polynode[2].X = (EleArr+ele-1)->G.Vertex[2].X;
3063 polynode[2].Y = (EleArr+ele-1)->G.Vertex[2].Y;
3064 polynode[2].Z = (EleArr+ele-1)->G.Vertex[2].Z;
3065 if(nvert == 4)
3066 {
3067 polynode[3].X = (EleArr+ele-1)->G.Vertex[3].X;
3068 polynode[3].Y = (EleArr+ele-1)->G.Vertex[3].Y;
3069 polynode[3].Z = (EleArr+ele-1)->G.Vertex[3].Z;
3070 }
3071
3072 Vector3D v01, v12, elenorm, unitelenorm;
3073 v01.X = polynode[1].X - polynode[0].X;
3074 v01.Y = polynode[1].Y - polynode[0].Y;
3075 v01.Z = polynode[1].Z - polynode[0].Z;
3076 v12.X = polynode[2].X - polynode[1].X;
3077 v12.Y = polynode[2].Y - polynode[1].Y;
3078 v12.Z = polynode[2].Z - polynode[1].Z;
3079 elenorm = Vector3DCrossProduct(&v01, &v12);
3080 unitelenorm = UnitVector3D(&elenorm);
3081
3082 if((nvert == 3) || (nvert == 4))
3083 {
3084 if(debugFn)
3085 {
3086 printf("nearestprim: %d, element: %d\n",
3087 nearestprim, ele); printf("vertex0: %lg, %lg, %lg\n", polynode[0].X,
3088 polynode[0].Y, polynode[0].Z); printf("vertex1: %lg, %lg, %lg\n",
3089 polynode[1].X, polynode[1].Y,
3090 polynode[1].Z); printf("vertex2: %lg, %lg, %lg\n", polynode[2].X,
3091 polynode[2].Y, polynode[2].Z); if(PrimType[prim] == 4)
3092 {
3093 printf("vertex3: %lg, %lg, %lg\n",
3094 polynode[3].X, polynode[3].Y,
3095 polynode[3].Z);
3096 }
3097 fprintf(ftmpEF, "#nearestprim: %d, element:
3098 %d\n", nearestprim, ele); fprintf(ftmpEF, "%lg %lg %lg\n", polynode[0].X,
3099 polynode[0].Y, polynode[0].Z); fprintf(ftmpEF, "%lg %lg %lg\n", polynode[1].X,
3100 polynode[1].Y, polynode[1].Z); fprintf(ftmpEF, "%lg %lg %lg\n", polynode[2].X,
3101 polynode[2].Y, polynode[2].Z); if(PrimType[prim] == 4)
3102 {
3103 fprintf(ftmpEF, "%lg %lg %lg\n",
3104 polynode[3].X, polynode[3].Y,
3105 polynode[3].Z);
3106 }
3107 fprintf(ftmpEF, "%lg %lg %lg\n",
3108 polynode[0].X, polynode[0].Y,
3109 polynode[0].Z); fprintf(ftmpEF, "\n"); fflush(stdout); } // debugFn
3110
3111 // use a, b, c (normal is ai + bj + ck) at one of the nodes to get d
3112 // ax + by + cz + d = 0 is the equation of the plane
3113 double a = unitelenorm.X;
3114 double b = unitelenorm.Y;
3115 double c = unitelenorm.Z;
3116 double d = - a*polynode[0].X - b*polynode[0].Y
3117 -
3118 c*polynode[0].Z;
3119
3120 // distance of the end point to this primitve is
3121 distele = (xend*a + yend*b + zend*c + d)
3122 / sqrt(a*a + b*b + c*c);
3123 distele = fabs(distele); // if only magnitude is
3124 required
3125 */
3126
3127 Vector3D eleOrigin;
3128 eleOrigin.X = (EleArr + ele - 1)->G.Origin.X;
3129 eleOrigin.Y = (EleArr + ele - 1)->G.Origin.Y;
3130 eleOrigin.Z = (EleArr + ele - 1)->G.Origin.Z;
3131 distele = (eleOrigin.X - xend) * (eleOrigin.X - xend) +
3132 (eleOrigin.Y - yend) * (eleOrigin.Y - yend) +
3133 (eleOrigin.Z - zend) * (eleOrigin.Z - zend);
3134 distele = sqrt(distele);
3135
3136 if (ele == ElementBgn[nearestprim]) {
3137 mindistele = distele;
3138 nearestele = ele;
3139 }
3140 if (distele < mindistele) {
3141 mindistele = distele;
3142 nearestele = ele;
3143 }
3144
3145 if (debugFn) {
3146 // printf("a, b, c, d, dist: %lg, %lg, %lg, %lg, %lg\n",
3147 // a, b, c, d, dist);
3148 // printf("vector n: ai + bj + ck\n");
3149 // printf("vector v: xgrd, ygrd, zgrd: %lg, %lg, %lg\n",
3150 // xgrd, ygrd, zgrd);
3151 printf(
3152 "distele: %lg, mindistele: %lg,from nearest ele "
3153 "origin: %d\n",
3154 distele, mindistele, nearestele);
3155 fflush(stdout);
3156 }
3157
3158 // } // if PrimType is 3 or 4
3159 } // for elements in nearestprim
3160
3161 // if(mindistele <= 10.0e-6)
3162 // {
3163 EleIntsctd = nearestele;
3164 InEle = 1;
3165 ptintsct.X = (EleArr + EleIntsctd - 1)->G.Origin.X;
3166 ptintsct.Y = (EleArr + EleIntsctd - 1)->G.Origin.Y;
3167 ptintsct.Z = (EleArr + EleIntsctd - 1)->G.Origin.Z;
3168 NbChUpEonEle[EleIntsctd]++;
3169
3170 fprintf(fPtEChUpMap, "%d %lg %lg %lg %d %d %d %d\n", electron,
3171 ptintsct.X, ptintsct.Y, ptintsct.Z, PrimIntsctd, InPrim,
3172 EleIntsctd, InEle);
3173 // } // if mindistele
3174
3175 if (debugFn) {
3176 printf("# electron: %d\n", electron);
3177 printf("%lg %lg %lg\n", xlbend, ylbend, zlbend);
3178 printf("%lg %lg %lg\n", xend, yend, zend);
3179 printf("%lg, %lg, %lg\n", ptintsct.X, ptintsct.Y, ptintsct.Z);
3180 printf("# Associated primitive: %d\n", PrimIntsctd);
3181 printf("# Associated element and origin: %d, %lg, %lg, %lg\n",
3182 EleIntsctd, (EleArr + EleIntsctd - 1)->G.Origin.X,
3183 (EleArr + EleIntsctd - 1)->G.Origin.Y,
3184 (EleArr + EleIntsctd - 1)->G.Origin.Z);
3185 printf("#NbChUpEonEle on element: %d\n",
3186 NbChUpEonEle[EleIntsctd]);
3187 fflush(stdout);
3188
3189 fprintf(ftmpEF, "#Element: %d\n", EleIntsctd);
3190 polynode[0].X = (EleArr + EleIntsctd - 1)->G.Vertex[0].X;
3191 polynode[0].Y = (EleArr + EleIntsctd - 1)->G.Vertex[0].Y;
3192 polynode[0].Z = (EleArr + EleIntsctd - 1)->G.Vertex[0].Z;
3193 polynode[1].X = (EleArr + EleIntsctd - 1)->G.Vertex[1].X;
3194 polynode[1].Y = (EleArr + EleIntsctd - 1)->G.Vertex[1].Y;
3195 polynode[1].Z = (EleArr + EleIntsctd - 1)->G.Vertex[1].Z;
3196 polynode[2].X = (EleArr + EleIntsctd - 1)->G.Vertex[2].X;
3197 polynode[2].Y = (EleArr + EleIntsctd - 1)->G.Vertex[2].Y;
3198 polynode[2].Z = (EleArr + EleIntsctd - 1)->G.Vertex[2].Z;
3199 if (nvert == 4) {
3200 polynode[3].X = (EleArr + EleIntsctd - 1)->G.Vertex[3].X;
3201 polynode[3].Y = (EleArr + EleIntsctd - 1)->G.Vertex[3].Y;
3202 polynode[3].Z = (EleArr + EleIntsctd - 1)->G.Vertex[3].Z;
3203 }
3204 fprintf(ftmpEF, "%lg %lg %lg\n", polynode[0].X, polynode[0].Y,
3205 polynode[0].Z);
3206 fprintf(ftmpEF, "%lg %lg %lg\n", polynode[1].X, polynode[1].Y,
3207 polynode[1].Z);
3208 fprintf(ftmpEF, "%lg %lg %lg\n", polynode[2].X, polynode[2].Y,
3209 polynode[2].Z);
3210 if (nvert == 4) {
3211 fprintf(ftmpEF, "%lg %lg %lg\n", polynode[3].X,
3212 polynode[3].Y, polynode[3].Z);
3213 }
3214 fprintf(ftmpEF, "%lg %lg %lg\n", polynode[0].X, polynode[0].Y,
3215 polynode[0].Z);
3216 fprintf(ftmpEF, "\n");
3217 } // debug
3218 } // if prim == NbPrimitives
3219
3220 } // for all primitives // just not those on the volume
3221
3222 if (debugFn)
3223 printf("writing file for checking electron positions\n");
3224
3225 if (debugFn) // check electron positions, volume primitives and
3226 // elements
3227 {
3228 char enbstr[12];
3229 snprintf(enbstr, 12, "%d", electron);
3230 char elecposdbg[256];
3231 strcpy(elecposdbg, "/tmp/Electron");
3232 strcat(elecposdbg, enbstr);
3233 strcat(elecposdbg, ".out");
3234 FILE *fepd = fopen(elecposdbg, "w");
3235 if (fepd == NULL) {
3236 printf(
3237 "cannot open writable file to debug electron positions "
3238 "...\n");
3239 printf("returning ...\n");
3240 return -111;
3241 }
3242 // write electron number, end, lbend, volume, primitive, elements,
3243 // intxn
3244 fprintf(fepd, "#electron: %d %d\n", enb,
3245 electron); // should print same
3246 fprintf(fepd, "#last but end position:\n");
3247 fprintf(fepd, "%lg %lg %lg\n", xlbend, ylbend, zlbend);
3248 fprintf(fepd, "#end position:\n");
3249 fprintf(fepd, "%lg %lg %lg\n\n", xend, yend, zend);
3250 fprintf(fepd, "#intersected primitive number: %d\n", PrimIntsctd);
3251 if (PrimIntsctd >= 1) {
3252 fprintf(fepd, "#PrimType: %d\n", PrimType[PrimIntsctd]);
3253 fprintf(fepd, "#prim vertices:\n");
3254 fprintf(fepd, "%lg %lg %lg\n", XVertex[PrimIntsctd][0],
3255 YVertex[PrimIntsctd][0], ZVertex[PrimIntsctd][0]);
3256 fprintf(fepd, "%lg %lg %lg\n", XVertex[PrimIntsctd][1],
3257 YVertex[PrimIntsctd][1], ZVertex[PrimIntsctd][1]);
3258 fprintf(fepd, "%lg %lg %lg\n", XVertex[PrimIntsctd][2],
3259 YVertex[PrimIntsctd][2], ZVertex[PrimIntsctd][2]);
3260 if (PrimType[PrimIntsctd] == 4) {
3261 fprintf(fepd, "%lg %lg %lg\n", XVertex[PrimIntsctd][3],
3262 YVertex[PrimIntsctd][3], ZVertex[PrimIntsctd][3]);
3263 }
3264 fprintf(fepd, "%lg %lg %lg\n", XVertex[PrimIntsctd][0],
3265 YVertex[PrimIntsctd][0], ZVertex[PrimIntsctd][0]);
3266 fprintf(fepd, "\n");
3267
3268 fprintf(fepd, "#ptintsct:\n");
3269 fprintf(fepd, "%lg %lg %lg\n", ptintsct.X, ptintsct.Y,
3270 ptintsct.Z);
3271 fprintf(fepd, "\n");
3272 }
3273 fprintf(fepd, "#intersected element number: %d\n", EleIntsctd);
3274 if (EleIntsctd >= 1) {
3275 int gtype = (EleArr + EleIntsctd - 1)->G.Type;
3276 fprintf(fepd, "#EleType: %d\n", gtype);
3277 fprintf(fepd, "#element vertices:\n");
3278 double x0 = (EleArr + EleIntsctd - 1)->G.Vertex[0].X;
3279 double y0 = (EleArr + EleIntsctd - 1)->G.Vertex[0].Y;
3280 double z0 = (EleArr + EleIntsctd - 1)->G.Vertex[0].Z;
3281 double x1 = (EleArr + EleIntsctd - 1)->G.Vertex[1].X;
3282 double y1 = (EleArr + EleIntsctd - 1)->G.Vertex[1].Y;
3283 double z1 = (EleArr + EleIntsctd - 1)->G.Vertex[1].Z;
3284 double x2 = (EleArr + EleIntsctd - 1)->G.Vertex[2].X;
3285 double y2 = (EleArr + EleIntsctd - 1)->G.Vertex[2].Y;
3286 double z2 = (EleArr + EleIntsctd - 1)->G.Vertex[2].Z;
3287 fprintf(fepd, "%lg %lg %lg\n", x0, y0, z0);
3288 fprintf(fepd, "%lg %lg %lg\n", x1, y1, z1);
3289 fprintf(fepd, "%lg %lg %lg\n", x2, y2, z2);
3290 if (gtype == 4) {
3291 double x3 = (EleArr + EleIntsctd - 1)->G.Vertex[3].X;
3292 double y3 = (EleArr + EleIntsctd - 1)->G.Vertex[3].Y;
3293 double z3 = (EleArr + EleIntsctd - 1)->G.Vertex[3].Z;
3294 fprintf(fepd, "%lg %lg %lg\n", x3, y3, z3);
3295 }
3296 fprintf(fepd, "%lg %lg %lg\n", x0, y0, z0);
3297 fprintf(fepd, "\n");
3298
3299 fprintf(fepd, "#ptintsct:\n");
3300 fprintf(fepd, "%lg %lg %lg\n", ptintsct.X, ptintsct.Y,
3301 ptintsct.Z);
3302 fprintf(fepd, "\n");
3303 }
3304
3305 fclose(fepd);
3306 } // if 1
3307 if (debugFn)
3308 printf("done writing file for checking electron positions\n");
3309 } // for all the electrons
3310 fclose(fPtEChUpMap);
3311 if (debugFn) printf("done for all electrons\n");
3312
3313 FILE *fEleEChUpMap = fopen("EleEChUpMap.out", "w");
3314 if (fEleEChUpMap == NULL) {
3315 printf("cannot open EleEChUpMap.out file for writing ...\n");
3316 return 111;
3317 }
3318 for (int ele = 1; ele <= NbElements; ++ele) {
3319 (EleArr + ele - 1)->Assigned +=
3320 ChUpFactor * Q_E * NbChUpEonEle[ele] / (EleArr + ele - 1)->G.dA;
3321 fprintf(fEleEChUpMap, "%d %lg %lg %lg %d %lg\n", ele,
3322 (EleArr + ele - 1)->G.Origin.X,
3323 (EleArr + ele - 1)->G.Origin.Y,
3324 (EleArr + ele - 1)->G.Origin.Z, NbChUpEonEle[ele],
3325 (EleArr + ele - 1)->Assigned);
3326 }
3327 fclose(fEleEChUpMap);
3328
3329 fclose(ftmpEF);
3330 free(NbChUpEonEle);
3331 } // Calculation for electrons ends
3332
3333 { // Calculation for ions
3334 FILE *fptrChargingUpIFile = fopen(ChargingUpIFile, "r");
3335 if (fptrChargingUpIFile == NULL) {
3336 neBEMMessage("ChargingUpI file absent ... returning\n");
3337 return -10;
3338 }
3339 int NbOfI = neBEMGetNbOfLines(ChargingUpIFile);
3340 if (NbOfI <= 1) {
3341 neBEMMessage("Too few lines in ChargingUpI ... returning\n");
3342 fclose(fptrChargingUpIFile);
3343 return -11;
3344 }
3345 // initialize
3346 int* NbChUpIonEle = (int *)malloc((NbElements + 1) * sizeof(int));
3347 for (int ele = 0; ele <= NbElements; ++ele) {
3348 // CHECK!!! ele limit starts from 0 but all other from 1 to ...
3349 NbChUpIonEle[ele] = 0;
3350 }
3351
3352 // read the header line
3353 char header[256];
3354 fgets(header, 256, fptrChargingUpIFile);
3355
3356 --NbOfI; // one line was for the header
3357 if (debugFn) printf("No. of ions: %d\n", NbOfI);
3358 char tmpIFile[256];
3359 strcpy(tmpIFile, "/tmp/IonTempFile.out");
3360 FILE *ftmpIF = fopen(tmpIFile, "w");
3361 if (ftmpIF == NULL) {
3362 printf("cannot open temporary ion output file ... returning ...\n");
3363 free(NbChUpIonEle);
3364 return -100;
3365 }
3366 FILE *fPtIChUpMap = fopen("PtIChUpMap.out", "w");
3367 if (fPtIChUpMap == NULL) {
3368 printf("cannot open PtIChUpMap.out file for writing ...\n");
3369 fclose(ftmpIF);
3370 return 110;
3371 }
3372
3373 char label;
3374 int inb, vol; // label, volume and ion number
3375 double xlbend, ylbend, zlbend, xend, yend,
3376 zend; // lbend == Last But END
3377 Point3D ptintsct; // each ion likely to have an intersection point
3378 for (int ion = 1; ion <= NbOfI; ++ion) {
3379 fscanf(fptrChargingUpIFile, "%c %d %d %lg %lg %lg %lg %lg %lg\n",
3380 &label, &vol, &inb, &xlbend, &xend, &ylbend, &yend, &zlbend,
3381 &zend);
3382 xlbend /= LScaleFactor; // cm to metre
3383 xend /= LScaleFactor; // and similar other
3384 ylbend /= LScaleFactor;
3385 yend /= LScaleFactor;
3386 zlbend /= LScaleFactor;
3387 zend /= LScaleFactor;
3388 ptintsct.X = 0.0;
3389 ptintsct.Y = 0.0;
3390 ptintsct.Z = 0.0; // initialize
3391
3392 // find the parametric equation of this last segment
3393 // if xend < xlbend, swap the directions
3394 // This has not been mentioned as mandatory in Vince's book
3395 // "Geometry for Computer Graphics", but implied in the book "A
3396 // Programmer's Geometry"
3397 if (xend < xlbend) // not implemented now
3398 {
3399 }
3400 double lseg = (xend - xlbend) * (xend - xlbend) +
3401 (yend - ylbend) * (yend - ylbend) +
3402 (zend - zlbend) * (zend - zlbend);
3403 lseg = sqrt(lseg);
3404 double xgrd =
3405 (xend - xlbend) / lseg; // normalized direction vector
3406 double ygrd = (yend - ylbend) / lseg;
3407 double zgrd = (zend - zlbend) / lseg;
3408 if (debugFn) {
3409 printf("\nion: %d\n", ion);
3410 printf("xlbend: %lg, ylbend: %lg, zlbend: %lg\n", xlbend, ylbend,
3411 zlbend);
3412 printf("xend: %lg, yend: %lg, zend: %lg\n", xend, yend, zend);
3413 printf("xgrd: %lg, ygrd: %lg, zgrd: %lg\n", xgrd, ygrd, zgrd);
3414 fprintf(ftmpIF, "#e: %d, label: %c, vol: %d\n", ion, label, vol);
3415 fprintf(ftmpIF, "%lg %lg %lg\n", xlbend, ylbend, zlbend);
3416 fprintf(ftmpIF, "%lg %lg %lg\n", xend, yend, zend);
3417 fprintf(ftmpIF, "#xgrd: %lg, ygrd: %lg, zgrd: %lg\n", xgrd, ygrd,
3418 zgrd);
3419 fprintf(ftmpIF, "\n");
3420 }
3421
3422 // determine which element gets this electron
3423 // At present, the logic is as follow:
3424 // Using the information on the last segment, find out which
3425 // primitive is pierced by it and at which point From the
3426 // intersection point, find out the element number on the primitive
3427 // in a local sense Using the information (start and end elements of
3428 // a given primitive) identify the element in a global sense. This
3429 // approach should be lot more efficient than checking intersection
3430 // element by element.
3431 // The intersection point is computed following algorithm
3432 // implemented in a matlab code (plane_imp_line_par_int_3d.m) Also
3433 // check which primitive in the list is the closet to the end point
3434
3435 int PrimIntsctd = -1,
3436 EleIntsctd = -1; // intersected primitive & element
3437 int nearestprim = -1; // absurd value
3438 double dist = 1.0e6, mindist = 1.0e6; // absurdly high numbers
3439 double SumOfAngles;
3440 // check all primitives
3441 for (int prim = 1; prim <= NbPrimitives; ++prim) {
3442 if (InterfaceType[prim] != 4)
3443 continue; // primitive not a dielectric
3444
3445 int intersect = 0, extrasect = 1; // worst of conditions
3446 int InPrim = 0, InEle = 0;
3447 if (debugFn)
3448 printf("prim: %d, mindist: %lg, nearestprim: %d\n", prim,
3449 mindist, nearestprim);
3450
3451 // get the primitive nodes
3452
3453 // Use two nodes at a time to get two independent vectors on
3454 // primitive Get cross-product of these two vector - normal to the
3455 // plane Note that the normal is already associated with the
3456 // primitive of type 3 and 4; 2 is wire and does not have any
3457 // associated normal
3458 if ((PrimType[prim] == 3) || (PrimType[prim] == 4)) {
3459 if (debugFn) {
3460 printf("prim: %d\n", prim);
3461 printf("vertex0: %lg, %lg, %lg\n", XVertex[prim][0],
3462 YVertex[prim][0], ZVertex[prim][0]);
3463 printf("vertex1: %lg, %lg, %lg\n", XVertex[prim][1],
3464 YVertex[prim][1], ZVertex[prim][1]);
3465 printf("vertex2: %lg, %lg, %lg\n", XVertex[prim][2],
3466 YVertex[prim][2], ZVertex[prim][2]);
3467 if (PrimType[prim] == 4) {
3468 printf("vertex3: %lg, %lg, %lg\n", XVertex[prim][3],
3469 YVertex[prim][3], ZVertex[prim][3]);
3470 }
3471 fprintf(ftmpIF, "#prim: %d\n", prim);
3472 fprintf(ftmpIF, "%lg %lg %lg\n", XVertex[prim][0],
3473 YVertex[prim][0], ZVertex[prim][0]);
3474 fprintf(ftmpIF, "%lg %lg %lg\n", XVertex[prim][1],
3475 YVertex[prim][1], ZVertex[prim][1]);
3476 fprintf(ftmpIF, "%lg %lg %lg\n", XVertex[prim][2],
3477 YVertex[prim][2], ZVertex[prim][2]);
3478 if (PrimType[prim] == 4) {
3479 fprintf(ftmpIF, "%lg %lg %lg\n", XVertex[prim][3],
3480 YVertex[prim][3], ZVertex[prim][3]);
3481 }
3482 fprintf(ftmpIF, "%lg %lg %lg\n", XVertex[prim][0],
3483 YVertex[prim][0], ZVertex[prim][0]);
3484 fprintf(ftmpIF, "\n");
3485 fflush(stdout);
3486 } // debugFn
3487
3488 // use a, b, c (normal is ai + bj + ck) at one of the nodes to
3489 // get d ax + by + cz + d = 0 is the equation of the plane
3490 double d = -XNorm[prim] * XVertex[prim][0] -
3491 YNorm[prim] * YVertex[prim][0] -
3492 ZNorm[prim] * ZVertex[prim][0];
3493
3494 // distance of the end point to this primitve is
3495 dist =
3496 (xend * XNorm[prim] + yend * YNorm[prim] +
3497 zend * ZNorm[prim] + d) /
3498 sqrt(XNorm[prim] * XNorm[prim] + YNorm[prim] * YNorm[prim] +
3499 ZNorm[prim] * ZNorm[prim]);
3500 dist = fabs(dist); // if only magnitude is required
3501 if (prim == 1) {
3502 mindist = dist;
3503 nearestprim = prim;
3504 }
3505 if ((prim == 1) && debugFn)
3506 printf(
3507 "after prim == 1 check mindist: %lg, nearestprim: %d\n",
3508 mindist, nearestprim);
3509
3510 // Point of intersection
3511 // Algo as on p62 (pdf 81) of Vince - Geometry for Computer
3512 // Graphics 1.5.13 Intersection of a line and a plane Algorithm
3513 // as implemented in plne_imp_line_par_int_3d.m a (nx), b (ny),
3514 // c (nz), d are a, b, c, d vx, vy, vz are xgrd, ygrd and zgrd
3515 // tx, ty, tz are xlbend, ylbend, zlbend
3516 // In the present case, n and v are unit vectors
3517 double a = XNorm[prim];
3518 double b = YNorm[prim];
3519 double c = ZNorm[prim];
3520 double norm1 = sqrt(a * a + b * b + c * c);
3521 double norm2 = sqrt(xgrd * xgrd + ygrd * ygrd + zgrd * zgrd);
3522 double denom =
3523 a * xgrd + b * ygrd + c * zgrd; // (vec)n.(vec)v; if 0, ||
3524 double tol =
3525 1.0e-12; // CHECK: -8 in original code; sizes small here
3526 intersect = extrasect = 0;
3527
3528 if (debugFn) {
3529 printf("a, b, c, d, dist: %lg, %lg, %lg, %lg, %lg\n", a, b, c,
3530 d, dist);
3531 printf("vector n: ai + bj + ck\n");
3532 printf("vector v: xgrd, ygrd, zgrd: %lg, %lg, %lg\n", xgrd,
3533 ygrd, zgrd);
3534 printf("norm1, norm2, (vec n . vec v) denom: %lg, %lg, %lg\n",
3535 norm1, norm2, denom);
3536 printf("if vec n . vec v == 0, line and plane parallel\n");
3537 fflush(stdout);
3538 }
3539
3540 if (fabs(denom) <
3541 tol * norm1 * norm2) // line parallel to the plane
3542 {
3543 if (a * xlbend + b * ylbend + c * zlbend + d ==
3544 0.0) // CHECK == for float
3545 {
3546 intersect = 1;
3547 extrasect = 0;
3548 ptintsct.X = xlbend;
3549 ptintsct.Y = ylbend;
3550 ptintsct.Z = zlbend;
3551 } else {
3552 intersect = 0;
3553 extrasect = 0;
3554 ptintsct.X = 0.0; // Wrong to assign 0 values
3555 ptintsct.Y =
3556 0.0; // However, they are never going to be used
3557 ptintsct.Z = 0.0; // since intersect is 0
3558 }
3559 if (debugFn) {
3560 printf("line and plane parallel ...\n");
3561 printf("intersect: %d, extrasect: %d\n", intersect,
3562 extrasect);
3563 printf("intersection point: %lg, %lg, %lg\n", ptintsct.X,
3564 ptintsct.Y, ptintsct.Z);
3565 } // if line and plane are parallel
3566 } else { // if they are not parallel, they must intersect
3567 intersect = 1;
3568 double t =
3569 -(a * xlbend + b * ylbend + c * zlbend + d) / denom;
3570
3571 // check whether t is less than the length of the segment
3572 // and in the correct direction
3573 // If not, then an extrapolated intersection is not of
3574 // interest
3575 if ((t < 0.0) || (fabs(t) > fabs(lseg))) {
3576 extrasect = 1;
3577 ptintsct.X = xlbend + t * xgrd;
3578 ptintsct.Y = ylbend + t * ygrd;
3579 ptintsct.Z = zlbend + t * zgrd;
3580 } else {
3581 extrasect = 0;
3582 ptintsct.X = xlbend + t * xgrd;
3583 ptintsct.Y = ylbend + t * ygrd;
3584 ptintsct.Z = zlbend + t * zgrd;
3585 }
3586 if (debugFn) {
3587 printf("line and plane NOT parallel ...\n");
3588 printf("intersect: %d, extrasect: %d\n", intersect,
3589 extrasect);
3590 printf("intersection point: %lg, %lg, %lg\n", ptintsct.X,
3591 ptintsct.Y, ptintsct.Z);
3592 printf("t, lseg: %lg, %lg\n", t, lseg);
3593 printf(
3594 "for an interesting intersection, lseg > t > 0.0 "
3595 "...\n\n");
3596 fflush(stdout);
3597 } // must intersect
3598 } // if not parallel
3599 } // if PrimType is 3 or 4
3600 else { // this is a wire primitive - assume no charging up issues
3601 dist = -1.0; // an absurd negative distance
3602 intersect = 0;
3603 extrasect = 0;
3604 } // else PrimType 3 or 4
3605
3606 if (dist < mindist) {
3607 mindist = dist;
3608 nearestprim = prim;
3609 }
3610
3611 // implicit assumption: the first primitive that gets pierced by
3612 // the ray is the one that we want. There can be other primitives
3613 // that are pierced by the same ray. So, this logic should be
3614 // refined further
3615 if ((intersect == 1) && (extrasect == 0)) {
3616 // check whether the intersection point is within primitive
3617 // polygon
3618 int nvert = PrimType[prim];
3619 Point3D polynode[4];
3620 polynode[0].X = XVertex[prim][0];
3621 polynode[0].Y = YVertex[prim][0];
3622 polynode[0].Z = ZVertex[prim][0];
3623 polynode[1].X = XVertex[prim][1];
3624 polynode[1].Y = YVertex[prim][1];
3625 polynode[1].Z = ZVertex[prim][1];
3626 polynode[2].X = XVertex[prim][2];
3627 polynode[2].Y = YVertex[prim][2];
3628 polynode[2].Z = ZVertex[prim][2];
3629 if (PrimType[prim] == 4) {
3630 polynode[3].X = XVertex[prim][3];
3631 polynode[3].Y = YVertex[prim][3];
3632 polynode[3].Z = ZVertex[prim][3];
3633 }
3634 // printf("neBEMChkInPoly for primitive %d\n", prim);
3635 SumOfAngles = neBEMChkInPoly(nvert, polynode, ptintsct);
3636 if (fabs(fabs(SumOfAngles) - neBEMtwopi) <= 1.0e-8) {
3637 InPrim = 1;
3638 PrimIntsctd = prim;
3639 }
3640 if (debugFn) {
3641 // print polynode and InPrim
3642 printf("Prim: %d\n", prim);
3643 printf("ptintsct: %lg, %lg, %lg\n", ptintsct.X, ptintsct.Y,
3644 ptintsct.Z);
3645 printf("nvert: %d\n", nvert);
3646 printf("polynode0: %lg, %lg, %lg\n", polynode[0].X,
3647 polynode[0].Y, polynode[0].Z);
3648 printf("polynode1: %lg, %lg, %lg\n", polynode[1].X,
3649 polynode[1].Y, polynode[1].Z);
3650 printf("polynode2: %lg, %lg, %lg\n", polynode[2].X,
3651 polynode[2].Y, polynode[2].Z);
3652 if (nvert == 4) {
3653 printf("polynode3: %lg, %lg, %lg\n", polynode[3].X,
3654 polynode[3].Y, polynode[3].Z);
3655 }
3656 printf("SumOfAngles: %lg, InPrim: %d\n", SumOfAngles, InPrim);
3657 fflush(stdout);
3658 }
3659 if (!InPrim) continue; // check next primitive
3660
3661 // Once identified, check in which element belonging to this
3662 // primitive contains the point of intersection
3663 InEle = 0;
3664 for (int ele = ElementBgn[prim]; ele <= ElementEnd[prim];
3665 ++ele) {
3666 nvert = 0;
3667 if ((EleArr + ele - 1)->G.Type == 3) nvert = 3;
3668 if ((EleArr + ele - 1)->G.Type == 4) nvert = 4;
3669 if (!nvert) {
3671 "no vertex in element! ... neBEMKnownCharges ...\n");
3672 fclose(fPtIChUpMap);
3673 return -20;
3674 }
3675
3676 polynode[0].X = (EleArr + ele - 1)->G.Vertex[0].X;
3677 polynode[0].Y = (EleArr + ele - 1)->G.Vertex[0].Y;
3678 polynode[0].Z = (EleArr + ele - 1)->G.Vertex[0].Z;
3679 polynode[1].X = (EleArr + ele - 1)->G.Vertex[1].X;
3680 polynode[1].Y = (EleArr + ele - 1)->G.Vertex[1].Y;
3681 polynode[1].Z = (EleArr + ele - 1)->G.Vertex[1].Z;
3682 polynode[2].X = (EleArr + ele - 1)->G.Vertex[2].X;
3683 polynode[2].Y = (EleArr + ele - 1)->G.Vertex[2].Y;
3684 polynode[2].Z = (EleArr + ele - 1)->G.Vertex[2].Z;
3685 if (nvert == 4) {
3686 polynode[3].X = (EleArr + ele - 1)->G.Vertex[3].X;
3687 polynode[3].Y = (EleArr + ele - 1)->G.Vertex[3].Y;
3688 polynode[3].Z = (EleArr + ele - 1)->G.Vertex[3].Z;
3689 }
3690
3691 // printf("neBEMChkInPoly for element %d\n", ele);
3692 SumOfAngles = neBEMChkInPoly(nvert, polynode, ptintsct);
3693 if (fabs(fabs(SumOfAngles) - neBEMtwopi) <= 1.0e-8) InEle = 1;
3694 if (debugFn) {
3695 // print polynode and InEle
3696 printf("Ele: %d\n", ele);
3697 printf("ptintsct: %lg, %lg, %lg\n", ptintsct.X, ptintsct.Y,
3698 ptintsct.Z);
3699 printf("nvert: %d\n", nvert);
3700 printf("polynode0: %lg, %lg, %lg\n", polynode[0].X,
3701 polynode[0].Y, polynode[0].Z);
3702 printf("polynode1: %lg, %lg, %lg\n", polynode[1].X,
3703 polynode[1].Y, polynode[1].Z);
3704 printf("polynode2: %lg, %lg, %lg\n", polynode[2].X,
3705 polynode[2].Y, polynode[2].Z);
3706 if (nvert == 4) {
3707 printf("polynode3: %lg, %lg, %lg\n", polynode[3].X,
3708 polynode[3].Y, polynode[3].Z);
3709 }
3710 printf("SumOfAngles: %lg, InEle: %d\n", SumOfAngles, InEle);
3711 fflush(stdout);
3712 }
3713 if (InEle) {
3714 ptintsct.X = (EleArr + ele - 1)->G.Origin.X;
3715 ptintsct.Y = (EleArr + ele - 1)->G.Origin.Y;
3716 ptintsct.Z = (EleArr + ele - 1)->G.Origin.Z;
3717 EleIntsctd = ele;
3718 // Associate this electron to the identified element
3719 NbChUpIonEle[ele]++;
3720 fprintf(fPtIChUpMap, "%d %lg %lg %lg %d %d %d %d\n", ion,
3721 ptintsct.X, ptintsct.Y, ptintsct.Z, prim, InPrim,
3722 ele, InEle);
3723
3724 if (debugFn) {
3725 printf("# ion: %d\n", ion);
3726 printf("%lg %lg %lg\n", xlbend, ylbend, zlbend);
3727 printf("%lg %lg %lg\n", xend, yend, zend);
3728 printf("%lg, %lg, %lg\n", ptintsct.X, ptintsct.Y,
3729 ptintsct.Z);
3730 printf("# Associated primitive: %d\n", prim);
3731 printf(
3732 "# Associated element and origin: %d, %lg, %lg, "
3733 "%lg\n",
3734 ele, (EleArr + ele - 1)->G.Origin.X,
3735 (EleArr + ele - 1)->G.Origin.Y,
3736 (EleArr + ele - 1)->G.Origin.Z);
3737 printf("#NbChUpIonEle on element: %d\n",
3738 NbChUpIonEle[ele]);
3739 fprintf(ftmpIF, "#Element: %d\n", ele);
3740 fprintf(ftmpIF, "%lg %lg %lg\n", polynode[0].X,
3741 polynode[0].Y, polynode[0].Z);
3742 fprintf(ftmpIF, "%lg %lg %lg\n", polynode[1].X,
3743 polynode[1].Y, polynode[1].Z);
3744 fprintf(ftmpIF, "%lg %lg %lg\n", polynode[2].X,
3745 polynode[2].Y, polynode[2].Z);
3746 if (nvert == 4) {
3747 fprintf(ftmpIF, "%lg %lg %lg\n", polynode[3].X,
3748 polynode[3].Y, polynode[3].Z);
3749 }
3750 fprintf(ftmpIF, "%lg %lg %lg\n", polynode[0].X,
3751 polynode[0].Y, polynode[0].Z);
3752 fprintf(ftmpIF, "\n");
3753 fflush(stdout);
3754 }
3755 break; // desired element has been found!
3756 } // if InEle
3757 } // for all elements on this primitive
3758
3759 if (InEle)
3760 break;
3761 else {
3763 "Element cannot be identified ... neBEMKnownCharges\n");
3764 return -2;
3765 }
3766 } // if proper intersection and no extrasection
3767
3768 if ((InPrim) && (intersect) && (!extrasect) &&
3769 (InEle)) // all satisfied
3770 break; // do not check any further primtive for this electron
3771
3772 // If, after checking all the primitives, no interstion is found
3773 // valid
3774 if (prim ==
3775 (NbPrimitives)) // end of the list and no intersection
3776 {
3777 int nvert;
3778 Point3D polynode[4];
3779 int nearestele = ElementBgn[nearestprim];
3780 double distele = 1.0e6,
3781 mindistele = 1.0e6; // absurdly high value
3782
3783 if (debugFn) {
3784 printf("prim == (NbPrimitives) ... checking nearest ...\n");
3785 printf("nearestprim: %d, mindist: %lg\n", nearestprim,
3786 mindist);
3787 }
3788
3789 if (mindist <= 10.0e-6) {
3790 PrimIntsctd = nearestprim;
3791 InPrim = 1;
3792 } else {
3793 InPrim = 0;
3794 InEle = 0;
3795 break;
3796 }
3797
3798 for (int ele = ElementBgn[nearestprim]; // check all elements
3799 ele <= ElementEnd[nearestprim]; ++ele) {
3800 nvert = 0;
3801 if ((EleArr + ele - 1)->G.Type == 3) nvert = 3;
3802 if ((EleArr + ele - 1)->G.Type == 4) nvert = 4;
3803 if (!nvert) {
3805 "no vertex element! ... neBEMKnownCharges ...\n");
3806 return -20;
3807 }
3808
3809 /*
3810 polynode[0].X = (EleArr+ele-1)->G.Vertex[0].X;
3811 polynode[0].Y = (EleArr+ele-1)->G.Vertex[0].Y;
3812 polynode[0].Z = (EleArr+ele-1)->G.Vertex[0].Z;
3813 polynode[1].X = (EleArr+ele-1)->G.Vertex[1].X;
3814 polynode[1].Y = (EleArr+ele-1)->G.Vertex[1].Y;
3815 polynode[1].Z = (EleArr+ele-1)->G.Vertex[1].Z;
3816 polynode[2].X = (EleArr+ele-1)->G.Vertex[2].X;
3817 polynode[2].Y = (EleArr+ele-1)->G.Vertex[2].Y;
3818 polynode[2].Z = (EleArr+ele-1)->G.Vertex[2].Z;
3819 if(nvert == 4)
3820 {
3821 polynode[3].X = (EleArr+ele-1)->G.Vertex[3].X;
3822 polynode[3].Y = (EleArr+ele-1)->G.Vertex[3].Y;
3823 polynode[3].Z = (EleArr+ele-1)->G.Vertex[3].Z;
3824 }
3825
3826 Vector3D v01, v12, elenorm, unitelenorm;
3827 v01.X = polynode[1].X - polynode[0].X;
3828 v01.Y = polynode[1].Y - polynode[0].Y;
3829 v01.Z = polynode[1].Z - polynode[0].Z;
3830 v12.X = polynode[2].X - polynode[1].X;
3831 v12.Y = polynode[2].Y - polynode[1].Y;
3832 v12.Z = polynode[2].Z - polynode[1].Z;
3833 elenorm = Vector3DCrossProduct(&v01, &v12);
3834 unitelenorm = UnitVector3D(&elenorm);
3835
3836 if((nvert == 3) || (nvert == 4))
3837 {
3838 if(debugFn)
3839 {
3840 printf("nearestprim: %d, element: %d\n",
3841 nearestprim, ele); printf("vertex0: %lg, %lg, %lg\n", polynode[0].X,
3842 polynode[0].Y, polynode[0].Z); printf("vertex1: %lg, %lg, %lg\n",
3843 polynode[1].X,
3844 polynode[1].Y, polynode[1].Z); printf("vertex2: %lg, %lg, %lg\n",
3845 polynode[2].X, polynode[2].Y,
3846 polynode[2].Z); if(PrimType[prim] == 4)
3847 {
3848 printf("vertex3: %lg, %lg, %lg\n",
3849 polynode[3].X,
3850 polynode[3].Y, polynode[3].Z);
3851 }
3852 fprintf(ftmpIF, "#nearestprim: %d, element:
3853 %d\n", nearestprim, ele); fprintf(ftmpIF, "%lg %lg %lg\n",
3854 polynode[0].X,
3855 polynode[0].Y, polynode[0].Z); fprintf(ftmpIF, "%lg %lg %lg\n",
3856 polynode[1].X,
3857 polynode[1].Y, polynode[1].Z); fprintf(ftmpIF, "%lg %lg %lg\n",
3858 polynode[2].X,
3859 polynode[2].Y, polynode[2].Z); if(PrimType[prim] == 4)
3860 {
3861 fprintf(ftmpIF, "%lg %lg %lg\n",
3862 polynode[3].X, polynode[3].Y,
3863 polynode[3].Z);
3864 }
3865 fprintf(ftmpIF, "%lg %lg %lg\n",
3866 polynode[0].X,
3867 polynode[0].Y, polynode[0].Z); fprintf(ftmpIF, "\n"); fflush(stdout);
3868 } // debugFn
3869
3870 // use a, b, c (normal is ai + bj + ck) at one of the nodes to get d
3871 // ax + by + cz + d = 0 is the equation of the plane
3872 double a = unitelenorm.X;
3873 double b = unitelenorm.Y;
3874 double c = unitelenorm.Z;
3875 double d = - unitelenorm.X*polynode[0].X
3876 - unitelenorm.Y*polynode[0].Y
3877 - unitelenorm.Z*polynode[0].Z;
3878
3879 // distance of the end point to this primitve is
3880 distele = (xend * unitelenorm.X + yend * unitelenorm.Y
3881 + zend * unitelenorm.Z + d)
3882 /
3883 sqrt(unitelenorm.X*unitelenorm.X
3884 + unitelenorm.Y*unitelenorm.Y
3885 + unitelenorm.Z*unitelenorm.Z);
3886 distele = fabs(distele); // if only magnitude is
3887 required
3888 */
3889
3890 Vector3D eleOrigin;
3891 eleOrigin.X = (EleArr + ele - 1)->G.Origin.X;
3892 eleOrigin.Y = (EleArr + ele - 1)->G.Origin.Y;
3893 eleOrigin.Z = (EleArr + ele - 1)->G.Origin.Z;
3894 distele = (eleOrigin.X - xend) * (eleOrigin.X - xend) +
3895 (eleOrigin.Y - yend) * (eleOrigin.Y - yend) +
3896 (eleOrigin.Z - zend) * (eleOrigin.Z - zend);
3897 distele = sqrt(distele);
3898
3899 if (ele == ElementBgn[nearestprim]) {
3900 mindistele = distele;
3901 nearestele = ele;
3902 }
3903 if (distele < mindistele) {
3904 mindistele = distele;
3905 nearestele = ele;
3906 }
3907
3908 if (debugFn) {
3909 // printf("a, b, c, d, dist: %lg, %lg, %lg, %lg, %lg\n",
3910 // a, b, c, d, dist);
3911 // printf("vector n: ai + bj + ck\n");
3912 // printf("vector v: xgrd, ygrd, zgrd: %lg, %lg, %lg\n",
3913 // xgrd, ygrd, zgrd);
3914 printf(
3915 "distele: %lg, mindist: %lg, from nearest ele: %d\n",
3916 distele, mindistele, nearestele);
3917 fflush(stdout);
3918 }
3919
3920 // } // if PrimType is 3 or 4
3921 } // for elements in nearestprim
3922
3923 // if(mindistele <= 10.0e-6)
3924 // {
3925 EleIntsctd = nearestele;
3926 InEle = 1;
3927 ptintsct.X = (EleArr + EleIntsctd - 1)->G.Origin.X;
3928 ptintsct.Y = (EleArr + EleIntsctd - 1)->G.Origin.Y;
3929 ptintsct.Z = (EleArr + EleIntsctd - 1)->G.Origin.Z;
3930 NbChUpIonEle[EleIntsctd]++;
3931
3932 fprintf(fPtIChUpMap, "%d %lg %lg %lg %d %d %d %d\n", ion,
3933 ptintsct.X, ptintsct.Y, ptintsct.Z, PrimIntsctd, InPrim,
3934 EleIntsctd, InEle);
3935 // }
3936
3937 if (debugFn) {
3938 printf("# ion: %d\n", ion);
3939 printf("%lg %lg %lg\n", xlbend, ylbend, zlbend);
3940 printf("%lg %lg %lg\n", xend, yend, zend);
3941 printf("%lg, %lg, %lg\n", ptintsct.X, ptintsct.Y, ptintsct.Z);
3942 printf("# Associated primitive: %d\n", PrimIntsctd);
3943 printf("# Associated element and origin: %d, %lg, %lg, %lg\n",
3944 EleIntsctd, (EleArr + EleIntsctd - 1)->G.Origin.X,
3945 (EleArr + EleIntsctd - 1)->G.Origin.Y,
3946 (EleArr + EleIntsctd - 1)->G.Origin.Z);
3947 printf("#NbChUpIonEle on element: %d\n",
3948 NbChUpIonEle[EleIntsctd]);
3949 fprintf(ftmpIF, "#Element: %d\n", EleIntsctd);
3950 polynode[0].X = (EleArr + EleIntsctd - 1)->G.Vertex[0].X;
3951 polynode[0].Y = (EleArr + EleIntsctd - 1)->G.Vertex[0].Y;
3952 polynode[0].Z = (EleArr + EleIntsctd - 1)->G.Vertex[0].Z;
3953 polynode[1].X = (EleArr + EleIntsctd - 1)->G.Vertex[1].X;
3954 polynode[1].Y = (EleArr + EleIntsctd - 1)->G.Vertex[1].Y;
3955 polynode[1].Z = (EleArr + EleIntsctd - 1)->G.Vertex[1].Z;
3956 polynode[2].X = (EleArr + EleIntsctd - 1)->G.Vertex[2].X;
3957 polynode[2].Y = (EleArr + EleIntsctd - 1)->G.Vertex[2].Y;
3958 polynode[2].Z = (EleArr + EleIntsctd - 1)->G.Vertex[2].Z;
3959 if (nvert == 4) {
3960 polynode[3].X = (EleArr + EleIntsctd - 1)->G.Vertex[3].X;
3961 polynode[3].Y = (EleArr + EleIntsctd - 1)->G.Vertex[3].Y;
3962 polynode[3].Z = (EleArr + EleIntsctd - 1)->G.Vertex[3].Z;
3963 }
3964 fprintf(ftmpIF, "%lg %lg %lg\n", polynode[0].X, polynode[0].Y,
3965 polynode[0].Z);
3966 fprintf(ftmpIF, "%lg %lg %lg\n", polynode[1].X, polynode[1].Y,
3967 polynode[1].Z);
3968 fprintf(ftmpIF, "%lg %lg %lg\n", polynode[2].X, polynode[2].Y,
3969 polynode[2].Z);
3970 if (nvert == 4) {
3971 fprintf(ftmpIF, "%lg %lg %lg\n", polynode[3].X,
3972 polynode[3].Y, polynode[3].Z);
3973 }
3974 fprintf(ftmpIF, "%lg %lg %lg\n", polynode[0].X, polynode[0].Y,
3975 polynode[0].Z);
3976 fprintf(ftmpIF, "\n");
3977 fflush(stdout);
3978 } // debug
3979 } // if prim == NbPrimitives
3980
3981 } // for all primitives // just not those on the volume
3982
3983 if (debugFn) // check ion positions, volume primitives and elements
3984 {
3985 char inbstr[12];
3986 snprintf(inbstr, 12, "%d", ion);
3987 char ionposdbg[256];
3988 strcpy(ionposdbg, "/tmp/Ion");
3989 strcat(ionposdbg, inbstr);
3990 strcat(ionposdbg, ".out");
3991 FILE *fipd = fopen(ionposdbg, "w");
3992 if (fipd == NULL) {
3993 printf(
3994 "cannot open writable file to debug ion positions ...\n");
3995 printf("returning ...\n");
3996 return -111;
3997 }
3998 // write electron number, end, lbend, volume, primitive, elements,
3999 // intxn
4000 fprintf(fipd, "#ion: %d %d\n", inb, ion); // should print same
4001 fprintf(fipd, "#last but end position:\n");
4002 fprintf(fipd, "%lg %lg %lg\n", xlbend, ylbend, zlbend);
4003 fprintf(fipd, "#end position:\n");
4004 fprintf(fipd, "%lg %lg %lg\n\n", xend, yend, zend);
4005
4006 fprintf(fipd, "#intersected primitive number: %d\n", PrimIntsctd);
4007 if (PrimIntsctd >= 1) {
4008 fprintf(fipd, "#PrimType: %d\n", PrimType[PrimIntsctd]);
4009 fprintf(fipd, "#prim vertices:\n");
4010 fprintf(fipd, "%lg %lg %lg\n", XVertex[PrimIntsctd][0],
4011 YVertex[PrimIntsctd][0], ZVertex[PrimIntsctd][0]);
4012 fprintf(fipd, "%lg %lg %lg\n", XVertex[PrimIntsctd][1],
4013 YVertex[PrimIntsctd][1], ZVertex[PrimIntsctd][1]);
4014 fprintf(fipd, "%lg %lg %lg\n", XVertex[PrimIntsctd][2],
4015 YVertex[PrimIntsctd][2], ZVertex[PrimIntsctd][2]);
4016 if (PrimType[PrimIntsctd] == 4) {
4017 fprintf(fipd, "%lg %lg %lg\n", XVertex[PrimIntsctd][3],
4018 YVertex[PrimIntsctd][3], ZVertex[PrimIntsctd][3]);
4019 }
4020 fprintf(fipd, "%lg %lg %lg\n", XVertex[PrimIntsctd][0],
4021 YVertex[PrimIntsctd][0], ZVertex[PrimIntsctd][0]);
4022 fprintf(fipd, "\n");
4023
4024 fprintf(fipd, "#ptintsct:\n");
4025 fprintf(fipd, "%lg %lg %lg\n", ptintsct.X, ptintsct.Y,
4026 ptintsct.Z);
4027 fprintf(fipd, "\n");
4028 }
4029
4030 fprintf(fipd, "#intersected element number: %d\n", EleIntsctd);
4031 if (EleIntsctd >= 1) {
4032 int gtype = (EleArr + EleIntsctd - 1)->G.Type;
4033 fprintf(fipd, "#EleType: %d\n", gtype);
4034 fprintf(fipd, "#element vertices:\n");
4035 double x0 = (EleArr + EleIntsctd - 1)->G.Vertex[0].X;
4036 double y0 = (EleArr + EleIntsctd - 1)->G.Vertex[0].Y;
4037 double z0 = (EleArr + EleIntsctd - 1)->G.Vertex[0].Z;
4038 double x1 = (EleArr + EleIntsctd - 1)->G.Vertex[1].X;
4039 double y1 = (EleArr + EleIntsctd - 1)->G.Vertex[1].Y;
4040 double z1 = (EleArr + EleIntsctd - 1)->G.Vertex[1].Z;
4041 double x2 = (EleArr + EleIntsctd - 1)->G.Vertex[2].X;
4042 double y2 = (EleArr + EleIntsctd - 1)->G.Vertex[2].Y;
4043 double z2 = (EleArr + EleIntsctd - 1)->G.Vertex[2].Z;
4044 fprintf(fipd, "%lg %lg %lg\n", x0, y0, z0);
4045 fprintf(fipd, "%lg %lg %lg\n", x1, y1, z1);
4046 fprintf(fipd, "%lg %lg %lg\n", x2, y2, z2);
4047 if (gtype == 4) {
4048 double x3 = (EleArr + EleIntsctd - 1)->G.Vertex[3].X;
4049 double y3 = (EleArr + EleIntsctd - 1)->G.Vertex[3].Y;
4050 double z3 = (EleArr + EleIntsctd - 1)->G.Vertex[3].Z;
4051 fprintf(fipd, "%lg %lg %lg\n", x3, y3, z3);
4052 }
4053 fprintf(fipd, "%lg %lg %lg\n", x0, y0, z0);
4054 fprintf(fipd, "\n");
4055
4056 fprintf(fipd, "#ptintsct:\n");
4057 fprintf(fipd, "%lg %lg %lg\n", ptintsct.X, ptintsct.Y,
4058 ptintsct.Z);
4059 fprintf(fipd, "\n");
4060 }
4061 fclose(fipd);
4062 } // if 1
4063 } // for all the ions
4064 fclose(fPtIChUpMap);
4065
4066 // This file contains information about number of ions (I)
4067 // and total (E+I) charge deposition on each element
4068 FILE *fEleEIChUpMap = fopen("EleE+IChUpMap.out", "w");
4069 if (fEleEIChUpMap == NULL) {
4070 printf("cannot open EleE+IChUpMap.out file for writing ...\n");
4071 return 111;
4072 }
4073 for (int ele = 1; ele <= NbElements; ++ele) {
4074 (EleArr + ele - 1)->Assigned +=
4075 ChUpFactor * Q_I * NbChUpIonEle[ele] / (EleArr + ele - 1)->G.dA;
4076 fprintf(fEleEIChUpMap, "%d %lg %lg %lg %d %lg\n", ele,
4077 (EleArr + ele - 1)->G.Origin.X,
4078 (EleArr + ele - 1)->G.Origin.Y,
4079 (EleArr + ele - 1)->G.Origin.Z, NbChUpIonEle[ele],
4080 (EleArr + ele - 1)->Assigned);
4081 }
4082 fclose(fEleEIChUpMap);
4083
4084 fclose(ftmpIF);
4085 free(NbChUpIonEle);
4086 } // Calculation for ions ends
4087
4088 } // OptChargingUp
4089
4090 fclose(ChargingUpInpFile);
4091 } // else ChargingUpInpFile
4092
4093 if (debugFn) {
4094 // print all the elements and their number of charging up e-s and i-s
4095 }
4096 } // charging up parameters set up
4097
4098 return (0);
4099} // InitChargingUp ends
4100
4101#ifdef __cplusplus
4102} // namespace
4103#endif
#define MINDIST
Definition Isles.h:18
#define MyPI
Definition ReTriM.c:15
Point3D RotatePoint3D(Point3D *A, DirnCosn3D *DC, int Sense)
Definition Vector.c:339
Vector3D UnitVector3D(Vector3D *v)
Definition Vector.c:227
Vector3D Vector3DCrossProduct(Vector3D *A, Vector3D *B)
Definition Vector.c:246
int PrintDirnCosn3D(DirnCosn3D A)
Definition Vector.c:269
#define local2global
Definition Vector.h:14
int neBEMMessage(const char *message)
int neBEMGetNbOfLines(const char fname[])
double neBEMChkInPoly(int n, Point3D *p, Point3D q)
double neBEMTimeElapsed(clock_t t0, clock_t t1)
INTFACEGLOBAL clock_t stopClock
INTFACEGLOBAL int OptPrimitiveFiles
#define neBEMtwopi
INTFACEGLOBAL FILE * fgnuPrim
INTFACEGLOBAL FILE * fgnuElem
INTFACEGLOBAL FILE * fgnuMesh
INTFACEGLOBAL int OptGnuplotPrimitives
INTFACEGLOBAL clock_t startClock
INTFACEGLOBAL int OptPrintVertexAndNormal
INTFACEGLOBAL int OptElementFiles
INTFACEGLOBAL int OptGnuplot
INTFACEGLOBAL int OptGnuplotElements
neBEMGLOBAL Element * EleArr
Definition neBEM.h:176
neBEMGLOBAL double * ApplPot
Definition neBEM.h:82
neBEMGLOBAL int DebugLevel
Definition neBEM.h:195
neBEMGLOBAL int BoundaryConditions(void)
Definition ReTriM.c:2125
neBEMGLOBAL int * NbElmntsOnPrim
Definition neBEM.h:101
neBEMGLOBAL int EleCntr
Definition neBEM.h:119
neBEMGLOBAL double * ZNorm
Definition neBEM.h:78
neBEMGLOBAL char MeshOutDir[256]
Definition neBEM.h:223
#define Q_E
Definition neBEM.h:27
neBEMGLOBAL double ** ZVertex
Definition neBEM.h:78
neBEMGLOBAL double ElementLengthRqstd
Definition neBEM.h:114
neBEMGLOBAL PointKnCh * PointKnChArr
Definition neBEM.h:253
neBEMGLOBAL VolumeKnCh * VolumeKnChArr
Definition neBEM.h:288
neBEMGLOBAL int OptChargingUp
Definition neBEM.h:60
neBEMGLOBAL int InitKnownCharges(void)
Definition ReTriM.c:2204
neBEMGLOBAL double * XNorm
Definition neBEM.h:78
neBEMGLOBAL double * PrimOriginZ
Definition neBEM.h:80
neBEMGLOBAL int NbPrimitives
Definition neBEM.h:64
neBEMGLOBAL int * NbVertices
Definition neBEM.h:77
neBEMGLOBAL int WireElements(int prim, int nvertex, double xvert[], double yvert[], double zvert[], double radius, int volref1, int volref2, int inttype, double potential, double charge, double lambda, int NbWireSeg)
Definition ReTriM.c:82
neBEMGLOBAL int AnalyzePrimitive(int, int *, int *)
Definition ReTriM.c:121
neBEMGLOBAL int NbElements
Definition neBEM.h:120
neBEMGLOBAL int NbPointsKnCh
Definition neBEM.h:244
neBEMGLOBAL double * Epsilon1
Definition neBEM.h:82
neBEMGLOBAL double ** YVertex
Definition neBEM.h:78
neBEMGLOBAL int DiscretizePolygon(int prim, int nvertex, double xvert[], double yvert[], double zvert[], double xnorm, double ynorm, double znorm, int volref1, int volref2, int inttype, double potential, double charge, double lambda, int NbSegX, int NbSegZ)
Definition ReTriM.c:2110
neBEMGLOBAL int InitialConditions(void)
Definition ReTriM.c:2153
neBEMGLOBAL double * PrimOriginY
Definition neBEM.h:80
neBEMGLOBAL AreaKnCh * AreaKnChArr
Definition neBEM.h:276
neBEMGLOBAL DirnCosn3D * PrimDC
Definition neBEM.h:81
#define Q_I
Definition neBEM.h:28
neBEMGLOBAL int AnalyzeSurface(int, int *, int *)
Definition ReTriM.c:246
neBEMGLOBAL int NbLinesKnCh
Definition neBEM.h:244
neBEMGLOBAL int InitChargingUp(void)
Definition ReTriM.c:2527
neBEMGLOBAL int * VolRef1
Definition neBEM.h:83
neBEMGLOBAL double * YNorm
Definition neBEM.h:78
neBEMGLOBAL char ModelOutDir[256]
Definition neBEM.h:222
neBEMGLOBAL int NbVolumesKnCh
Definition neBEM.h:244
neBEMGLOBAL double ** XVertex
Definition neBEM.h:78
neBEMGLOBAL int * VolRef2
Definition neBEM.h:83
neBEMGLOBAL int NbAreasKnCh
Definition neBEM.h:244
neBEMGLOBAL int * ElementEnd
Definition neBEM.h:101
neBEMGLOBAL int * InterfaceType
Definition neBEM.h:75
neBEMGLOBAL int * PrimType
Definition neBEM.h:74
neBEMGLOBAL double * PrimLX
Definition neBEM.h:79
neBEMGLOBAL int DiscretizeWire(int prim, int nvertex, double xvert[], double yvert[], double zvert[], double radius, int volref1, int volref2, int inttype, double potential, double charge, double lambda, int NbSegs)
Definition ReTriM.c:407
neBEMGLOBAL double * Solution
Definition neBEM.h:197
neBEMGLOBAL int * ElementBgn
Definition neBEM.h:101
neBEMGLOBAL double * PrimOriginX
Definition neBEM.h:80
neBEMGLOBAL FILE * fMeshLog
Definition neBEM.h:121
neBEMGLOBAL int MaxNbElementsOnLength
Definition neBEM.h:112
neBEMGLOBAL int SurfaceElements(int prim, int nvertex, double xvert[], double yvert[], double zvert[], double xnorm, double ynorm, double znorm, int volref1, int volref2, int inttype, double potential, double charge, double lambda, int NbSegX, int NbSegZ)
Definition ReTriM.c:33
neBEMGLOBAL int DiscretizeRectangle(int prim, int nvertex, double xvert[], double yvert[], double zvert[], double xnorm, double ynorm, double znorm, int volref1, int volref2, int inttype, double potential, double charge, double lambda, int NbSegX, int NbSegZ)
Definition ReTriM.c:1592
neBEMGLOBAL LineKnCh * LineKnChArr
Definition neBEM.h:264
neBEMGLOBAL int AnalyzeWire(int, int *)
Definition ReTriM.c:158
neBEMGLOBAL int OptKnCh
Definition neBEM.h:59
neBEMGLOBAL double * PrimLZ
Definition neBEM.h:79
neBEMGLOBAL double * Epsilon2
Definition neBEM.h:82
neBEMGLOBAL int DiscretizeTriangle(int prim, int nvertex, double xvert[], double yvert[], double zvert[], double xnorm, double ynorm, double znorm, int volref1, int volref2, int inttype, double potential, double charge, double lambda, int NbSegX, int NbSegZ)
Definition ReTriM.c:788
neBEMGLOBAL int MinNbElementsOnLength
Definition neBEM.h:110
Vector3D ZUnit
Definition Vector.h:38
Vector3D YUnit
Definition Vector.h:37
Vector3D XUnit
Definition Vector.h:36
double X
Definition Vector.h:22
double Z
Definition Vector.h:24
double Y
Definition Vector.h:23
double Z
Definition Vector.h:31
double Y
Definition Vector.h:30
double X
Definition Vector.h:29