Garfield++ 5.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
neBEM.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <gsl/gsl_cblas.h>
#include <gsl/gsl_linalg.h>
#include <gsl/gsl_matrix.h>
#include "Isles.h"
#include "NR.h"
#include "Vector.h"
#include "neBEM.h"
#include "neBEMInterface.h"

Go to the source code of this file.

Functions

int ComputeSolution (void)
 
int LHMatrix (void)
 
int InvertMatrix (void)
 
int DecomposeMatrixSVD (double **SVDInf, double *SVDw, double **SVDv)
 
int ReadInvertedMatrix (void)
 
double ComputeInfluence (int elefld, int elesrc, Point3D *localP, DirnCosn3D *DirCos)
 
double SatisfyValue (int elesrc, Point3D *localP)
 
double SatisfyContinuity (int elefld, int elesrc, Point3D *localP, DirnCosn3D *DirCos)
 
int RHVector (void)
 
double ValueKnCh (int elefld)
 
double ContinuityKnCh (int elefld)
 
double ValueChUp (int elefld)
 
double ContinuityChUp (int elefld)
 
int Solve (void)
 
int ReadSolution (void)
 
int WeightingFieldSolution (int NbPrimsWtField, int PrimListWtField[], double solnarray[])
 
Point3D ReflectPrimitiveOnMirror (char Axis, int primsrc, Point3D srcpt, Point3D fldpt, double distance, DirnCosn3D *MirroredDC)
 
Point3D ReflectOnMirror (char Axis, int elesrc, Point3D srcpt, Point3D fldpt, double distance, DirnCosn3D *MirroredDC)
 
int UpdateKnownCharges (void)
 
int UpdateChargingUp (void)
 

Variables

int InfluenceMatrixFlag
 

Function Documentation

◆ ComputeInfluence()

double ComputeInfluence ( int elefld,
int elesrc,
Point3D * localP,
DirnCosn3D * DirCos )

Definition at line 1652 of file neBEM.c.

1653 {
1654 if (DebugLevel == 301) {
1655 printf("In ComputeInfluence ...\n");
1656 }
1657
1658 double value; // influence coefficient
1659
1660 if (0) {
1661 printf("\nContinuity satisfaction using following parameters ...\n");
1662 printf("gtsrc: %d, lxsrc: %lg, lzsrc% lg, dA: %lg\n",
1663 (EleArr + elesrc - 1)->G.Type, (EleArr + elesrc - 1)->G.LX,
1664 (EleArr + elesrc - 1)->G.LZ, (EleArr + elesrc - 1)->G.dA);
1665 printf("xlocal: %lg, ylocal: %lg, zlocal: %lg\n", localP->X, localP->Y,
1666 localP->Z);
1667 }
1668
1669 switch ((EleArr + elefld - 1)
1670 ->E.Type) // depending on the etype at the field point
1671 { // different boundary conditions need to be applied
1672 case 1: // conductor with known potential
1673 value = SatisfyValue(elesrc, localP);
1674 return (value);
1675 break;
1676
1677 case 2: // Conductor with a specified charge - has to have a BC as well!
1678 printf("Conductors with specific charge not implemented yet.\n");
1679 return -1; // The potential has to be the same for the complete
1680 // component.
1681 break; // If the value of pot is known, the situation is same as above.
1682 // if not, it is similar to a floating conductor.
1683
1684 case 3: // floating conductor
1685 value = SatisfyValue(elesrc, localP);
1686 return (value);
1687 // printf("Floating conductors not implemented yet.\n");
1688 // return -1;
1689 break;
1690
1691 // normal component of the displacement vector is continuous across each
1692 // dielectric-to-dielectric interface
1693 case 4: // DD interface
1694 value = SatisfyContinuity(elefld, elesrc, localP, DirCos);
1695 return (value);
1696 break;
1697
1698 case 5: // Dielectric with surface charge density known; same as above BC?
1699 value = SatisfyContinuity(elefld, elesrc, localP, DirCos);
1700 return (value);
1701 // The BC has to be the same and some part of the charge
1702 break; // density necessary to satisfy the BC needs to be solved for.
1703
1704 case 6: // Symmetry boundary, E parallel
1705 printf("Symmetry boundary, E parallel not implemented yet. \n");
1706 return -1;
1707 break;
1708
1709 case 7: // Symmetry boundary, E perpendicular (not likely to be used)
1710 printf("Symmetry boundary, E perpendicular not implemented yet. \n");
1711 return -1;
1712 break;
1713
1714 default:
1715 printf("Electric type %d out of range! ... exiting.\n",
1716 (EleArr + elefld - 1)->E.Type);
1717 return (-1);
1718 break; // unreachable
1719 } // switch on etfld ends
1720} // end of ComputeInfluence
double SatisfyContinuity(int elefld, int elesrc, Point3D *localP, DirnCosn3D *DirCos)
Definition neBEM.c:1797
double SatisfyValue(int elesrc, Point3D *localP)
Definition neBEM.c:1759
neBEMGLOBAL Element * EleArr
Definition neBEM.h:176
neBEMGLOBAL int DebugLevel
Definition neBEM.h:195
double X
Definition Vector.h:22
double Z
Definition Vector.h:24
double Y
Definition Vector.h:23

Referenced by LHMatrix().

◆ ComputeSolution()

int ComputeSolution ( void )

Definition at line 35 of file neBEM.c.

35 {
36 int LHMatrix(void), RHVector(void), Solve(void);
37 int InvertMatrix(void);
38 int ReadInvertedMatrix(void);
39#ifdef _OPENMP
40 double time_begin = 0., time_end = 0.;
41#endif
42 printf(
43 "----------------------------------------------------------------\n\n");
44 printf("ComputeSolution: neBEM solution begins ...\n");
45 printf(" TimeStep: %d\n", TimeStep);
46 printf(" NewModel: %d, NewMesh: %d, NewBC: %d, NewPP: %d\n",
48 printf(
49 " ModelCntr: %d, MeshCntr: %d, BCCntr: %d, PPCntr: %d\n",
51 fflush(stdout);
52 DebugISLES = 0; // an integer declared in Isles header file
53
55
56 switch (OptInvMatProc) {
57 case 0:
58 OptLU = 1;
59 OptSVD = 0;
60 OptGSL = 0;
61 break;
62 case 1:
63 OptLU = 0;
64 OptSVD = 1;
65 OptGSL = 0;
66 break;
67 case 2:
68 OptLU = 0;
69 OptSVD = 0;
70 OptGSL = 1;
71 break;
72 default:
73 OptLU = 1;
74 OptSVD = 0;
75 OptGSL = 0;
76 }
77 if ((OptSVD == 0) && (OptLU == 0) && (OptGSL == 0)) {
78 printf("Cannot proceed with OptSVD, OptLU and OptGSL zero.\n");
79 printf("Assuming the safer option OptSVD = 1.\n");
80 OptLU = 0;
81 OptSVD = 1;
82 OptGSL = 0;
83 }
84 if ((OptSVD == 1) && (OptLU == 1) && (OptGSL == 1)) {
85 printf("Cannot proceed with all OptSVD, OptLU and OptGSL one.\n");
86 printf("Assuming the safer option OptSVD = 1.\n");
87 OptLU = 0;
88 OptSVD = 1;
89 OptGSL = 0;
90 }
91
92 NbConstraints = 0;
94 printf(
95 "ComputeSolution: Simultaneous presence of OptSystemChargeZero && "
96 "NbFloatingConductors!\n");
97 printf(" Returning ...\n");
98 return (-1);
99 }
100 if (OptSystemChargeZero) // Constraint making total charge on the sysyem,
101 // zero
102 {
107 NbUnknowns; // which equation & unknown relates to this
108 } // constraint
109 if (NbFloatingConductors) // Number of floating conductors now restricted to
110 // one
111 {
112 if (NbFloatingConductors > 1) {
113 printf("Number of floating conductors > 1! ... not yet implemented.\n");
114 printf("Returning\n");
115 return -1;
116 }
120 NbFloatCon = NbUnknowns; // which equation and unknown relates to this
121 } // floating conductor
122
123 if (NewModel || NewMesh) {
126 } else {
128 }
129 // Computation of the influence coefficient matrix and inversion of the same
130 // is necessary only when we are considering a NewModel, and / or a NewMesh,
131 // i.e., InfluenceMatrixFlag is true.
132 // When OptChargingUp is true, then influence matrix, if not already
133 // available, is computed in the EffectChargingUp function. For an existing
134 // model and unchanged mesh, we can simply read in the relevant inverted
135 // matrix.
136 if (TimeStep == 1) {
138 startClock = clock();
139 printf("ComputeSolution: LHMatrix ... ");
140 fflush(stdout);
141#ifdef _OPENMP
142 time_begin = omp_get_wtime();
143#endif
144 int fstatus = LHMatrix();
145#ifdef _OPENMP
146 time_end = omp_get_wtime();
147 printf("Elapsed time: %lg\n", time_end - time_begin);
148#endif
149 if (fstatus != 0) {
150 neBEMMessage("ComputeSolution - LHMatrix");
151 return -1;
152 }
153 printf("ComputeSolution: LHMatrix done!\n");
154 fflush(stdout);
155 stopClock = clock();
157 printf("to setup influence matrix.\n");
158
159 startClock = clock();
160 printf("ComputeSolution: Inverting influence matrix ...\n");
161 fflush(stdout);
162 fstatus = InvertMatrix();
163 if (fstatus != 0) {
164 neBEMMessage("ComputeSolution - InvertMatrix");
165 return -1;
166 }
167 printf("ComputeSolution: Matrix inversion over.\n");
168 stopClock = clock();
170 printf("to invert influence matrix.\n");
171 } // if InfluenceMatrixFlag
172
173 if ((!InfluenceMatrixFlag) && NewBC) {
174 if (OptReadInvMatrix) {
175 startClock = clock();
176 printf(
177 "ComputeSolution: Reading inverted matrix ... will take time ...");
178 int fstatus = ReadInvertedMatrix();
179 if (fstatus != 0) {
180 neBEMMessage("ComputeSolution - ReadInvertedMatrix");
181 return -1;
182 }
183 printf(" done!\n");
184 stopClock = clock();
186 printf("to read inverted influence matrix.\n");
187 } else {
188 neBEMMessage("ComputeSolution - NewBC but no InvMat ... ");
189 neBEMMessage("don't know how to proceed!\n");
190 return -1;
191 }
192 } // if (!InfluenceMatrixFlag) && NewBC
193 } // if TimeStep == 1
194
195 // If TimeStep > 1, use the Infl (LHS) and InvMat existing in memory
196
197 int fstatus = 0;
198
199 // Update known charges
200 if (OptKnCh) {
201 startClock = clock();
202 printf("ComputeSolution: UpdateKnownCharges ... ");
203 fflush(stdout);
204 fstatus = UpdateKnownCharges();
205 if (fstatus != 0) {
206 neBEMMessage("ComputeSolution - UpdateKnownCharges");
207 return -1;
208 }
209 printf("ComputeSolution: UpdateKnownCharges done!\n");
210 fflush(stdout);
211 stopClock = clock();
213 printf("to set up UpdateKnownCharges.\n");
214 } // if OptKnCh
215
216 // Update charging up
217 if (OptChargingUp) {
218 startClock = clock();
219 printf("ComputeSolution: UpdateChargingUp ... ");
220 fflush(stdout);
221 fstatus = UpdateChargingUp();
222 if (fstatus != 0) {
223 neBEMMessage("ComputeSolution - UpdateChargingUp");
224 return -1;
225 }
226 printf("ComputeSolution: UpdateChargingUp done!\n");
227 fflush(stdout);
228 stopClock = clock();
230 printf("to set up UpdateChargingUp.\n");
231 } // if OptChargingUp
232
233 // RHS
234 startClock = clock();
235 printf("ComputeSolution: RHVector ... ");
236 fflush(stdout);
237 fstatus = RHVector();
238 if (fstatus != 0) {
239 neBEMMessage("ComputeSolution - RHVector");
240 return -1;
241 }
242 printf("ComputeSolution: RHVector done!\n");
243 fflush(stdout);
244 stopClock = clock();
246 printf("to set up RH vector.\n");
247
248 // Solve
249 // The Solve routine simply involves the matrix
250 // multiplication of inverted matrix and the current RHVector.
251 startClock = clock();
252 printf("ComputeSolution: Solve ... ");
253 fflush(stdout);
254#ifdef _OPENMP
255 time_begin = omp_get_wtime();
256#endif
257 fstatus = Solve();
258#ifdef _OPENMP
259 time_end = omp_get_wtime();
260 printf("Elapsed time: %lg\n", time_end - time_begin);
261#endif
262 if (fstatus != 0) {
263 neBEMMessage("ComputeSolution - Solve");
264 return -1;
265 }
266 printf("ComputeSolution: Solve done!\n");
267 fflush(stdout);
268 stopClock = clock();
270 printf("to compute solution.\n");
271
272 // The other locations where this matrix is freed is in
273 // InvertMatrix (if OptValidateSolution is false!),
274 // or in
275 // Solve (due to a combination of OptValidateSolution true and
276 // InfluenceMatrixFlag false)
277 // due to RepeatLHMatrix
278 // or OptStoreInflMatrix.
281
282 printf("ComputeSolution: neBEM solution ends ...\a\n");
283 fflush(stdout);
284 return (0);
285} // end of neBEM
ISLESGLOBAL int DebugISLES
Definition Isles.h:36
int neBEMMessage(const char *message)
double neBEMTimeElapsed(clock_t t0, clock_t t1)
INTFACEGLOBAL clock_t stopClock
INTFACEGLOBAL clock_t startClock
int InfluenceMatrixFlag
Definition neBEM.c:29
int RHVector(void)
Definition neBEM.c:1976
int LHMatrix(void)
Definition neBEM.c:307
int Solve(void)
Definition neBEM.c:2784
int ReadInvertedMatrix(void)
Definition neBEM.c:1577
int InvertMatrix(void)
Definition neBEM.c:1309
int UpdateChargingUp(void)
Definition neBEM.c:4267
int UpdateKnownCharges(void)
Definition neBEM.c:4265
neBEMGLOBAL int NbFloatCon
Definition neBEM.h:133
neBEMGLOBAL int MeshCntr
Definition neBEM.h:184
neBEMGLOBAL int PPCntr
Definition neBEM.h:184
neBEMGLOBAL int OptSVD
Definition neBEM.h:196
neBEMGLOBAL int OptInvMatProc
Definition neBEM.h:43
neBEMGLOBAL int OptLU
Definition neBEM.h:196
neBEMGLOBAL int NewModel
Definition neBEM.h:180
neBEMGLOBAL int OptChargingUp
Definition neBEM.h:60
neBEMGLOBAL int EndOfTime
Definition neBEM.h:201
neBEMGLOBAL int NewMesh
Definition neBEM.h:180
neBEMGLOBAL int NbElements
Definition neBEM.h:120
neBEMGLOBAL int OptSystemChargeZero
Definition neBEM.h:125
neBEMGLOBAL int NbEqns
Definition neBEM.h:194
neBEMGLOBAL int NbFloatingConductors
Definition neBEM.h:131
neBEMGLOBAL int NbConstraints
Definition neBEM.h:193
neBEMGLOBAL int NewPP
Definition neBEM.h:180
neBEMGLOBAL int BCCntr
Definition neBEM.h:184
neBEMGLOBAL int TimeStep
Definition neBEM.h:201
neBEMGLOBAL int OptGSL
Definition neBEM.h:196
neBEMGLOBAL double ** Inf
Definition neBEM.h:197
neBEMGLOBAL int OptReadInvMatrix
Definition neBEM.h:50
neBEMGLOBAL int NbUnknowns
Definition neBEM.h:194
neBEMGLOBAL int ModelCntr
Definition neBEM.h:184
neBEMGLOBAL int OptValidateSolution
Definition neBEM.h:44
neBEMGLOBAL int OptKnCh
Definition neBEM.h:59
neBEMGLOBAL int NbSystemChargeZero
Definition neBEM.h:127
neBEMGLOBAL int NewBC
Definition neBEM.h:180
void free_dmatrix(double **m, long nrl, long, long ncl, long)
Definition nrutil.c:482

Referenced by neBEMSolve().

◆ ContinuityChUp()

double ContinuityChUp ( int elefld)

Definition at line 2616 of file neBEM.c.

2616 {
2617 int dbgFn = 0;
2618
2619 if (dbgFn) printf("\nelefld: %d\n", elefld);
2620 if (dbgFn) {
2621 printf("In ContinuityChUp ...\n");
2622 }
2623
2624 double value = 0.0;
2625 double assigned = 0.0;
2626 double xfld = (EleArr + elefld - 1)->BC.CollPt.X;
2627 double yfld = (EleArr + elefld - 1)->BC.CollPt.Y;
2628 double zfld = (EleArr + elefld - 1)->BC.CollPt.Z;
2629
2630 Vector3D localF, globalF;
2631
2632 // OMPCheck - parallelize
2633
2634 // Effect of known charges on interface elements
2635 for (int elesrc = 1; elesrc <= NbElements; ++elesrc) {
2636 Point3D localP;
2637
2638 assigned = (EleArr + elesrc - 1)->Assigned;
2639 if (fabs(assigned) <= 1.0e-16) continue;
2640
2641 Point3D *pOrigin = &(EleArr + elesrc - 1)->G.Origin;
2642
2643 // Retrieve element properties from the structure
2644 if ((EleArr + elesrc - 1)->E.Type == 0) {
2645 printf("Wrong EType for elesrc %d element %d on %dth primitive!\n",
2646 elesrc, (EleArr + elesrc - 1)->Id,
2647 (EleArr + elesrc - 1)->PrimitiveNb);
2648 exit(-1);
2649 }
2650
2651 { // Rotate point3D from global to local system
2652 double InitialVector[3]
2653 = {xfld - pOrigin->X, yfld - pOrigin->Y, zfld - pOrigin->Z};
2654 double TransformationMatrix[3][3] = {{0.0, 0.0, 0.0},
2655 {0.0, 0.0, 0.0},
2656 {0.0, 0.0, 0.0}};
2657 DirnCosn3D *DirCos = &(EleArr + elesrc - 1)->G.DC;
2658 TransformationMatrix[0][0] = DirCos->XUnit.X;
2659 TransformationMatrix[0][1] = DirCos->XUnit.Y;
2660 TransformationMatrix[0][2] = DirCos->XUnit.Z;
2661 TransformationMatrix[1][0] = DirCos->YUnit.X;
2662 TransformationMatrix[1][1] = DirCos->YUnit.Y;
2663 TransformationMatrix[1][2] = DirCos->YUnit.Z;
2664 TransformationMatrix[2][0] = DirCos->ZUnit.X;
2665 TransformationMatrix[2][1] = DirCos->ZUnit.Y;
2666 TransformationMatrix[2][2] = DirCos->ZUnit.Z;
2667 double FinalVector[3];
2668
2669 for (int i = 0; i < 3; ++i) {
2670 FinalVector[i] = 0.0;
2671 for (int j = 0; j < 3; ++j) {
2672 FinalVector[i] += TransformationMatrix[i][j] * InitialVector[j];
2673 }
2674 }
2675
2676 localP.X = FinalVector[0];
2677 localP.Y = FinalVector[1];
2678 localP.Z = FinalVector[2];
2679 } // Point3D rotated
2680
2681 // if((((EleArr+elesrc-1)->E.Type == 4) && (elefld == elesrc)) //
2682 // self-influence
2683 // || (((EleArr+elesrc-1)->E.Type == 5) && (elefld == elesrc))) // DD intfce
2684 // For self-influence, lmsrc is equal to lmfld which allows the following.
2685 if ((elefld == elesrc) &&
2686 (fabs(localP.X) < (EleArr + elesrc - 1)->G.LX / 2.0) &&
2687 (fabs(localP.Y) < MINDIST) &&
2688 (fabs(localP.Z) < (EleArr + elesrc - 1)->G.LZ / 2.0)) {
2689 value += assigned * 1.0 / (2.0 * EPS0 * (EleArr + elesrc - 1)->E.Lambda);
2690 } else {
2691 // Retrieve element properties from the structure
2692 if ((EleArr + elesrc - 1)->E.Type == 0) {
2693 printf("Wrong EType for elesrc %d element %d on %dth primitive!\n",
2694 elesrc, (EleArr + elesrc - 1)->Id,
2695 (EleArr + elesrc - 1)->PrimitiveNb);
2696 exit(-1);
2697 }
2698
2699 switch ((EleArr + elesrc - 1)->G.Type) {
2700 case 4: // rectangular element
2701 RecFlux(elesrc, &localP, &localF);
2702 break;
2703 case 3: // triangular element
2704 TriFlux(elesrc, &localP, &localF);
2705 break;
2706 case 2: // linear (wire) element
2707 WireFlux(elesrc, &localP, &localF);
2708 break;
2709 default:
2710 printf("Geometrical type out of range! ... exiting ...\n");
2711 exit(-1);
2712 break; // never comes here
2713 } // switch over gtsrc ends
2714
2715 // in GCS - mirror points?!
2716 globalF =
2717 RotateVector3D(&localF, &(EleArr + elesrc - 1)->G.DC, local2global);
2718 // in ECS (local to the field element)
2719 localF =
2720 RotateVector3D(&globalF, &(EleArr + elefld - 1)->G.DC, global2local);
2721
2722 value -= assigned * localF.Y; // +ve gradient of Green's is -ve normal
2723 // force (changed from -= to += on 02/11/11
2724 // - CHECK!!! - and back to -= on 05/11/11)
2725 } // else self-influence
2726 }
2727
2728 value *= MyFACTOR;
2729 if (dbgFn) {
2730 printf("value (* MyFACTOR): %g\n", value);
2731 }
2732
2733 // Contributions from points, lines areas and volumes carrying known charge
2734 // (density).
2735 Point3D globalP;
2736 globalP.X = xfld;
2737 globalP.Y = yfld; // the global position of the field point necessary now
2738 globalP.Z = zfld;
2739 for (int point = 1; point <= NbPointsKnCh; ++point) {
2740 // potential not being used to evaluate Neumann continuity
2741 (void)PointKnChPF((PointKnChArr + point - 1)->P, globalP, &globalF);
2742 localF =
2743 RotateVector3D(&globalF, &(EleArr + elefld - 1)->G.DC, global2local);
2744 value -= (PointKnChArr + point - 1)->Assigned * localF.Y;
2745 } // loop over points NbPointsKnCh
2746
2747 for (int line = 1; line <= NbLinesKnCh; ++line) {
2748 // potential not being used to evaluate Neumann continuity
2749 (void)LineKnChPF((LineKnChArr + line - 1)->Start,
2750 (LineKnChArr + line - 1)->Stop, globalP, &globalF);
2751 localF =
2752 RotateVector3D(&globalF, &(EleArr + elefld - 1)->G.DC, global2local);
2753 value -= (LineKnChArr + line - 1)->Assigned * localF.Y;
2754 } // loop over lines
2755
2756 for (int area = 1; area <= NbAreasKnCh; ++area) {
2757 // potential not being used to evaluate Neumann continuity
2758 (void)AreaKnChPF((AreaKnChArr + area - 1)->NbVertices,
2759 ((AreaKnChArr + area - 1)->Vertex), globalP, &globalF);
2760 localF =
2761 RotateVector3D(&globalF, &(EleArr + elefld - 1)->G.DC, global2local);
2762 value -= (AreaKnChArr + area - 1)->Assigned * localF.Y;
2763 } // loop over areas
2764
2765 for (int vol = 1; vol <= NbVolumesKnCh; ++vol) {
2766 // potential not being used to evaluate Neumann continuity
2767 (void)VolumeKnChPF((VolumeKnChArr + vol - 1)->NbVertices,
2768 ((VolumeKnChArr + vol - 1)->Vertex), globalP, &globalF);
2769 localF =
2770 RotateVector3D(&globalF, &(EleArr + elefld - 1)->G.DC, global2local);
2771 value -= (VolumeKnChArr + vol - 1)->Assigned * localF.Y;
2772 } // loop over volumes
2773
2774 value /= MyFACTOR;
2775 if (dbgFn) {
2776 printf("value after known charges in volumes (/ MyFACTOR): %g\n", value);
2777 printf("Exiting ContinuityChUp ...\n");
2778 }
2779
2780 return (value);
2781} // ContinuityChUp ends
void TriFlux(int ele, Point3D *localP, Vector3D *localF)
void RecFlux(int ele, Point3D *localP, Vector3D *localF)
void WireFlux(int ele, Point3D *localP, Vector3D *localF)
double LineKnChPF(Point3D LineStart, Point3D LineStop, Point3D FieldPt, Vector3D *globalF)
Definition Isles.c:2271
double AreaKnChPF(int NbVertices, Point3D *Vertex, Point3D FieldPt, Vector3D *globalF)
Definition Isles.c:2694
double PointKnChPF(Point3D SourcePt, Point3D FieldPt, Vector3D *globalF)
Definition Isles.c:2249
double VolumeKnChPF(int, Point3D *, Point3D, Vector3D *globalF)
Definition Isles.c:2841
#define MINDIST
Definition Isles.h:18
Vector3D RotateVector3D(Vector3D *A, DirnCosn3D *DC, int Sense)
Definition Vector.c:395
#define global2local
Definition Vector.h:13
#define local2global
Definition Vector.h:14
DoubleAc fabs(const DoubleAc &f)
Definition DoubleAc.h:615
#define EPS0
Definition neBEM.h:20
neBEMGLOBAL PointKnCh * PointKnChArr
Definition neBEM.h:253
neBEMGLOBAL VolumeKnCh * VolumeKnChArr
Definition neBEM.h:288
neBEMGLOBAL int * NbVertices
Definition neBEM.h:77
neBEMGLOBAL int NbPointsKnCh
Definition neBEM.h:244
neBEMGLOBAL AreaKnCh * AreaKnChArr
Definition neBEM.h:276
neBEMGLOBAL int NbLinesKnCh
Definition neBEM.h:244
neBEMGLOBAL int NbVolumesKnCh
Definition neBEM.h:244
neBEMGLOBAL int NbAreasKnCh
Definition neBEM.h:244
neBEMGLOBAL LineKnCh * LineKnChArr
Definition neBEM.h:264
#define MyFACTOR
Definition neBEM.h:21
double Y
Definition Vector.h:30

Referenced by RHVector().

◆ ContinuityKnCh()

double ContinuityKnCh ( int elefld)

Definition at line 2290 of file neBEM.c.

2290 {
2291 int dbgFn = 0;
2292
2293 if (dbgFn) printf("\nelefld: %d\n", elefld);
2294
2295 double value = 0.0;
2296 double assigned = 0.0;
2297 double xfld = (EleArr + elefld - 1)->BC.CollPt.X;
2298 double yfld = (EleArr + elefld - 1)->BC.CollPt.Y;
2299 double zfld = (EleArr + elefld - 1)->BC.CollPt.Z;
2300
2301 Vector3D localF, globalF;
2302
2303 // OMPCheck - parallelize
2304
2305 // Effect of known charges on interface elements
2306 for (int elesrc = 1; elesrc <= NbElements; ++elesrc) {
2307 Point3D localP;
2308
2309 assigned = (EleArr + elesrc - 1)->Assigned;
2310 if (fabs(assigned) <= 1.0e-16) continue;
2311
2312 Point3D *pOrigin = &(EleArr + elesrc - 1)->G.Origin;
2313
2314 // Retrieve element properties from the structure
2315 if ((EleArr + elesrc - 1)->E.Type == 0) {
2316 printf("Wrong EType for elesrc %d element %d on %dth primitive!\n",
2317 elesrc, (EleArr + elesrc - 1)->Id,
2318 (EleArr + elesrc - 1)->PrimitiveNb);
2319 exit(-1);
2320 }
2321
2322 { // Rotate point3D from global to local system
2323 double InitialVector[3]
2324 = {xfld - pOrigin->X, yfld - pOrigin->Y, zfld - pOrigin->Z};
2325 double TransformationMatrix[3][3] = {{0.0, 0.0, 0.0},
2326 {0.0, 0.0, 0.0},
2327 {0.0, 0.0, 0.0}};
2328 DirnCosn3D *DirCos = &(EleArr + elesrc - 1)->G.DC;
2329 TransformationMatrix[0][0] = DirCos->XUnit.X;
2330 TransformationMatrix[0][1] = DirCos->XUnit.Y;
2331 TransformationMatrix[0][2] = DirCos->XUnit.Z;
2332 TransformationMatrix[1][0] = DirCos->YUnit.X;
2333 TransformationMatrix[1][1] = DirCos->YUnit.Y;
2334 TransformationMatrix[1][2] = DirCos->YUnit.Z;
2335 TransformationMatrix[2][0] = DirCos->ZUnit.X;
2336 TransformationMatrix[2][1] = DirCos->ZUnit.Y;
2337 TransformationMatrix[2][2] = DirCos->ZUnit.Z;
2338 double FinalVector[3];
2339
2340 for (int i = 0; i < 3; ++i) {
2341 FinalVector[i] = 0.0;
2342 for (int j = 0; j < 3; ++j) {
2343 FinalVector[i] += TransformationMatrix[i][j] * InitialVector[j];
2344 }
2345 }
2346
2347 localP.X = FinalVector[0];
2348 localP.Y = FinalVector[1];
2349 localP.Z = FinalVector[2];
2350 } // Point3D rotated
2351
2352 // if((((EleArr+elesrc-1)->E.Type == 4) && (elefld == elesrc)) //
2353 // self-influence
2354 // || (((EleArr+elesrc-1)->E.Type == 5) && (elefld == elesrc))) // DD intfce
2355 // For self-influence, lmsrc is equal to lmfld which allows the following.
2356 if ((elefld == elesrc) &&
2357 (fabs(localP.X) < (EleArr + elesrc - 1)->G.LX / 2.0) &&
2358 (fabs(localP.Y) < MINDIST) &&
2359 (fabs(localP.Z) < (EleArr + elesrc - 1)->G.LZ / 2.0)) {
2360 value += assigned * 1.0 / (2.0 * EPS0 * (EleArr + elesrc - 1)->E.Lambda);
2361 } else {
2362 // Retrieve element properties from the structure
2363 if ((EleArr + elesrc - 1)->E.Type == 0) {
2364 printf("Wrong EType for elesrc %d element %d on %dth primitive!\n",
2365 elesrc, (EleArr + elesrc - 1)->Id,
2366 (EleArr + elesrc - 1)->PrimitiveNb);
2367 exit(-1);
2368 }
2369
2370 // Following fluxes in the influencing ECS
2371 switch ((EleArr + elesrc - 1)->G.Type) {
2372 case 4: // rectangular element
2373 RecFlux(elesrc, &localP, &localF);
2374 break;
2375 case 3: // triangular element
2376 TriFlux(elesrc, &localP, &localF);
2377 break;
2378 case 2: // linear (wire) element
2379 WireFlux(elesrc, &localP, &localF);
2380 break;
2381 default:
2382 printf("Geometrical type out of range! ... exiting ...\n");
2383 exit(-1);
2384 break; // never comes here
2385 } // switch over gtsrc ends
2386
2387 // in GCS - mirror points?!
2388 globalF =
2389 RotateVector3D(&localF, &(EleArr + elesrc - 1)->G.DC, local2global);
2390 // in ECS (local to the field element)
2391 localF =
2392 RotateVector3D(&globalF, &(EleArr + elefld - 1)->G.DC, global2local);
2393
2394 value -= assigned * localF.Y; // +ve gradient of Green's is -ve normal
2395 // force (changed from -= to += on 02/11/11
2396 // - CHECK!!! - and back to -= on 05/11/11)
2397 } // else self-influence
2398 } // for elesrc
2399
2400 value *= MyFACTOR; // so that later MyFACTOR divisions are reduced.
2401 if (dbgFn) {
2402 printf("value (* MyFACTOR): %g\n", value);
2403 }
2404
2405 // Contributions from points, lines areas and volumes carrying known charge
2406 // (density).
2407 Point3D fieldPt;
2408 fieldPt.X = xfld;
2409 fieldPt.Y = yfld; // the global position of the field point necessary now
2410 fieldPt.Z = zfld;
2411 for (int point = 1; point <= NbPointsKnCh; ++point) {
2412 Point3D sourcePt;
2413 sourcePt.X = PointKnChArr[point].P.X;
2414 sourcePt.Y = PointKnChArr[point].P.Y;
2415 sourcePt.Z = PointKnChArr[point].P.Z;
2416 // potential not being used to evaluate Neumann continuity
2417 (void)PointKnChPF(sourcePt, fieldPt, &globalF);
2418 localF =
2419 RotateVector3D(&globalF, &(EleArr + elefld - 1)->G.DC, global2local);
2420 value -= PointKnChArr[point].Assigned * localF.Y;
2421 } // loop over points NbPointsKnCh
2422
2423 for (int line = 1; line <= NbLinesKnCh; ++line) {
2424 Point3D startPt, stopPt;
2425 startPt.X = LineKnChArr[line].Start.X;
2426 startPt.Y = LineKnChArr[line].Start.Y;
2427 startPt.Z = LineKnChArr[line].Start.Z;
2428 stopPt.X = LineKnChArr[line].Stop.X;
2429 stopPt.Y = LineKnChArr[line].Stop.Y;
2430 stopPt.Z = LineKnChArr[line].Stop.Z;
2431 double radius = LineKnChArr[line].Radius;
2432 if (0) {
2433 printf(
2434 "In ContinuityKnCh, Nb: %d, X1Y1Z1: %lg %lg %lg X2Y2Z2 %lg %lg %lg "
2435 "R: %lg Lmda:%lg\n",
2436 LineKnChArr[line].Nb, startPt.X, startPt.Y, startPt.Z, stopPt.X,
2437 stopPt.Y, stopPt.Z, radius, LineKnChArr[line].Assigned);
2438 }
2439 // potential not being used to evaluate Neumann continuity
2440 (void)LineKnChPF(startPt, stopPt, fieldPt, &globalF);
2441 localF =
2442 RotateVector3D(&globalF, &(EleArr + elefld - 1)->G.DC, global2local);
2443 value -= LineKnChArr[line].Assigned * localF.Y;
2444 } // loop over lines
2445 // Simplifying conversions, similar to points and lines may be necessary.
2446 for (int area = 1; area <= NbAreasKnCh; ++area) {
2447 // potential not being used to evaluate Neumann continuity
2448 (void)AreaKnChPF((AreaKnChArr + area - 1)->NbVertices,
2449 ((AreaKnChArr + area - 1)->Vertex), fieldPt, &globalF);
2450 localF =
2451 RotateVector3D(&globalF, &(EleArr + elefld - 1)->G.DC, global2local);
2452 value -= (AreaKnChArr + area - 1)->Assigned * localF.Y;
2453 } // loop over areas
2454
2455 // Simplifying conversions, similar to points and lines may be necessary.
2456 for (int vol = 1; vol <= NbVolumesKnCh; ++vol) {
2457 // potential not being used to evaluate Neumann continuity
2458 (void)VolumeKnChPF((VolumeKnChArr + vol - 1)->NbVertices,
2459 ((VolumeKnChArr + vol - 1)->Vertex), fieldPt, &globalF);
2460 localF =
2461 RotateVector3D(&globalF, &(EleArr + elefld - 1)->G.DC, global2local);
2462 value -= (VolumeKnChArr + vol - 1)->Assigned * localF.Y;
2463 } // loop over volumes
2464
2465 value /= MyFACTOR; // factored in
2466 return (value);
2467} // end of ContinuityKnCh

Referenced by RHVector().

◆ DecomposeMatrixSVD()

int DecomposeMatrixSVD ( double ** SVDInf,
double * SVDw,
double ** SVDv )

Definition at line 1527 of file neBEM.c.

1527 {
1528 // The following needs optimization - wmin, wmax etc.
1529 double wmin, wmax;
1530
1531 printf("DecomposeMatrix: matrix decomposition using SVD ... ");
1532 fflush(stdout);
1533 svdcmp(SVDInf, NbEqns, NbUnknowns, SVDw, SVDv); // SVDInf matrix over-written
1534 printf("DecomposeMatrix: decomposition completed ...\n");
1535 fflush(stdout);
1536
1537 wmax = SVDw[1]; // Will be the maximum singular value obtained - changed 0.0
1538#ifdef _OPENMP
1539#pragma omp parallel
1540#endif
1541 {
1542 int j;
1543#ifdef _OPENMP
1544#pragma omp for private(j)
1545#endif
1546 for (j = 1; j <= NbUnknowns; j++) {
1547 if (SVDw[j] > wmax) wmax = SVDw[j];
1548 }
1549 } // omp parallel
1550
1551 // This is where we set the threshold for singular values allowed to be
1552 // nonzero. The constant is typical, but not universal. You have to experiment
1553 // with your own application.
1554 wmin = wmax * 1.0e-12;
1555#ifdef _OPENMP
1556#pragma omp parallel
1557#endif
1558 {
1559 int j;
1560#ifdef _OPENMP
1561#pragma omp for private(j)
1562#endif
1563 for (j = 1; j <= NbUnknowns; j++) {
1564 if (SVDw[j] < wmin) SVDw[j] = 0.0;
1565 }
1566 } // omp parallel
1567 // printf("wmin: %le, wmax: %le\n", wmin, wmax);
1568
1569 neBEMState = 7;
1570
1571 return (0);
1572} // end of DecomposeMatrixSVD
NRGLOBAL void svdcmp(double **a, int matrow, int matcol, double *w, double **v)
Definition svdcmp.c:27
INTFACEGLOBAL int neBEMState

Referenced by InvertMatrix().

◆ InvertMatrix()

int InvertMatrix ( void )

Definition at line 1309 of file neBEM.c.

1309 {
1310 int DecomposeMatrixSVD(double **SVDInf, double *SVDw, double **SVDv);
1311
1312 InvMat = dmatrix(1, NbUnknowns, 1, NbEqns);
1313
1314 if (OptGSL) {
1315 printf("InvertMatrix: matrix decomposition using GSL ... ");
1316 printf("no OpenMP implementation ...");
1317 fflush(stdout);
1318
1319 int s; // signum for LU decomposition
1320
1321 gsl_matrix *m = gsl_matrix_alloc(NbUnknowns, NbEqns);
1322 gsl_matrix *inverse = gsl_matrix_alloc(NbUnknowns, NbEqns);
1323 gsl_permutation *perm = gsl_permutation_alloc(NbUnknowns);
1324
1325 for (int i = 0; i < NbUnknowns; ++i)
1326 for (int j = 0; j < NbEqns; ++j)
1327 gsl_matrix_set(m, i, j, Inf[i + 1][j + 1]);
1328
1329 // Make LU decomposition of matrix m
1330 gsl_linalg_LU_decomp(m, perm, &s);
1331
1332 // Invert the matrix m
1333 gsl_linalg_LU_invert(m, perm, inverse);
1334
1335 for (int i = 0; i < NbUnknowns; ++i)
1336 for (int j = 0; j < NbEqns; ++j)
1337 InvMat[i + 1][j + 1] = gsl_matrix_get(inverse, i, j);
1338
1339 gsl_matrix_free(m);
1340 gsl_matrix_free(inverse);
1341 printf("InvertMatrix: ... completed using GSL\n");
1342 } // if OptGSL
1343
1344 if (OptSVD) {
1345 printf("InvertMatrix: matrix decomposition using SVD ... ");
1346 printf("no OpenMP implementation ...");
1347 fflush(stdout);
1348
1349 clock_t SVDstartClock = clock();
1350 printf("ComputeSolution: Decomposing influence matrix ...\n");
1351 fflush(stdout);
1352
1353 // These may as well be declared in neBEM.h because a signicant amount
1354 // of information can be extracted from them in a later version.
1355 double **SVDInf, *SVDw, **SVDv;
1356 SVDInf = dmatrix(1, NbEqns, 1, NbUnknowns);
1357 SVDw = dvector(1, NbUnknowns);
1358 SVDv = dmatrix(1, NbUnknowns, 1, NbUnknowns); // a square matrix!
1359
1360 // Keep the original Inf[] safe
1361 for (int i = 1; i <= NbEqns; i++) {
1362 int j;
1363#ifdef _OPENMP
1364#pragma omp parallel for private(j)
1365#endif
1366 for (j = 1; j <= NbUnknowns; j++)
1367 SVDInf[i][j] = Inf[i][j]; // end of omp parallel for
1368 }
1369
1370 int fstatus = DecomposeMatrixSVD(SVDInf, SVDw, SVDv);
1371 if (fstatus != 0) {
1372 neBEMMessage("ComputeSolution - DecomposeMatrixSVD");
1373 return -1;
1374 }
1375 printf("ComputeSolution: Matrix decomposition over.\n");
1376 clock_t SVDstopClock = clock();
1377 neBEMTimeElapsed(SVDstartClock, SVDstopClock);
1378 printf("to singular value decompose the influence matrix.\n");
1379
1380 // Find the pseudo-inverse of the influence coefficient matrix
1381 double **tmpmat;
1382 tmpmat = dmatrix(1, NbEqns, 1, NbUnknowns);
1383
1384 // calculate w+ (transpose)u
1385 for (int j = 1; j <= NbUnknowns;
1386 j++) { // w+ is obtained by replacing every non-zero diagonal entry of
1387 // [W]
1388 int i;
1389#ifdef _OPENMP
1390#pragma omp parallel for private(i)
1391#endif
1392 for (i = 1; i <= NbEqns; i++) // (note W, not w) by its reciprocal and
1393 { // transposing the resulting matrix
1394 if (SVDw[j]) // nonzero result only if w[i] is nonzero
1395 {
1396 tmpmat[j][i] = SVDInf[i][j] / SVDw[j];
1397 } else {
1398 tmpmat[j][i] = 0.0;
1399 }
1400 } // end of omp parallel for
1401 }
1402
1403 // multiply by [V] to get answer
1404 for (int i = 1; i <= NbUnknowns; i++)
1405 for (int j = 1; j <= NbEqns; j++) {
1406 InvMat[i][j] = 0.0;
1407
1408 int k;
1409 double sum = 0.0;
1410#ifdef _OPENMP
1411#pragma omp parallel for private(k) reduction(+ : sum)
1412#endif
1413 for (k = 1; k <= NbUnknowns; k++)
1414 sum += SVDv[i][k] * tmpmat[k][j]; // end of omp parallel for
1415
1416 InvMat[i][j] = sum;
1417 }
1418
1419 free_dmatrix(tmpmat, 1, NbEqns, 1, NbUnknowns);
1420 // free SVD matrices? may need to be manitained for later use
1421 free_dmatrix(SVDInf, 1, NbEqns, 1, NbUnknowns);
1422 free_dvector(SVDw, 1, NbUnknowns);
1423 free_dmatrix(SVDv, 1, NbUnknowns, 1, NbUnknowns);
1424 printf("InvertMatrix: completed using SVD ...\n");
1425 fflush(stdout);
1426 } // if OptSVD
1427
1428 if (OptLU) {
1429 int *index;
1430 double d, *col, **y;
1431 y = dmatrix(1, NbUnknowns, 1, NbUnknowns);
1432 col = dvector(1, NbUnknowns);
1433 index = ivector(1, NbUnknowns);
1434
1435 double **tmpInf; // temporary influence matrix necessary for ludcmp
1436 tmpInf = dmatrix(1, NbEqns, 1, NbUnknowns);
1437 for (int i = 1; i <= NbEqns; i++) // Keep original Inf[] safe
1438 {
1439 int j;
1440#ifdef _OPENMP
1441#pragma omp parallel for private(j)
1442#endif
1443 for (j = 1; j <= NbUnknowns; j++)
1444 tmpInf[i][j] = Inf[i][j]; // end of omp parallel for
1445 }
1446
1447 printf("InvertMatrix: matrix decomposition using LU ... ");
1448 fflush(stdout);
1449 ludcmp(tmpInf, NbUnknowns, index, &d); // The tmpInf matrix over-written
1450
1451 for (int j = 1; j <= NbUnknowns; j++) // Find inverse by columns.
1452 {
1453 int i;
1454#ifdef _OPENMP
1455#pragma omp parallel for private(i)
1456#endif
1457 for (i = 1; i <= NbUnknowns; i++)
1458 col[i] = 0.0; // end of omp parallel for
1459
1460 col[j] = 1.0;
1461
1462 lubksb(tmpInf, NbUnknowns, index, col); // changed avatar of tmpInf used
1463#ifdef _OPENMP
1464#pragma omp parallel for private(i)
1465#endif
1466 for (i = 1; i <= NbEqns; i++) {
1467 y[i][j] = col[i];
1468 InvMat[i][j] = y[i][j];
1469 } // end of omp parallel for
1470 // printf("\b\b\b\b\b\b");
1471 }
1472
1473 free_ivector(index, 1, NbUnknowns);
1474 free_dvector(col, 1, NbUnknowns);
1476 free_dmatrix(tmpInf, 1, NbEqns, 1, NbUnknowns);
1477
1478 printf("InvertMatrix: completed using LU ...\n");
1479 fflush(stdout);
1480 } // if OptLU
1481
1482 // Since this is occurring within the InvertMatrix function, it is obvious
1483 // that the InfluenceMatrixFlag is true and the LHMatrix has already been
1484 // computed giving rise to a valid Inf[].
1485 // Free Inf[] if validation is not opted for, despite going through a fresh
1486 // solution attempt - highly deprecated!
1488
1489 // It is necessary to write this file always if we want to avoid
1490 // matrix inversion for analyzing the same device with a different BC
1491 printf("OptStoreInvMatrix: %d, OptFormattedFile: %d\n", OptStoreInvMatrix,
1493
1495 printf("storing the inverted matrix in a formatted file ...\n");
1496 fflush(stdout);
1497
1498 FILE *fInv; // can be a very large file - change to raw and zipped format
1499 char InvMFile[256];
1500 strcpy(InvMFile, MeshOutDir);
1501 strcat(InvMFile, "/InvMat.out");
1502 fInv = fopen(InvMFile, "w");
1503
1504 // following line may be removed after the dimension issue is resolved.
1505 fprintf(fInv, "%d %d\n", NbEqns, NbUnknowns);
1506 for (int i = 1; i <= NbEqns; i++)
1507 for (int j = 1; j <= NbUnknowns; j++)
1508 fprintf(fInv, "%.16le\n", InvMat[i][j]);
1509
1510 fclose(fInv);
1511 } // if OptStoreInvMatrix && OptFormattedFile
1512
1514 // not implemented yet
1515 // not implemented
1516 neBEMMessage("InvertMatrix - Binary write not yet implemented.");
1517 return (-1);
1518 }
1519
1520 neBEMState = 7;
1521
1522 return (0);
1523} // end of InvertMatrix
void lubksb(double **a, int n, int *index, double *b)
Definition luc.c:91
void ludcmp(double **a, int n, int *index, double *d)
Definition luc.c:13
int DecomposeMatrixSVD(double **SVDInf, double *SVDw, double **SVDv)
Definition neBEM.c:1527
neBEMGLOBAL double ** InvMat
Definition neBEM.h:197
neBEMGLOBAL char MeshOutDir[256]
Definition neBEM.h:223
neBEMGLOBAL int OptFormattedFile
Definition neBEM.h:56
neBEMGLOBAL int OptUnformattedFile
Definition neBEM.h:57
neBEMGLOBAL int OptStoreInvMatrix
Definition neBEM.h:49
void free_dvector(double *v, long nl, long)
Definition nrutil.c:471
int * ivector(long nl, long nh)
Definition nrutil.c:33
double ** dmatrix(long nrl, long nrh, long ncl, long nch)
Definition nrutil.c:98
void free_ivector(int *v, long nl, long)
Definition nrutil.c:456
double * dvector(long nl, long nh)
Definition nrutil.c:64

Referenced by ComputeSolution(), and Garfield::ComponentNeBem2d::Initialise().

◆ LHMatrix()

int LHMatrix ( void )

Definition at line 307 of file neBEM.c.

307 {
308#ifdef _OPENMP
309 int dbgFn = 0;
310#endif
311 printf(
312 "\nLHMatrix: The size of the Influence coefficient matrix is %d X %d\n",
314 fflush(stdout);
315
316 // The influence coefficient matrix is created only when the
317 // InfluenceMatrixFlag
318 // is true. The other eventualities when this can get created is when
319 // this flag is false but the OptValidateSolution flag is true (through
320 // RepeatLHMatrix (here!)
321 // or1s
322 // OptStoreInflMatrix (in function Solve)).
323 Inf = dmatrix(1, NbEqns, 1, NbUnknowns);
324
325 // Influence coefficient matrix
326 // For each field point where the boundary condition is known (collocation
327 // point), influence from all the source elements needs to be summed up
328 // The field points are followed using elefld (field counter) and the
329 // source elements are followed using elesrc (source counter)
330 // printf("field point: "); // do not remove
331 printf("Computing influence coefficient matrix ... will take time ...\n");
332
333#ifdef _OPENMP
334 int nthreads = 1, tid = 0;
335#pragma omp parallel private(nthreads, tid)
336#endif
337 {
338#ifdef _OPENMP
339 if (dbgFn) {
340 tid = omp_get_thread_num();
341 if (tid == 0) {
342 nthreads = omp_get_num_threads();
343 printf("Starting influence matrix computation with %d threads\n",
344 nthreads);
345 }
346 }
347#endif
348 // printf("Field point:");
349 // fflush(stdout);
350
351 for (int elefld = 1; elefld <= NbElements; ++elefld) {
352 // printf("%6d", elefld);
353 // fflush(stdout); // do not remove
354
355 // Retrieve element properties at the field point
356 // boundary condn applied at collocation point
357 const double xfld = (EleArr + elefld - 1)->BC.CollPt.X;
358 const double yfld = (EleArr + elefld - 1)->BC.CollPt.Y;
359 const double zfld = (EleArr + elefld - 1)->BC.CollPt.Z;
360
361#ifdef _OPENMP
362#pragma omp for
363#endif
364 for (int elesrc = 1; elesrc <= NbElements; ++elesrc) {
365 if (DebugLevel == 301) {
366 printf("\n\nelefld: %d, elesrc: %d\n", elefld, elesrc);
367 }
368
369 // Retrieve element properties at the field point
370 const int primsrc = (EleArr + elesrc - 1)->PrimitiveNb;
371 const double xsrc = (EleArr + elesrc - 1)->G.Origin.X;
372 const double ysrc = (EleArr + elesrc - 1)->G.Origin.Y;
373 const double zsrc = (EleArr + elesrc - 1)->G.Origin.Z;
374
375 if ((EleArr + elesrc - 1)->E.Type == 0) {
376 printf(
377 "LHMatrix: Wrong EType for elesrc %d element %d on %dth "
378 "primitive!\n",
379 elesrc, (EleArr + elesrc - 1)->Id, primsrc);
380 exit(-1);
381 }
382
383 // The total influence is due to elements on the basic device and due to
384 // virtual elements arising out of repetition, reflection etc and not
385 // residing on the basic device
386
387 // Influence due to elements belonging to the basic device
388 {
389 Point3D localP;
390 // Through InitialVector[], field point gets translated to ECS origin
391 // Axes direction are, however, still global which when rotated to ECS
392 // system, yields FinalVector[].
393 { // Rotate point3D from global to local system
394 double InitialVector[3] = {xfld - xsrc, yfld - ysrc, zfld - zsrc};
395 double TransformationMatrix[3][3] = {
396 {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
397 DirnCosn3D *DirCos = &(EleArr + elesrc - 1)->G.DC;
398 TransformationMatrix[0][0] = DirCos->XUnit.X;
399 TransformationMatrix[0][1] = DirCos->XUnit.Y;
400 TransformationMatrix[0][2] = DirCos->XUnit.Z;
401 TransformationMatrix[1][0] = DirCos->YUnit.X;
402 TransformationMatrix[1][1] = DirCos->YUnit.Y;
403 TransformationMatrix[1][2] = DirCos->YUnit.Z;
404 TransformationMatrix[2][0] = DirCos->ZUnit.X;
405 TransformationMatrix[2][1] = DirCos->ZUnit.Y;
406 TransformationMatrix[2][2] = DirCos->ZUnit.Z;
407 double FinalVector[3] = {0., 0., 0.};
408
409 for (int i = 0; i < 3; ++i) {
410 for (int j = 0; j < 3; ++j) {
411 FinalVector[i] += TransformationMatrix[i][j] * InitialVector[j];
412 }
413 }
414
415 localP.X = FinalVector[0];
416 localP.Y = FinalVector[1];
417 localP.Z = FinalVector[2];
418 }
419
420 // Initiate debugging, if necessary
421 if ((elefld == 0) && (elesrc == 0))
422 DebugISLES = 1;
423 else
424 DebugISLES = 0;
425
426 Inf[elefld][elesrc] = ComputeInfluence(elefld, elesrc, &localP,
427 &(EleArr + elesrc - 1)->G.DC);
428 if (DebugLevel == 301) {
429 printf("elefld: %d, elesrc: %d, Influence: %.16lg\n", elefld,
430 elesrc, Inf[elefld][elesrc]);
431 }
432
433 // Take care of reflections of basic device
434 // At present, reflection on a single mirror is allowed
435
436 if (MirrorTypeX[primsrc] || MirrorTypeY[primsrc] ||
437 MirrorTypeZ[primsrc]) {
438 printf(
439 "Mirror not correctly implemented in this version of neBEM "
440 "...\n");
441 exit(0);
442
443 Point3D fldpt, srcpt;
444 DirnCosn3D DirCos;
445
446 fldpt.X = xfld;
447 fldpt.Y = yfld;
448 fldpt.Z = zfld;
449 srcpt.X = xsrc;
450 srcpt.Y = ysrc;
451 srcpt.Z = zsrc;
452
453 if (MirrorTypeX[primsrc]) {
454 MirrorTypeY[primsrc] = 0;
455 MirrorTypeZ[primsrc] = 0;
456 }
457 if (MirrorTypeY[primsrc]) // no point checking MirrorTypeX
458 MirrorTypeZ[primsrc] = 0;
459
460 // If the reflection is other than that of an element (a known space
461 // charge, for example), elesrc should be 0 and no question of
462 // reflection of DC would arise. However, if the space charge is
463 // itself distributed on a surface or in a volume, reflection of DC
464 // etc will be important. What happens when reflection of an wire is
465 // considered? At a later stage, reflection and periodicity should
466 // become a property of an element and should be computed through a
467 // single call of ComputeInfluence
468 if (MirrorTypeX[primsrc]) {
469 localP = ReflectOnMirror('X', elesrc, srcpt, fldpt,
470 MirrorDistXFromOrigin[primsrc], &DirCos);
471 double AddnalInfl =
472 ComputeInfluence(elefld, elesrc, &localP, &DirCos);
473
474 if (MirrorTypeX[primsrc] ==
475 1) // element having opposite charge density
476 Inf[elefld][elesrc] -= AddnalInfl; // classical image charge
477 if (MirrorTypeX[primsrc] ==
478 2) // element having same charge density
479 Inf[elefld][elesrc] += AddnalInfl;
480 }
481
482 if (MirrorTypeY[primsrc]) {
483 localP = ReflectOnMirror('Y', elesrc, srcpt, fldpt,
484 MirrorDistYFromOrigin[primsrc], &DirCos);
485 double AddnalInfl =
486 ComputeInfluence(elefld, elesrc, &localP, &DirCos);
487
488 if (MirrorTypeY[primsrc] ==
489 1) // element having opposite charge density
490 Inf[elefld][elesrc] -= AddnalInfl; // classical image charge
491 if (MirrorTypeY[primsrc] ==
492 2) // element having same charge density
493 Inf[elefld][elesrc] += AddnalInfl;
494 }
495
496 if (MirrorTypeZ[primsrc]) {
497 localP = ReflectOnMirror('Z', elesrc, srcpt, fldpt,
498 MirrorDistZFromOrigin[primsrc], &DirCos);
499 double AddnalInfl =
500 ComputeInfluence(elefld, elesrc, &localP, &DirCos);
501
502 if (MirrorTypeZ[primsrc] ==
503 1) // element having opposite charge density
504 Inf[elefld][elesrc] -= AddnalInfl; // classical image charge
505 if (MirrorTypeZ[primsrc] ==
506 2) // element having same charge density
507 Inf[elefld][elesrc] += AddnalInfl;
508 }
509
510 if (DebugLevel == 301) {
511 printf("After reflection of basic device =>\n");
512 printf("elefld: %d, elesrc: %d, Influence: %.16lg\n", elefld,
513 elesrc, Inf[elefld][elesrc]);
514 }
515 } // reflections of basic device, taken care of
516
517 DebugISLES =
518 0; // Stop beyond basic device - may need changes. CHECK!
519 } // end of influence due to elements belonging to the basic device
520
521 { // Influence due to virtual elements
522
523 // If the source element is repeated due to periodicity (the field
524 // points remain unchanged), the influence at the field point will
525 // change due to additional influence of the extra elements. The
526 // repeated elements have properties identical to the real element
527 // (including the solved value of charge density - otherwise we would
528 // not be able to simply add up the influence at the field point!),
529 // except that its location is determined by direction of periodicty
530 // (at present assumed to be along one of the coordinate axes, but
531 // this constraint can be easily relaxed later - we can have a
532 // direction cosine along which the elements may be repeated) and the
533 // distance of repeatition. Thus, for each repeated element, we need
534 // to compute its position and the rest remains identical as above.
535 // The influence, evaluated as a temporary double, can be added to the
536 // base value computed above. PeriodicInX etc are either zero or +ve
537
538 if ((PeriodicTypeX[primsrc] == 1) || (PeriodicTypeY[primsrc] == 1) ||
539 (PeriodicTypeZ[primsrc] == 1)) {
540 if (PeriodicInX[primsrc] || PeriodicInY[primsrc] ||
541 PeriodicInZ[primsrc]) {
542 for (int xrpt = -PeriodicInX[primsrc];
543 xrpt <= PeriodicInX[primsrc]; ++xrpt) {
544 double XOfRpt = xsrc + XPeriod[primsrc] * (double)xrpt;
545
546 for (int yrpt = -PeriodicInY[primsrc];
547 yrpt <= PeriodicInY[primsrc]; ++yrpt) {
548 double YOfRpt = ysrc + YPeriod[primsrc] * (double)yrpt;
549
550 for (int zrpt = -PeriodicInZ[primsrc];
551 zrpt <= PeriodicInZ[primsrc]; ++zrpt) {
552 double ZOfRpt = zsrc + ZPeriod[primsrc] * (double)zrpt;
553
554 if ((xrpt == 0) && (yrpt == 0) && (zrpt == 0))
555 continue; // this is the base device
556
557 Point3D localP;
558 // axis direction in the global system
559 { // Rotate point3D from global to local system
560 // Vector in the GCS
561 double InitialVector[3] = {xfld - XOfRpt, yfld - YOfRpt,
562 zfld - ZOfRpt};
563 double TransformationMatrix[3][3] = {
564 {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
565 DirnCosn3D *DirCos = &(EleArr + elesrc - 1)->G.DC;
566 TransformationMatrix[0][0] = DirCos->XUnit.X;
567 TransformationMatrix[0][1] = DirCos->XUnit.Y;
568 TransformationMatrix[0][2] = DirCos->XUnit.Z;
569 TransformationMatrix[1][0] = DirCos->YUnit.X;
570 TransformationMatrix[1][1] = DirCos->YUnit.Y;
571 TransformationMatrix[1][2] = DirCos->YUnit.Z;
572 TransformationMatrix[2][0] = DirCos->ZUnit.X;
573 TransformationMatrix[2][1] = DirCos->ZUnit.Y;
574 TransformationMatrix[2][2] = DirCos->ZUnit.Z;
575 double FinalVector[3] = {0., 0., 0.};
576
577 for (int i = 0; i < 3; ++i) {
578 for (int j = 0; j < 3; ++j) {
579 FinalVector[i] +=
580 TransformationMatrix[i][j] * InitialVector[j];
581 }
582 }
583
584 localP.X = FinalVector[0]; // Vector in the ECS
585 localP.Y = FinalVector[1];
586 localP.Z = FinalVector[2];
587 } // Point3D rotated
588
589 // Direction cosines remain unchanged for a regular
590 // repetition
591 double AddnalInfl = ComputeInfluence(
592 elefld, elesrc, &localP, &(EleArr + elesrc - 1)->G.DC);
593 Inf[elefld][elesrc] += AddnalInfl;
594
595 if (DebugLevel == 301) {
596 printf("REPEATED\n");
597 printf("elefld: %d, elesrc: %d\n", elefld, elesrc);
598 printf("xsrc: %lg, ysrc: %lg, zsrc: %lg\n", xsrc, ysrc,
599 zsrc);
600 printf("xrpt: %d, yrpt: %d, zrpt: %d\n", xrpt, yrpt,
601 zrpt);
602 printf("XOfRpt: %lg, YOfRpt: %lg, ZOfRpt: %lg\n", XOfRpt,
603 YOfRpt, ZOfRpt);
604 printf("AddnalInfl: %lg\n", AddnalInfl);
605 printf("Inf: %lg\n", Inf[elefld][elesrc]);
606 }
607
608 // Take care of reflections of repetitions
609 // At present, reflection on a single mirror is allowed
610 if (MirrorTypeX[primsrc] || MirrorTypeY[primsrc] ||
611 MirrorTypeZ[primsrc]) {
612 printf(
613 "Mirror not correctly implemented in this version of "
614 "neBEM ...\n");
615 exit(0);
616
617 Point3D fldpt, srcpt;
618 DirnCosn3D DirCos;
619
620 fldpt.X = xfld;
621 fldpt.Y = yfld;
622 fldpt.Z = zfld;
623 srcpt.X = XOfRpt;
624 srcpt.Y = YOfRpt;
625 srcpt.Z = ZOfRpt;
626
627 if (MirrorTypeX[primsrc]) {
628 MirrorTypeY[primsrc] = 0;
629 MirrorTypeZ[primsrc] = 0;
630 }
631 if (MirrorTypeY[primsrc]) MirrorTypeZ[primsrc] = 0;
632
633 if (MirrorTypeX[primsrc]) {
634 localP = ReflectOnMirror('X', elesrc, srcpt, fldpt,
635 MirrorDistXFromOrigin[primsrc],
636 &DirCos);
637 AddnalInfl =
638 ComputeInfluence(elefld, elesrc, &localP, &DirCos);
639
640 if (MirrorTypeX[primsrc] ==
641 1) // opposite charge density
642 Inf[elefld][elesrc] -=
643 AddnalInfl; // classical image charge
644 if (MirrorTypeX[primsrc] == 2) // same charge density
645 Inf[elefld][elesrc] += AddnalInfl;
646 }
647
648 if (MirrorTypeY[primsrc]) {
649 localP = ReflectOnMirror('Y', elesrc, srcpt, fldpt,
650 MirrorDistYFromOrigin[primsrc],
651 &DirCos);
652 AddnalInfl =
653 ComputeInfluence(elefld, elesrc, &localP, &DirCos);
654
655 if (MirrorTypeY[primsrc] ==
656 1) // opposite charge density
657 Inf[elefld][elesrc] -=
658 AddnalInfl; // classical image charge
659 if (MirrorTypeY[primsrc] == 2) // same charge density
660 Inf[elefld][elesrc] += AddnalInfl;
661 }
662
663 if (MirrorTypeZ[primsrc]) {
664 localP = ReflectOnMirror('Z', elesrc, srcpt, fldpt,
665 MirrorDistZFromOrigin[primsrc],
666 &DirCos);
667 AddnalInfl =
668 ComputeInfluence(elefld, elesrc, &localP, &DirCos);
669
670 if (MirrorTypeZ[primsrc] ==
671 1) // opposite charge density
672 Inf[elefld][elesrc] -=
673 AddnalInfl; // classical image charge
674 if (MirrorTypeZ[primsrc] == 2) // same charge density
675 Inf[elefld][elesrc] += AddnalInfl;
676 }
677
678 if (DebugLevel == 301) {
679 printf("REPEATED and reflected\n");
680 printf("elefld: %d, elesrc: %d\n", elefld, elesrc);
681 printf("xsrc: %lg, ysrc: %lg, zsrc: %lg\n", xsrc, ysrc,
682 zsrc);
683 printf("xrpt: %d, yrpt: %d, zrpt: %d\n", xrpt, yrpt,
684 zrpt);
685 printf("XOfRpt: %lg, YOfRpt: %lg, ZOfRpt: %lg\n",
686 XOfRpt, YOfRpt, ZOfRpt);
687 printf("AddnalInfl: %lg\n", AddnalInfl);
688 printf("Inf: %lg\n", Inf[elefld][elesrc]);
689 }
690 } // reflections of repetitions taken care of
691
692 } // for zrpt
693 } // for yrpt
694 } // for xrpt
695 } // PeriodicInX || PeriodicInY || PeriodicInZ
696 } // PeriodicType == 1
697 } // end of influence due to virtual elements
698
699 } // loop for elesrc, source element (influencing)
700
701 // printf("\b\b\b\b\b\b");
702 } // loop for elefld, field element (influenced)
703 } // pragma omp parallel
704
705 // Enforce total charge on the system to be zero.
706 // All the voltages in the system need to be shifted by an unknown amount
707 // V_shift
708 // V_shift is obtained by introducing one additional row and column and
709 // impposing the constraint that the sum of all the charges in the system is
710 // zero.
711 // Please note that charge = Element Charge Density * Element Area
713 // an additional column
714 for (int row = 1; row <= NbEqns; ++row) {
715 if (((EleArr + row - 1)->E.Type == 1) ||
716 ((EleArr + row - 1)->E.Type == 3)) // The
717 Inf[row][NbUnknowns] = 1.0; // VSystemChargeZero is subtracted only
718 else // from potentials
719 Inf[row][NbUnknowns] = 0.0;
720 }
721
722 // an additional row
723 for (int col = 1; col <= NbUnknowns; ++col)
724 Inf[NbEqns][col] =
725 (EleArr + col - 1)->G.dA; // if charge density is computed
726 // Inf[NbEqns][col] = 1.0; // if charge is computed
727
728 // the last element
729 Inf[NbEqns][NbUnknowns] = 0.0;
730 } // if(OptSystemChargeZero)
731 else {
732 VSystemChargeZero = 0.0;
733 }
734
735 if (NbFloatingConductors) // assume only one floating conductor
736 {
737 // an additional column
738 for (int row = 1; row <= NbEqns; ++row) {
739 int etfld = (EleArr + row - 1)->E.Type;
740 if (etfld == 3) // element of a floating conductor
741 Inf[row][NbUnknowns] = -1.0;
742 else
743 Inf[row][NbUnknowns] = 0.0;
744 } // additional column
745
746 // an additional row
747 for (int col = 1; col <= NbUnknowns; ++col) {
748 int etfld = (EleArr + col - 1)->E.Type;
749 if (etfld == 3) // element of a floating conductor
750 {
751 Inf[NbEqns][col] =
752 (EleArr + col - 1)->G.dA; // if charge density is computed
753 // Inf[NbEqns][col] = 1.0; // if charge is computed
754 } else {
755 Inf[NbEqns][col] = 0.0; // if charge density is computed
756 // Inf[NbEqns][col] = 0.0; // if charge is computed
757 }
758 } // additional row
759
760 // the last element
761 Inf[NbEqns][NbUnknowns] = 0.0;
762 } // if NbFloatingConductors
763
765 printf("storing the influence matrix in a formatted file ...\n");
766 fflush(stdout);
767
768 char InflFile[256];
769 strcpy(InflFile, MeshOutDir);
770 strcat(InflFile, "/Infl.out");
771 FILE *fInf = fopen(InflFile, "w+");
772 if (fInf == NULL) {
773 neBEMMessage("LHMatrix - InflFile");
774 return -1;
775 }
776 fprintf(fInf, "%d %d\n", NbEqns, NbUnknowns);
777
778 for (int elefld = 1; elefld <= NbEqns; ++elefld) {
779 for (int elesrc = 1; elesrc <= NbUnknowns; ++elesrc)
780 fprintf(fInf, "%.16lg\n", Inf[elefld][elesrc]);
781 fprintf(fInf, "\n");
782 }
783
784 fclose(fInf);
785 } // if OptStoreInflMatrix && OptFormattedFile
786
787 if (OptStoreInflMatrix &&
788 OptUnformattedFile) // Raw cannot be implemented now.
789 { // It may be because of the memory allocation using the NR routines -
791 "LHMatrix - Binary write of Infl matrix not implemented yet.\n");
792 return -1;
793
794 char InflFile[256];
795 strcpy(InflFile, MeshOutDir);
796 strcat(InflFile, "/RawInfl.out");
797 FILE *fInf = fopen(InflFile, "wb");
798 if (fInf == NULL) {
799 neBEMMessage("LHMatrix - RawInflFile");
800 return -1;
801 }
802 printf("\nfInf: %p\n", (void *)fInf);
803 int rfw = fwrite(Inf, sizeof(double), NbEqns * NbUnknowns, fInf);
804 fclose(fInf);
805 printf("\nNb of items successfully written in raw mode in %s is %d\n",
806 InflFile, rfw);
807
808 /* following block used to check raw reading from a file written in raw
809 double **RawInf;
810 RawInf = dmatrix(1,NbEqns,1,NbUnknowns);
811 strcpy(InflFile, MeshOutDir); strcat(InflFile, "/RawInfl.out");
812 fInf = fopen(InflFile, "rb");
813 // assert(fInf != NULL);
814 if(fInf == NULL)
815 {
816 neBEMMessage("LHMatrix - RawInflFile");
817 return -1;
818 }
819 rfw = fread(RawInf, sizeof(double), NbEqns*NbUnknowns, fInf);
820 fclose(fInf);
821 printf("Nb of items successfully read in raw mode from %s is %d\n",
822 InflFile, rfw);
823 for(int unknown = 1; unknown <= NbUnknowns; ++unknown)
824 for(int eqn = 1; eqn <= NbEqns; ++eqn)
825 printf("Unknown:%d, Eqn:%d => diff Inf: %lg, RawInf: %lg is
826 %lg\n", unknown, eqn, Inf[unknown][eqn], RawInf[unknown][eqn],
827 fabs(Inf[unknown][eqn] -
828 RawInf[unknown][eqn])); Please do not delete */
829 } // if OptStoreInflMatrix && OptUnformattedFile
830
831 neBEMState = 6;
832
833 return (0);
834} // end of LHMatrix
double ComputeInfluence(int elefld, int elesrc, Point3D *localP, DirnCosn3D *DirCos)
Definition neBEM.c:1652
Point3D ReflectOnMirror(char Axis, int elesrc, Point3D srcpt, Point3D fldpt, double distance, DirnCosn3D *MirroredDC)
Definition neBEM.c:4177
neBEMGLOBAL int * PeriodicInY
Definition neBEM.h:86
neBEMGLOBAL int * MirrorTypeZ
Definition neBEM.h:88
neBEMGLOBAL double * MirrorDistYFromOrigin
Definition neBEM.h:89
neBEMGLOBAL double * ZPeriod
Definition neBEM.h:87
neBEMGLOBAL double VSystemChargeZero
Definition neBEM.h:129
neBEMGLOBAL int * PeriodicTypeX
Definition neBEM.h:85
neBEMGLOBAL int * PeriodicTypeY
Definition neBEM.h:85
neBEMGLOBAL double * MirrorDistZFromOrigin
Definition neBEM.h:90
neBEMGLOBAL double * XPeriod
Definition neBEM.h:87
neBEMGLOBAL int * MirrorTypeY
Definition neBEM.h:88
neBEMGLOBAL int * MirrorTypeX
Definition neBEM.h:88
neBEMGLOBAL int OptStoreInflMatrix
Definition neBEM.h:47
neBEMGLOBAL int * PeriodicInZ
Definition neBEM.h:86
neBEMGLOBAL int * PeriodicInX
Definition neBEM.h:86
neBEMGLOBAL int * PeriodicTypeZ
Definition neBEM.h:85
neBEMGLOBAL double * YPeriod
Definition neBEM.h:87
neBEMGLOBAL double * MirrorDistXFromOrigin
Definition neBEM.h:89
Vector3D ZUnit
Definition Vector.h:38
Vector3D YUnit
Definition Vector.h:37
Vector3D XUnit
Definition Vector.h:36
double Z
Definition Vector.h:31
double X
Definition Vector.h:29

Referenced by ComputeSolution(), and Solve().

◆ ReadInvertedMatrix()

int ReadInvertedMatrix ( void )

Definition at line 1577 of file neBEM.c.

1577 {
1578 // Computation of solution using LU only in this version
1580 // InvMat = dmatrix(1,NbEqns,1,NbUnknowns); // may be reinstated after
1581 // the dimension issue is resolvedint ReadInvertedMatrix(void)
1582 } else {
1583 printf(
1584 "ReadInvertedMatrix: OptFormattedFile and OptUnformattedFile, both are "
1585 "false ... ");
1586 printf(
1587 " Can not read inverted matrix ... returning ...\n");
1588 return (-1);
1589 }
1590
1591 // We need to provide two inputs to implement this
1592 // 1. The fact that we are only changing the BC; MotherInputFile and object
1593 // files should be the same as the original - in such an event, it is
1594 // obvious where the following file is to be found.
1595 // 2. The new set of BCs and the new output file - can be a subdirectory
1596 // of the original (may be default-ed to BC0).
1597 // 3. BC0, if existing, should never be overwritten / removed by the code.
1598 // If at all, it should be removed manually.
1599
1600 if (OptFormattedFile) {
1601 // can be a very large file - change to raw and zipped format
1602 char InvMFile[256];
1603 strcpy(InvMFile, MeshOutDir);
1604 strcat(InvMFile, "/InvMat.out");
1605 FILE *fInv = fopen(InvMFile, "r");
1606 // assert(fInv != NULL);
1607 if (fInv == NULL) {
1608 neBEMMessage("ReadInvertedMatrix - inverted matrix not found.");
1609 return (-1);
1610 }
1611
1612 // Retrieve the dimensions and create matrix
1613 // These lines may be removed once the dimension issue is resolved
1614 // Better still, these numbers can be used to cross-check that there is
1615 // a possibility we are reading the correct inverted matrix - at least the
1616 // dimensions match!
1617 int chkNbEqns, chkNbUnknowns;
1618 fscanf(fInv, "%d %d\n", &chkNbEqns, &chkNbUnknowns);
1619 if ((chkNbEqns != NbEqns) || (chkNbUnknowns != NbUnknowns)) {
1621 "ReadInvertedMatrix - inverted matrix imension do not match!");
1622 fclose(fInv);
1623 return (-1);
1624 }
1625
1626 printf("ReadInvertedMatrix: Matrix dimensions: %d equations, %d unknowns\n",
1628 InvMat = dmatrix(1, NbEqns, 1, NbUnknowns);
1629
1630 for (int i = 1; i <= NbEqns; i++) {
1631 printf("%6d", i); // fflush(stdout);
1632 for (int j = 1; j <= NbUnknowns; j++) {
1633 fscanf(fInv, "%le\n", &InvMat[i][j]);
1634 }
1635 printf("\b\b\b\b\b\b");
1636 }
1637
1638 fclose(fInv);
1639 } // if OptFormattedFile
1640 else if (OptUnformattedFile) // both can not be true!
1641 {
1642 // not implemented
1643 neBEMMessage("ReadInvertedMatrix - Binary read not yet implemented.");
1644 return (-1);
1645 }
1646
1647 neBEMState = 7;
1648
1649 return (0);
1650} // end of ReadInvertedMatrix

Referenced by ComputeSolution().

◆ ReadSolution()

int ReadSolution ( void )

Definition at line 3963 of file neBEM.c.

3963 {
3964 char SolnFile[256];
3965 strcpy(SolnFile, BCOutDir);
3966 strcat(SolnFile, "/Soln.out");
3967 FILE *fSoln = fopen(SolnFile, "r");
3968 // assert(fSoln != NULL);
3969 if (fSoln == NULL) {
3970 neBEMMessage("ReadSoln - unable to open solution file.");
3971 return -1;
3972 }
3973
3974 int itmp;
3975 double dtmp, sol;
3976 char instr[256];
3977 fgets(instr, 256, fSoln);
3978 for (int ele = 1; ele <= NbElements; ++ele) {
3979 fscanf(fSoln, "%d %lg %lg %lg %lg\n", &itmp, &dtmp, &dtmp, &dtmp, &sol);
3980 // assert(ele == itmp);
3981 if (ele != itmp) {
3982 neBEMMessage("ReadSolution - ele_itmp in ReadSolution");
3983 fclose(fSoln);
3984 return -1;
3985 }
3986 (EleArr + ele - 1)->Solution = sol;
3987 }
3988 printf("\nReadSolution: Solution read in for all elements ...\n");
3989 fflush(stdout);
3990
3991 if (NbConstraints) {
3992 if (OptSystemChargeZero) {
3993 fgets(instr, 256, fSoln);
3994 fscanf(fSoln, "%d %lg\n", &NbSystemChargeZero, &VSystemChargeZero);
3995 printf(
3996 "ReadSolution: Read in voltage shift to ensure system charge "
3997 "zero.\n");
3998 }
4000 fgets(instr, 256, fSoln);
4001 fscanf(fSoln, "%d %lg\n", &NbFloatCon, &VFloatCon);
4002 printf("ReadSolution: Read in voltage on floating conductor.\n");
4003 }
4004 fflush(stdout);
4005 } // if NbConstraints
4006
4007 fclose(fSoln);
4008
4009 // Find primitive related charge densities
4010 // OMPCheck - may be parallelized
4011 for (int prim = 1; prim <= NbPrimitives; ++prim) {
4012 double area = 0.0; // need area of the primitive as well!
4013 AvChDen[prim] = 0.0;
4014 AvAsgndChDen[prim] = 0.0;
4015
4016 for (int ele = ElementBgn[prim]; ele <= ElementEnd[prim]; ++ele) {
4017 const double dA = (EleArr + ele - 1)->G.dA;
4018 area += dA;
4019 AvChDen[prim] += (EleArr + ele - 1)->Solution * dA;
4020 AvAsgndChDen[prim] += (EleArr + ele - 1)->Assigned * dA;
4021 }
4022
4023 AvChDen[prim] /= area;
4024 AvAsgndChDen[prim] /= area;
4025 }
4026
4027 neBEMState = 9;
4028
4029 return (0);
4030} // end of neBEMReadSolution
neBEMGLOBAL double VFloatCon
Definition neBEM.h:135
neBEMGLOBAL int NbPrimitives
Definition neBEM.h:64
neBEMGLOBAL double * AvAsgndChDen
Definition neBEM.h:97
neBEMGLOBAL int * ElementEnd
Definition neBEM.h:101
neBEMGLOBAL double * AvChDen
Definition neBEM.h:97
neBEMGLOBAL double * Solution
Definition neBEM.h:197
neBEMGLOBAL int * ElementBgn
Definition neBEM.h:101
neBEMGLOBAL char BCOutDir[256]
Definition neBEM.h:223

Referenced by neBEMSolve().

◆ ReflectOnMirror()

Point3D ReflectOnMirror ( char Axis,
int elesrc,
Point3D srcpt,
Point3D fldpt,
double distance,
DirnCosn3D * MirroredDC )

Definition at line 4177 of file neBEM.c.

4178 {
4179 Vector3D n; // define mirror by a bi-vector perpendicular to it
4180 Point3D Image; // reflected point by mirror assumed at origin
4181
4182 switch (Axis) {
4183 case 'x':
4184 case 'X':
4185 n.X = 1.0;
4186 n.Y = 0.0;
4187 n.Z = 0.0;
4188
4189 Image = ReflectPoint3DByMirrorAtOrigin(&srcpt, &n);
4190 Image.X += 2.0 * distance;
4191
4192 MirroredDC->XUnit.X = -(EleArr + elesrc - 1)->G.DC.XUnit.X;
4193 MirroredDC->XUnit.Y = (EleArr + elesrc - 1)->G.DC.XUnit.Y;
4194 MirroredDC->XUnit.Z = (EleArr + elesrc - 1)->G.DC.XUnit.Z;
4195 MirroredDC->YUnit.X = -(EleArr + elesrc - 1)->G.DC.YUnit.X;
4196 MirroredDC->YUnit.Y = (EleArr + elesrc - 1)->G.DC.YUnit.Y;
4197 MirroredDC->YUnit.Z = (EleArr + elesrc - 1)->G.DC.YUnit.Z;
4198 MirroredDC->ZUnit.X = -(EleArr + elesrc - 1)->G.DC.ZUnit.X;
4199 MirroredDC->ZUnit.Y = (EleArr + elesrc - 1)->G.DC.ZUnit.Y;
4200 MirroredDC->ZUnit.Z = (EleArr + elesrc - 1)->G.DC.ZUnit.Z;
4201 break;
4202
4203 case 'y':
4204 case 'Y':
4205 n.X = 0.0;
4206 n.Y = 1.0;
4207 n.Z = 0.0;
4208
4209 Image = ReflectPoint3DByMirrorAtOrigin(&srcpt, &n);
4210 Image.Y += 2.0 * distance;
4211
4212 MirroredDC->XUnit.X = (EleArr + elesrc - 1)->G.DC.XUnit.X;
4213 MirroredDC->XUnit.Y = -(EleArr + elesrc - 1)->G.DC.XUnit.Y;
4214 MirroredDC->XUnit.Z = (EleArr + elesrc - 1)->G.DC.XUnit.Z;
4215 MirroredDC->YUnit.X = (EleArr + elesrc - 1)->G.DC.YUnit.X;
4216 MirroredDC->YUnit.Y = -(EleArr + elesrc - 1)->G.DC.YUnit.Y;
4217 MirroredDC->YUnit.Z = (EleArr + elesrc - 1)->G.DC.YUnit.Z;
4218 MirroredDC->ZUnit.X = (EleArr + elesrc - 1)->G.DC.ZUnit.X;
4219 MirroredDC->ZUnit.Y = -(EleArr + elesrc - 1)->G.DC.ZUnit.Y;
4220 MirroredDC->ZUnit.Z = (EleArr + elesrc - 1)->G.DC.ZUnit.Z;
4221 break;
4222
4223 case 'z':
4224 case 'Z':
4225 n.X = 0.0;
4226 n.Y = 0.0;
4227 n.Z = 1.0;
4228
4229 Image = ReflectPoint3DByMirrorAtOrigin(&srcpt, &n);
4230 Image.Z += 2.0 * distance;
4231
4232 MirroredDC->XUnit.X = (EleArr + elesrc - 1)->G.DC.XUnit.X;
4233 MirroredDC->XUnit.Y = (EleArr + elesrc - 1)->G.DC.XUnit.Y;
4234 MirroredDC->XUnit.Z = -(EleArr + elesrc - 1)->G.DC.XUnit.Z;
4235 MirroredDC->YUnit.X = (EleArr + elesrc - 1)->G.DC.YUnit.X;
4236 MirroredDC->YUnit.Y = (EleArr + elesrc - 1)->G.DC.YUnit.Y;
4237 MirroredDC->YUnit.Z = -(EleArr + elesrc - 1)->G.DC.YUnit.Z;
4238 MirroredDC->ZUnit.X = (EleArr + elesrc - 1)->G.DC.ZUnit.X;
4239 MirroredDC->ZUnit.Y = (EleArr + elesrc - 1)->G.DC.ZUnit.Y;
4240 MirroredDC->ZUnit.Z = -(EleArr + elesrc - 1)->G.DC.ZUnit.Z;
4241 break;
4242
4243 default:
4244 printf("Axis not chosen properly!!! No reflection occurred!\n");
4245 Image.X = srcpt.X;
4246 Image.Y = srcpt.Y;
4247 Image.Z = srcpt.Z;
4248 } // switch on Axis ends
4249
4250 // printf("Axis: %c, distance: %lg\n", Axis, distance);
4251 // printf("srcpt: %lg, %lg, %lg\n", srcpt.X, srcpt.Y, srcpt.Z);
4252 // printf("Image: %lg, %lg, %lg\n", Image.X, Image.Y, Image.Z);
4253 // getchar();
4254
4255 // traslated to ECS origin, but axes direction as in global system
4256 Point3D globalP, localP;
4257 globalP.X = fldpt.X - Image.X;
4258 globalP.Y = fldpt.Y - Image.Y;
4259 globalP.Z = fldpt.Z - Image.Z;
4260
4261 // entirely in ECS
4262 return (localP = RotatePoint3D(&globalP, MirroredDC, global2local));
4263} // ReflectOnMirror ends
Point3D ReflectPoint3DByMirrorAtOrigin(Point3D *p1, Vector3D *n)
Definition Vector.c:465
Point3D RotatePoint3D(Point3D *A, DirnCosn3D *DC, int Sense)
Definition Vector.c:339

Referenced by ElePFAtPoint(), and LHMatrix().

◆ ReflectPrimitiveOnMirror()

Point3D ReflectPrimitiveOnMirror ( char Axis,
int primsrc,
Point3D srcpt,
Point3D fldpt,
double distance,
DirnCosn3D * MirroredDC )

Definition at line 4088 of file neBEM.c.

4090 {
4091 Vector3D n; // define mirror by a bi-vector perpendicular to it
4092 Point3D Image; // reflected point by mirror assumed at origin
4093
4094 switch (Axis) {
4095 case 'x':
4096 case 'X':
4097 n.X = 1.0;
4098 n.Y = 0.0;
4099 n.Z = 0.0;
4100
4101 Image = ReflectPoint3DByMirrorAtOrigin(&srcpt, &n);
4102 Image.X += 2.0 * distance;
4103
4104 MirroredDC->XUnit.X = -PrimDC[primsrc].XUnit.X;
4105 MirroredDC->XUnit.Y = PrimDC[primsrc].XUnit.Y;
4106 MirroredDC->XUnit.Z = PrimDC[primsrc].XUnit.Z;
4107 MirroredDC->YUnit.X = -PrimDC[primsrc].YUnit.X;
4108 MirroredDC->YUnit.Y = PrimDC[primsrc].YUnit.Y;
4109 MirroredDC->YUnit.Z = PrimDC[primsrc].YUnit.Z;
4110 MirroredDC->ZUnit.X = -PrimDC[primsrc].ZUnit.X;
4111 MirroredDC->ZUnit.Y = PrimDC[primsrc].ZUnit.Y;
4112 MirroredDC->ZUnit.Z = PrimDC[primsrc].ZUnit.Z;
4113 break;
4114
4115 case 'y':
4116 case 'Y':
4117 n.X = 0.0;
4118 n.Y = 1.0;
4119 n.Z = 0.0;
4120
4121 Image = ReflectPoint3DByMirrorAtOrigin(&srcpt, &n);
4122 Image.Y += 2.0 * distance;
4123
4124 MirroredDC->XUnit.X = PrimDC[primsrc].XUnit.X;
4125 MirroredDC->XUnit.Y = -PrimDC[primsrc].XUnit.Y;
4126 MirroredDC->XUnit.Z = PrimDC[primsrc].XUnit.Z;
4127 MirroredDC->YUnit.X = PrimDC[primsrc].YUnit.X;
4128 MirroredDC->YUnit.Y = -PrimDC[primsrc].YUnit.Y;
4129 MirroredDC->YUnit.Z = PrimDC[primsrc].YUnit.Z;
4130 MirroredDC->ZUnit.X = PrimDC[primsrc].ZUnit.X;
4131 MirroredDC->ZUnit.Y = -PrimDC[primsrc].ZUnit.Y;
4132 MirroredDC->ZUnit.Z = PrimDC[primsrc].ZUnit.Z;
4133 break;
4134
4135 case 'z':
4136 case 'Z':
4137 n.X = 0.0;
4138 n.Y = 0.0;
4139 n.Z = 1.0;
4140
4141 Image = ReflectPoint3DByMirrorAtOrigin(&srcpt, &n);
4142 Image.Z += 2.0 * distance;
4143
4144 MirroredDC->XUnit.X = PrimDC[primsrc].XUnit.X;
4145 MirroredDC->XUnit.Y = PrimDC[primsrc].XUnit.Y;
4146 MirroredDC->XUnit.Z = -PrimDC[primsrc].XUnit.Z;
4147 MirroredDC->YUnit.X = PrimDC[primsrc].YUnit.X;
4148 MirroredDC->YUnit.Y = PrimDC[primsrc].YUnit.Y;
4149 MirroredDC->YUnit.Z = -PrimDC[primsrc].YUnit.Z;
4150 MirroredDC->ZUnit.X = PrimDC[primsrc].ZUnit.X;
4151 MirroredDC->ZUnit.Y = PrimDC[primsrc].ZUnit.Y;
4152 MirroredDC->ZUnit.Z = -PrimDC[primsrc].ZUnit.Z;
4153 break;
4154
4155 default:
4156 printf("Axis not chosen properly!!! No reflection occurred!\n");
4157 Image.X = srcpt.X;
4158 Image.Y = srcpt.Y;
4159 Image.Z = srcpt.Z;
4160 } // switch on Axis ends
4161
4162 // printf("Axis: %c, distance: %lg\n", Axis, distance);
4163 // printf("srcpt: %lg, %lg, %lg\n", srcpt.X, srcpt.Y, srcpt.Z);
4164 // printf("Image: %lg, %lg, %lg\n", Image.X, Image.Y, Image.Z);
4165 // getchar();
4166
4167 // traslated to ECS origin, but axes direction as in global system
4168 Point3D globalP, localP;
4169 globalP.X = fldpt.X - Image.X;
4170 globalP.Y = fldpt.Y - Image.Y;
4171 globalP.Z = fldpt.Z - Image.Z;
4172
4173 // entirely in ECS
4174 return (localP = RotatePoint3D(&globalP, MirroredDC, global2local));
4175} // ReflectPrimtiveOnMirror ends here
neBEMGLOBAL DirnCosn3D * PrimDC
Definition neBEM.h:81

Referenced by ElePFAtPoint().

◆ RHVector()

int RHVector ( void )

Definition at line 1976 of file neBEM.c.

1976 {
1977 double value, valueKnCh, valueChUp;
1978
1979 if (TimeStep == 1) RHS = dvector(1, NbEqns);
1980
1981 char outfile[256];
1982 strcpy(outfile, BCOutDir);
1983 strcat(outfile, "/BCondns.out");
1984 FILE *fout = fopen(outfile, "w");
1985 fprintf(fout, "#BCondn Vector\n");
1986 fprintf(fout, "#elefld\tAssigned\tBC\tKnCh\tChUp\tRHValue\n");
1987
1988 printf("created BCondns.out file ...\n");
1989 fflush(stdout);
1990
1991 for (int elefld = 1; elefld <= NbElements; ++elefld) {
1992 if (0) printf("\nIn RHVector, elefld: %d\n", elefld);
1993 value = valueKnCh = valueChUp = 0.0;
1994 value = (EleArr + elefld - 1)
1995 ->BC.Value; // previouly this line was within case 1
1996
1997 switch ((EleArr + elefld - 1)->E.Type) {
1998 case 1: // Conducting surfaces
1999 // value = (EleArr+elefld-1)->BC.Value;
2000 if (OptKnCh) {
2001 valueKnCh = ValueKnCh(elefld); // effect of all known charges
2002 if (isnan(valueKnCh)) exit(-1);
2003 if (isinf(valueKnCh)) exit(-1);
2004 }
2005 if (OptChargingUp) {
2006 valueChUp = ValueChUp(elefld); // effect of device charging up
2007 if (isnan(valueChUp)) exit(-1);
2008 if (isinf(valueChUp)) exit(-1);
2009 }
2010 RHS[elefld] = value - valueKnCh - valueChUp;
2011 break;
2012 case 2: // Conducting surfaces with known charge
2013 printf("Conducting surface with charge not implemented.\n");
2014 fclose(fout);
2015 return -1;
2016 break; // NOTE: no RHVector
2017 case 3: // Floating conducting surfaces
2018 if (OptKnCh) {
2019 valueKnCh = ValueKnCh(elefld);
2020 if (isnan(valueKnCh)) exit(-1);
2021 if (isinf(valueKnCh)) exit(-1);
2022 }
2023 if (OptChargingUp) {
2024 valueChUp = ValueChUp(elefld);
2025 if (isnan(valueChUp)) exit(-1);
2026 if (isinf(valueChUp)) exit(-1);
2027 }
2028 RHS[elefld] = value - valueKnCh - valueChUp;
2029 break;
2030 case 4: // Dielectric interfaces
2031 if (OptKnCh) {
2032 valueKnCh = ContinuityKnCh(elefld);
2033 if (isnan(valueKnCh)) exit(-1);
2034 if (isinf(valueKnCh)) exit(-1);
2035 }
2036 if (OptChargingUp) {
2037 valueChUp = ContinuityChUp(elefld);
2038 if (isnan(valueChUp)) exit(-1);
2039 if (isinf(valueChUp)) exit(-1);
2040 }
2041 RHS[elefld] = value - valueKnCh - valueChUp;
2042 RHS[elefld] +=
2043 (EleArr + elefld - 1)->Assigned; // effect due to charging up
2044 break;
2045 case 5: // Dielectric interfaces with known charge
2046 if (OptKnCh) {
2047 valueKnCh = ContinuityKnCh(elefld);
2048 if (isnan(valueKnCh)) exit(-1);
2049 if (isinf(valueKnCh)) exit(-1);
2050 }
2051 if (OptChargingUp) {
2052 valueChUp = ContinuityChUp(elefld);
2053 if (isnan(valueChUp)) exit(-1);
2054 if (isinf(valueChUp)) exit(-1);
2055 }
2056 RHS[elefld] = value - valueKnCh - valueChUp; // Check Bardhan's eqn 16
2057 RHS[elefld] +=
2058 (EleArr + elefld - 1)->Assigned; // effect due to assigned
2059 // charge; what happens when assigned elements are charged up in
2060 // addition?
2061 break;
2062 case 6: // E parallel symmetry boundary
2063 printf("Symmetry boundary, E parallel not implemented yet.\n");
2064 return -1;
2065 break;
2066 case 7: // E perpendicular symmetry boundary
2067 printf("Symmetry boundary, E perpendicular not implemented yet.\n");
2068 return -1;
2069 break;
2070 default:
2071 printf("elefld in RHVector out of range ... returning\n");
2072 return -1;
2073 }
2074 fprintf(fout, "%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n", elefld,
2075 (EleArr + elefld - 1)->G.Origin.X,
2076 (EleArr + elefld - 1)->G.Origin.Y,
2077 (EleArr + elefld - 1)->G.Origin.Z, (EleArr + elefld - 1)->Assigned,
2078 value, valueKnCh, valueChUp, RHS[elefld]);
2079 } // for elefld ends
2080
2081 // Floating conductor are long neglected. Needs close inspection.
2082 if (NbConstraints) {
2083 for (int eqn = NbElements + 1; eqn <= NbEqns; ++eqn) {
2084 if (eqn ==
2085 NbSystemChargeZero) // if row corresponds to zero-charge condition
2086 {
2087 double assigned, dA, SumAssigned = 0.0;
2088 // can be parallelized
2089 for (int ele = 1; ele <= NbElements; ++ele) {
2090 assigned = (EleArr + ele - 1)->Assigned;
2091 dA = (EleArr + ele - 1)->G.dA;
2092 SumAssigned += assigned * dA; // charge density * element area
2093 }
2094 RHS[eqn] =
2095 -SumAssigned; // applied charge considered - too small change
2096 RHS[eqn] =
2097 0.0; // applied charge not considered while meeting constraint
2098 } // if eqn == NbSystemChargeZero
2099 else {
2100 RHS[eqn] = 0.0;
2101 }
2102 }
2103 } // if NbConstraints
2104
2105 printf("computations for RHVector completed ...\n");
2106 fflush(stdout);
2107
2108 fclose(fout);
2109
2110 neBEMState = 5;
2111
2112 return (0);
2113} // RHVector
double ValueKnCh(int elefld)
Definition neBEM.c:2120
double ContinuityKnCh(int elefld)
Definition neBEM.c:2290
double ContinuityChUp(int elefld)
Definition neBEM.c:2616
double ValueChUp(int elefld)
Definition neBEM.c:2470
neBEMGLOBAL double * RHS
Definition neBEM.h:197

Referenced by ComputeSolution().

◆ SatisfyContinuity()

double SatisfyContinuity ( int elefld,
int elesrc,
Point3D * localP,
DirnCosn3D * DirCos )

Definition at line 1797 of file neBEM.c.

1798 {
1799 if (DebugLevel == 301) {
1800 printf("In SatisfyContinuity ...\n");
1801 }
1802
1803 double value = 0.0;
1804 Vector3D localF, globalF;
1805
1806 // For self-influence, lmsrc is equal to lmfld which allows the following.
1807 // Additional conditions on distances ensure that periodic copies are not
1808 // treated as `self'.
1809 // Here, we have the additional problem of correctly treating the
1810 // self-influence of traingular elements for which the co-ordinate origin
1811 // does not coincide with the barycentre and thus elesrc and elefld
1812 // are separated from each other by lx/3 and lz/3 in X and Z,
1813 // respectively. The Y coordinates match, however, since the element
1814 // local coordinate system has the Y=0 plane coinciding with the element
1815 // on which the element is lying.
1816 // Since elefld and elesrc are the same for self-influence, etsrc can either
1817 // be 4 or 5. So, the check on the value of etsrc is superfluous, and two
1818 // separate if blocks are merged into one.
1819 // Check for other "special" cases!
1820 if ((elefld == elesrc) &&
1821 (fabs(localP->X) < (EleArr + elesrc - 1)->G.LX / 2.0) &&
1822 (fabs(localP->Y) < MINDIST) &&
1823 (fabs(localP->Z) <
1824 (EleArr + elesrc - 1)->G.LZ / 2.0)) // self-inf for DD intrfc
1825 { // consistent with eqn 18 of Bardhan's paper where lmsrc is inverse
1826 value = 1.0 / (2.0 * EPS0 * (EleArr + elesrc - 1)->E.Lambda);
1827 } // of the multiplying factor of roe(r). EPS0 arises due to electrostatics.
1828 else {
1829 value = 0.0;
1830 // Following fluxes in the influencing ECS
1831 switch ((EleArr + elesrc - 1)->G.Type) {
1832 case 4: // rectangular element
1833 RecFlux(elesrc, localP, &localF);
1834 break;
1835 case 3: // triangular element
1836 TriFlux(elesrc, localP, &localF);
1837 break;
1838 case 2: // linear (wire) element
1839 WireFlux(elesrc, localP, &localF);
1840 break;
1841 default:
1842 printf("Geometrical type out of range! ... exiting ...\n");
1843 exit(-1);
1844 break; // never comes here
1845 } // switch over gtsrc ends
1846
1847 // flux in the global co-ordinate system
1848 // globalF = RotateVector3D(&localF, &(EleArr+elesrc-1)->G.DC,
1849 // local2global);
1850 globalF = RotateVector3D(&localF, DirCos, local2global);
1851
1852 // Fluxes in the influenced ECS co-ordinate system
1853 localF =
1854 RotateVector3D(&globalF, &(EleArr + elefld - 1)->G.DC, global2local);
1855
1856 value = -localF.Y;
1857 // normal derivative of Green's function is - normal force
1858 // (changed from -Fy to +Fy on 02/11/11 - CHECK!!!);
1859 // From = to +=, further change on 04/11/11; Reverted + to - on 05/11/11
1860 } // else self-influence
1861
1862 return (value);
1863} // end of SatisfyContinuity

Referenced by ComputeInfluence().

◆ SatisfyValue()

double SatisfyValue ( int elesrc,
Point3D * localP )

Definition at line 1759 of file neBEM.c.

1759 {
1760 if (DebugLevel == 301) {
1761 printf("In SatisfyValue ...\n");
1762 }
1763
1764 double value;
1765
1766 switch ((EleArr + elesrc - 1)->G.Type) {
1767 case 4: // rectangular element
1768 value = RecPot(elesrc, localP);
1769 return (value);
1770 // return(value/dA);
1771 break;
1772 case 3: // triangular element
1773 value = TriPot(elesrc, localP);
1774 return (value);
1775 // return(value/dA);
1776 break;
1777 case 2: // linear (wire) element
1778 value = WirePot(elesrc, localP);
1779 return (value);
1780 // return(value/dA);
1781 break;
1782 default:
1783 printf("Geometrical type out of range! ... exiting ...\n");
1784 return (-1);
1785 break; // never comes here
1786 } // switch over gtsrc ends
1787} // end of SatisfyValue
double TriPot(int ele, Point3D *localP)
double WirePot(int ele, Point3D *localP)
double RecPot(int ele, Point3D *localP)

Referenced by ComputeInfluence().

◆ Solve()

int Solve ( void )

Definition at line 2784 of file neBEM.c.

2784 {
2785 double **RawInf = NULL;
2786 int LHMatrix(void);
2787
2789 // printf("Solution array allocated\n"); fflush(stdout);
2790
2791 printf("\ncomputing solution for each element: ");
2792
2793 for (int i = 1; i <= NbUnknowns; i++) {
2794 printf("%6d ...", i);
2795 Solution[i] = 0.0;
2796
2797 double sum = 0.0;
2798 int j;
2799#ifdef _OPENMP
2800#pragma omp parallel for private(j) reduction(+ : sum)
2801#endif
2802 for (j = 1; j <= NbUnknowns; j++) {
2803 sum += InvMat[i][j] * RHS[j]; // new
2804 }
2805
2806 Solution[i] = sum;
2807 printf("\b\b\b\b\b\b\b\b\b\b");
2808 }
2809 fflush(stdout);
2810
2811 printf("\nsolution over for all elements ...\n");
2812 fflush(stdout);
2813
2814 if (NbConstraints) {
2815 if (OptSystemChargeZero) {
2817 printf("\nsolution over for system charge zero constraint ...\n");
2818 fflush(stdout);
2819 }
2820
2823 printf(
2824 "\nsolution over for floating conductor charge zero constraint "
2825 "...\n");
2826 fflush(stdout);
2827 }
2828 } // if NbConstraints
2829
2830 // Update the element structure array and write the solution in a file
2831 char SolnFile[256];
2832 strcpy(SolnFile, BCOutDir);
2833 strcat(SolnFile, "/Soln.out");
2834 FILE *fSoln = fopen(SolnFile, "w");
2835 if (fSoln == NULL) {
2836 neBEMMessage("Solve - SolnFile");
2837 return -1;
2838 }
2839 fprintf(fSoln, "#EleNb\tX\tY\tZ\tSolution\tAssigned\tTotal\n");
2840 for (int ele = 1; ele <= NbElements; ++ele) {
2841 (EleArr + ele - 1)->Solution = Solution[ele];
2842 fprintf(fSoln, "%d\t%lg\t%lg\t%lg\t%.16lg\t%.16lg\t%.16lg\n", ele,
2843 (EleArr + ele - 1)->G.Origin.X, (EleArr + ele - 1)->G.Origin.Y,
2844 (EleArr + ele - 1)->G.Origin.Z, (EleArr + ele - 1)->Solution,
2845 (EleArr + ele - 1)->Assigned,
2846 ((EleArr + ele - 1)->Solution + (EleArr + ele - 1)->Assigned));
2847 }
2848
2849 if (NbConstraints) {
2850 if (OptSystemChargeZero) {
2851 fprintf(fSoln, "#NbSystemChargeZero\tVSystemChargeZero\n");
2852 fprintf(fSoln, "# %d\t%lg\n", NbSystemChargeZero, VSystemChargeZero);
2853 }
2855 fprintf(fSoln, "#NbFloatCon\tVFloatCon\n");
2856 fprintf(fSoln, "# %d\t%lg\n", NbFloatCon, VFloatCon);
2857 }
2858 } // if NbConstraints
2859
2860 fclose(fSoln);
2861
2862 // Find primitive related charge densities
2863 char PrimSolnFile[256];
2864 strcpy(PrimSolnFile, BCOutDir);
2865 strcat(PrimSolnFile, "/PrimSoln.out");
2866 FILE *fPrimSoln = fopen(PrimSolnFile, "w");
2867 if (fPrimSoln == NULL) {
2868 neBEMMessage("Solve - PrimSolnFile");
2869 return -1;
2870 }
2871 fprintf(fPrimSoln,
2872 "#PrimNb\tEleBgn\tEleEnd\tX\tY\tZ\tAvChDen\tAvAsgndChDen\n");
2873 // OMPCheck - may be parallelized
2874 for (int prim = 1; prim <= NbPrimitives; ++prim) {
2875 double area = 0.0; // need area of the primitive as well!
2876 AvChDen[prim] = 0.0;
2877 AvAsgndChDen[prim] = 0.0;
2878
2879 for (int ele = ElementBgn[prim]; ele <= ElementEnd[prim]; ++ele) {
2880 area += (EleArr + ele - 1)->G.dA;
2881 AvChDen[prim] += (EleArr + ele - 1)->Solution * (EleArr + ele - 1)->G.dA;
2882 AvAsgndChDen[prim] +=
2883 (EleArr + ele - 1)->Assigned * (EleArr + ele - 1)->G.dA;
2884 }
2885
2886 AvChDen[prim] /= area;
2887 AvAsgndChDen[prim] /= area;
2888
2889 fprintf(fPrimSoln, "%d\t%d\t%d\t%lg\t%lg\t%lg\t%.16lg\t%.16g\n", prim,
2890 ElementBgn[prim], ElementEnd[prim], PrimOriginX[prim],
2891 PrimOriginY[prim], PrimOriginZ[prim], AvChDen[prim],
2892 AvAsgndChDen[prim]);
2893 }
2894
2895 fclose(fPrimSoln);
2896
2897 neBEMState = 9;
2898
2899 // Validate the obtained solution, i.e., estimate the residue at the
2900 // collocation points. The validation is expected to be carried out by the
2901 // influence matrix already available in the memory. If, however, for some
2902 // reason (such as a repeat calculation), the influence coefficient matrix is
2903 // not available, it can be retrieved by carrying out the computation once
2904 // again, reading it from a formatted or an unformatted file.
2905 printf("OptValidateSolution: %d\n", OptValidateSolution);
2906 if (OptValidateSolution) {
2907 printf("Computing solution at the collocation points for comparison.\n");
2908 fflush(stdout);
2909
2910 if (InfluenceMatrixFlag) {
2911 printf("Influence matrix in memory ...\n");
2912 }
2913
2914 // Only when InfluenceMatrixFlag is false, the influence coefficient
2915 // reamins uncomputed. Then the question of re-computation or reading it
2916 // from a file (formatted / unformatted) arises.
2917 if (!InfluenceMatrixFlag) {
2918 if (TimeStep != 1) {
2919 // influence matrix to be computed only in the first time step
2920 printf("Influence matrix in memory ...\n");
2921 } else {
2922 printf("Influence matrix NOT in memory ...\n");
2923
2924 if (OptRepeatLHMatrix) {
2925 printf("repeating influence coefficient matrix computation ...\n");
2926
2927 int fstatus = LHMatrix();
2928 // assert(fstatus == 0);
2929 if (fstatus != 0) {
2930 neBEMMessage("Solve - LHMatrix in OptRepeatLHMatrix");
2931 return -1;
2932 }
2933 }
2934
2936 printf(
2937 "reading influence coefficient matrix from formatted file...\n");
2938
2939 char InflFile[256];
2940 strcpy(InflFile, MeshOutDir);
2941 strcat(InflFile, "/Infl.out");
2942 FILE *fInf = fopen(InflFile, "r");
2943 // assert(fInf != NULL);
2944 if (fInf == NULL) {
2945 neBEMMessage("Solve - InflFile in OptValidate.");
2946 return 1;
2947 }
2948
2949 int chkNbEqns, chkNbUnknowns;
2950 fscanf(fInf, "%d %d\n", &chkNbEqns, &chkNbUnknowns);
2951 if ((chkNbEqns != NbEqns) || (chkNbUnknowns != NbUnknowns)) {
2952 neBEMMessage("Solve - matrix dimension do not match!");
2953 fclose(fInf);
2954 return (-1);
2955 }
2956
2957 printf("Solve: Matrix dimensions: %d equations, %d unknowns\n",
2959
2960 Inf = dmatrix(1, NbEqns, 1, NbUnknowns);
2961
2962 for (int elefld = 1; elefld <= NbEqns; ++elefld)
2963 for (int elesrc = 1; elesrc <= NbUnknowns; ++elesrc)
2964 fscanf(fInf, "%le\n", &Inf[elefld][elesrc]);
2965 fclose(fInf);
2966 } // stored influence matrix and formatted file
2967
2970 "Solve - Binary read of Infl matrix not implemented yet.\n");
2971 return -1;
2972
2973 RawInf = dmatrix(1, NbEqns, 1, NbUnknowns);
2974
2975 printf(
2976 "reading influence coefficient matrix from unformatted file "
2977 "...\n");
2978
2979 char InflFile[256];
2980 strcpy(InflFile, MeshOutDir);
2981 strcat(InflFile, "/RawInfl.out");
2982 printf("\nread from file %s\n", InflFile);
2983 fflush(stdout);
2984 FILE *fInf = fopen(InflFile, "rb");
2985 // assert(fInf != NULL);
2986 if (fInf == NULL) {
2987 neBEMMessage("Solve - RawInflFile in OptValidate");
2988 return -1;
2989 }
2990 printf("\nfInf: %p\n", (void *)fInf);
2991 int rfw = fread(RawInf, sizeof(double), NbEqns * NbUnknowns, fInf);
2992 fclose(fInf);
2993 printf("\nNb of items successfully read from raw mode in %s is %d\n",
2994 InflFile, rfw);
2995 fflush(stdout);
2996
2997 for (int unknown = 1; unknown <= NbUnknowns; ++unknown)
2998 for (int eqn = 1; eqn <= NbEqns; ++eqn)
2999 printf(
3000 "Unknown:%d, Eqn:%d => diff Inf: %lg, RawInf: %lg is %lg\n",
3001 unknown, eqn, Inf[unknown][eqn], RawInf[unknown][eqn],
3002 fabs(Inf[unknown][eqn] - RawInf[unknown][eqn]));
3003 } // if OptStoreInflMatrix and Unformatted file
3004 } // else TimeStep != 1
3005 } // if(!InfluenceMatrixFlag)
3006
3007 // Used for all validations except where re-computation is forced which
3008 // is taken care of by else of this if
3009 if (Inf || RawInf) {
3010 double XChk;
3011 char Chkfile[256];
3012 strcpy(Chkfile, BCOutDir);
3013 strcat(Chkfile, "/XChk.out");
3014 FILE *fChk = fopen(Chkfile, "w"); // assert(fChk != NULL);
3015 if (fChk == NULL) {
3016 neBEMMessage("Solve - ChkFile");
3017 return -1;
3018 }
3019 fprintf(fChk, "#Row\tGivenPot\tError\n");
3020
3021 int ElementOfMaxError = 1;
3022 double *Error, MaxError = 0.0;
3023 Error = dvector(1, NbEqns);
3024 int elesrc;
3025#ifdef _OPENMP
3026#pragma omp parallel for private(elesrc)
3027#endif
3028 for (int elefld = 1; elefld <= NbEqns; elefld++) {
3029 XChk = 0.0;
3030 for (elesrc = 1; elesrc <= NbUnknowns; elesrc++) {
3033 XChk += RawInf[elefld][elesrc] * Solution[elesrc];
3034 else
3035 XChk += Inf[elefld][elesrc] * Solution[elesrc];
3036 } // for elesrc
3037 Error[elefld] = fabs(RHS[elefld] - XChk);
3038
3039 if (Error[elefld] > MaxError) {
3040 MaxError = Error[elefld]; // update maximum error related info
3041 ElementOfMaxError = elefld;
3042 }
3043 } // for elefld
3044 for (int elefld = 1; elefld <= NbEqns; elefld++)
3045 fprintf(fChk, "%d\t%lg\t%lg\n", elefld, RHS[elefld], Error[elefld]);
3046 free_dvector(Error, 1, NbEqns);
3047
3048 printf("Computed values at the collocation points for comparison.\n");
3049 printf("Error maximum on element %d and its magnitude is %lg.\n",
3050 ElementOfMaxError, MaxError);
3051 fflush(stdout);
3052
3053 fprintf(fChk, "#Error maximum on element %d and its magnitude is %lg.\n",
3054 ElementOfMaxError, MaxError);
3055 fclose(fChk);
3056
3062 free_dmatrix(RawInf, 1, NbEqns, 1, NbUnknowns);
3063 } // if(Inf || RawInf)
3064 else {
3065 if (OptForceValidation) {
3067 "Solve - Infl matrix not available, re-computation forced.\n");
3068
3069 int fstatus = LHMatrix();
3070 if (fstatus != 0) {
3071 neBEMMessage("Solve - LHMatrix in forced OptRepeatLHMatrix");
3072 return -1;
3073 }
3074
3075 double XChk;
3076 char Chkfile[256];
3077 FILE *fChk;
3078 strcpy(Chkfile, BCOutDir);
3079 strcat(Chkfile, "/XChk.out");
3080 fChk = fopen(Chkfile, "w");
3081 if (fChk == NULL) {
3082 neBEMMessage("Solve - ChkFile in forced recomputation");
3083 return -1;
3084 }
3085 fprintf(fChk, "#Row\tGivenPot\tComputedPot\tDiff\n");
3086
3087 int ElementOfMaxError = 1;
3088 double Error, MaxError = 0.0;
3089 for (int elefld = 1; elefld <= NbEqns; elefld++) {
3090 XChk = 0.0;
3091 for (int elesrc = 1; elesrc <= NbUnknowns; elesrc++) {
3092 XChk += Inf[elefld][elesrc] * Solution[elesrc];
3093 }
3094 Error = fabs(RHS[elefld] - XChk);
3095 fprintf(fChk, "%d\t%lg\t%lg\t%lg\n", elefld, RHS[elefld], XChk,
3096 Error);
3097
3098 if (Error > MaxError) {
3099 MaxError = Error; // update maximum error related info
3100 ElementOfMaxError = elefld;
3101 }
3102 }
3103
3104 printf("Computed values at the collocation points for comparison.\n");
3105 printf("Error maximum on element %d and its magnitude is %lg.\n",
3106 ElementOfMaxError, MaxError);
3107 fflush(stdout);
3108
3109 fprintf(fChk,
3110 "#Error maximum on element %d and its magnitude is %lg.\n",
3111 ElementOfMaxError, MaxError);
3112 fclose(fChk);
3113
3115 } else { // this is not an error, though
3116 neBEMMessage("Solve - Infl matrix not available, no validation.\n");
3117 }
3118 } // else (Inf || RawInf)
3119 } // if(OptValidateSolution)
3120
3121 /*
3122 Find out the error at relevant points. The points are chosen such that the
3123 mesh can be refined based on the errors obtained. For example, if the error
3124 at a particular point is found to be more than acceptable, an additional
3125 element (including necessary adjustment of the elements on the primitive
3126 in question) can easily be inserted to improve the accuracy of the solution.
3127 The validation is NOT expected to be carried out by the influence matrix
3128 already available in the memory, since the evaluation points no longer
3129 coincides with the collocation (qualocation?) points used to compute the
3130 solution. There is no question of repeating the computation, as while
3131 estimating the RESIDUE (Validation block immediately above this paragraph).
3132 The relevant points of rectangular elements are the centroid of four
3133 possible quadrants, whereas, for the triangular elements, these are the
3134 centroid of the rectangular and two barycentre of the two possible right
3135 triangles.
3136 In the following figures, X-s represent the collocation points, while x-s
3137 represent the points introduced to estimate error. For the triangle,
3138 there is a possibility of overlap of X and x of the rectangle.
3139 ----------------------------
3140 | | |
3141 | x | x |
3142 | | |
3143 --------------X-------------
3144 | | |
3145 | x | x |
3146 | | |
3147 ----------------------------
3148 \
3149 |\
3150 | \
3151 |x \
3152 ----\
3153 | |\
3154 | x | \
3155 | |x \
3156 --------\
3157 */
3158
3159 OptEstimateError = 0; // temporary measure
3160 printf("OptEstimateError: %d\n", OptEstimateError);
3161 if (OptEstimateError) {
3162 printf(
3163 "Properties at non-collocation points on element for estimating "
3164 "error.\n");
3165 fflush(stdout);
3166
3167 double Err;
3168 int PrimitiveOfMaxError = 1;
3169 int ElementOfMaxError = 1;
3170 double MaxError = 0.0;
3171 double xerrMax = 0.0, yerrMax = 0.0, zerrMax = 0.0;
3172
3173 char Errfile[256];
3174 strcpy(Errfile, BCOutDir);
3175 strcat(Errfile, "/Errors.out");
3176 FILE *fErr = fopen(Errfile, "w");
3177 if (fErr == NULL) {
3178 neBEMMessage("Solve - ErrFile");
3179 return -1;
3180 }
3181 fprintf(fErr,
3182 "#Prim\tEle\tGType\tIType\txerr\tyerr\tzerr\tGivenBC\tComputVal\tDi"
3183 "ff\n");
3184
3185 // loop over all the elements - at present wire elements are NOT
3186 // considered!! We now also have ElementBgn and ElementEnd for each
3187 // primitive. So, we can loop over primtives and, within it, the necessary
3188 // elements can be considered. It turns out that going from primitive to
3189 // primitive can result into lesser computation. For example, E.Type for an
3190 // entire primitive is the same, and does not need to be evaluated from
3191 // element to element. conductor-dielectric: 1, conductor with known charge:
3192 // 2 conductor with floating potential: 3, dielectric-dielectric: 4
3193 // dielectric with known charge: 5
3194 // At present, error-accounting is maintained only for two types of
3195 // interfaces, C-D interfaces (specified voltage), D-D interfaces
3196 // (continuity of displacement current implied)
3197 // OMPCheck - may be parallelized
3198 for (int prim = 1; prim <= NbPrimitives; ++prim)
3199 for (int ele = ElementBgn[prim]; ele <= ElementEnd[prim]; ++ele) {
3200 double normdisp = 1.0e-8; // displacement in the normal direction
3201
3202 if ((prim == 91) && (ele == 337)) // debug switches are turned on
3203 {
3204 // DebugLevel = 1001;
3205 DebugLevel = 0;
3206 } else // turn off switches
3207 {
3208 DebugLevel = 0;
3209 }
3210
3211 // find relevant points for this element; compute PF and cross-check
3212 // with BC
3213 if ((EleArr + ele - 1)->G.Type == 2) continue;
3214
3215 if ((EleArr + ele - 1)->G.Type == 3) // triangle
3216 { // 3 points need to be considered for estimating error (above fig)
3217 Point3D globalP;
3218 double Potential;
3219 Vector3D globalF, localF;
3220 double x0 = (EleArr + ele - 1)->G.Vertex[0].X;
3221 double y0 = (EleArr + ele - 1)->G.Vertex[0].Y;
3222 double z0 = (EleArr + ele - 1)->G.Vertex[0].Z;
3223 double x1 = (EleArr + ele - 1)->G.Vertex[1].X;
3224 double y1 = (EleArr + ele - 1)->G.Vertex[1].Y;
3225 double z1 = (EleArr + ele - 1)->G.Vertex[1].Z;
3226 double x2 = (EleArr + ele - 1)->G.Vertex[2].X;
3227 double y2 = (EleArr + ele - 1)->G.Vertex[2].Y;
3228 double z2 = (EleArr + ele - 1)->G.Vertex[2].Z;
3229 double xb = (x0 + x1 + x2) / 3.0; // b for barycentre
3230 double yb = (y0 + y1 + y2) / 3.0; // b for barycentre
3231 double zb = (z0 + z1 + z2) / 3.0; // b for barycentre
3232
3233 // check values at the barycentre
3234 globalP.X = xb;
3235 globalP.Y = yb;
3236 globalP.Z = zb;
3237 if (InterfaceType[prim] == 1) {
3238 PFAtPoint(&globalP, &Potential, &globalF);
3239 Err = ApplPot[prim] - Potential;
3240 fprintf(fErr, "%d\t%d\t%d\t%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
3241 prim, ele, 3, 1, xb, yb, zb, ApplPot[prim], Potential, Err);
3242 if (fabs(Err) > fabs(MaxError)) {
3243 MaxError = Err;
3244 PrimitiveOfMaxError = prim;
3245 ElementOfMaxError = ele;
3246 xerrMax = xb;
3247 yerrMax = yb;
3248 zerrMax = zb;
3249 }
3250 }
3251 if (InterfaceType[prim] ==
3252 4) { // compute displacement currents in the two dielectrics
3253 double xplus = xb + (EleArr + ele - 1)->G.DC.XUnit.X * normdisp;
3254 xplus += (EleArr + ele - 1)->G.DC.YUnit.X * normdisp;
3255 xplus += (EleArr + ele - 1)->G.DC.ZUnit.X * normdisp;
3256 double yplus = yb + (EleArr + ele - 1)->G.DC.XUnit.Y * normdisp;
3257 yplus += (EleArr + ele - 1)->G.DC.YUnit.Y * normdisp;
3258 yplus += (EleArr + ele - 1)->G.DC.ZUnit.Y * normdisp;
3259 double zplus = zb + (EleArr + ele - 1)->G.DC.XUnit.Z * normdisp;
3260 zplus += (EleArr + ele - 1)->G.DC.YUnit.Z * normdisp;
3261 zplus += (EleArr + ele - 1)->G.DC.ZUnit.Z * normdisp;
3262 globalP.X = xplus;
3263 globalP.Y = yplus;
3264 globalP.Z = zplus;
3265 PFAtPoint(&globalP, &Potential, &globalF);
3266 localF // Flux in the ECS
3267 = RotateVector3D(&globalF, &(EleArr + ele - 1)->G.DC,
3268 global2local);
3269 double value1 = -localF.Y;
3270 double xminus = xb - (EleArr + ele - 1)->G.DC.XUnit.X * normdisp;
3271 xminus -= (EleArr + ele - 1)->G.DC.YUnit.X * normdisp;
3272 xminus -= (EleArr + ele - 1)->G.DC.ZUnit.X * normdisp;
3273 double yminus = yb - (EleArr + ele - 1)->G.DC.XUnit.Y * normdisp;
3274 yminus -= (EleArr + ele - 1)->G.DC.YUnit.Y * normdisp;
3275 yminus -= (EleArr + ele - 1)->G.DC.ZUnit.Y * normdisp;
3276 double zminus = zb - (EleArr + ele - 1)->G.DC.XUnit.Z * normdisp;
3277 zminus -= (EleArr + ele - 1)->G.DC.YUnit.Z * normdisp;
3278 zminus -= (EleArr + ele - 1)->G.DC.ZUnit.Z * normdisp;
3279 globalP.X = xminus;
3280 globalP.Y = yminus;
3281 globalP.Z = zminus;
3282 PFAtPoint(&globalP, &Potential, &globalF);
3283 localF // Flux in the ECS
3284 = RotateVector3D(&globalF, &(EleArr + ele - 1)->G.DC,
3285 global2local);
3286 double value2 = -localF.Y;
3287 double epsratio = (Epsilon2[prim] / Epsilon1[prim]);
3288 Err = epsratio - (value1 / value2);
3289 fprintf(fErr, "%d\t%d\t%d\t%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
3290 prim, ele, 3, 4, xb, yb, zb, epsratio, (value1 / value2),
3291 Err);
3292 if (fabs(Err) > fabs(MaxError)) {
3293 MaxError = Err;
3294 PrimitiveOfMaxError = prim;
3295 ElementOfMaxError = ele;
3296 xerrMax = xb;
3297 yerrMax = yb;
3298 zerrMax = zb;
3299 }
3300 }
3301
3302 // values at the centroid of the rectangular part
3303 double xerr =
3304 0.25 * (x0 + 0.5 * (x0 + x1) + 0.5 * (x1 + x2) + 0.5 * (x0 + x2));
3305 double yerr =
3306 0.25 * (y0 + 0.5 * (y0 + y1) + 0.5 * (y1 + y2) + 0.5 * (y0 + y2));
3307 double zerr =
3308 0.25 * (z0 + 0.5 * (z0 + z1) + 0.5 * (z1 + z2) + 0.5 * (z0 + z2));
3309 globalP.X = xerr;
3310 globalP.Y = yerr;
3311 globalP.Z = zerr;
3312 // At present, error-accounting is maintained only for two types of
3313 // interfaces, C-D interfaces (specified voltage), D-D interfaces
3314 // (continuity of displacement current implied)
3315 if (InterfaceType[prim] == 1) {
3316 PFAtPoint(&globalP, &Potential, &globalF);
3317 Err = ApplPot[prim] - Potential;
3318 fprintf(fErr, "%d\t%d\t%d\t%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
3319 prim, ele, 3, 1, xerr, yerr, zerr, ApplPot[prim], Potential,
3320 Err);
3321 if (fabs(Err) > fabs(MaxError)) {
3322 MaxError = Err;
3323 PrimitiveOfMaxError = prim;
3324 ElementOfMaxError = ele;
3325 xerrMax = xerr;
3326 yerrMax = yerr;
3327 zerrMax = zerr;
3328 }
3329 }
3330 if (InterfaceType[prim] ==
3331 4) { // compute displacement currents in the two dielectrics
3332 double xplus = xerr + (EleArr + ele - 1)->G.DC.XUnit.X * normdisp;
3333 xplus += (EleArr + ele - 1)->G.DC.YUnit.X * normdisp;
3334 xplus += (EleArr + ele - 1)->G.DC.ZUnit.X * normdisp;
3335 double yplus = yerr + (EleArr + ele - 1)->G.DC.XUnit.Y * normdisp;
3336 yplus += (EleArr + ele - 1)->G.DC.YUnit.Y * normdisp;
3337 yplus += (EleArr + ele - 1)->G.DC.ZUnit.Y * normdisp;
3338 double zplus = zerr + (EleArr + ele - 1)->G.DC.XUnit.Z * normdisp;
3339 zplus += (EleArr + ele - 1)->G.DC.YUnit.Z * normdisp;
3340 zplus += (EleArr + ele - 1)->G.DC.ZUnit.Z * normdisp;
3341 globalP.X = xplus;
3342 globalP.Y = yplus;
3343 globalP.Z = zplus;
3344 PFAtPoint(&globalP, &Potential, &globalF);
3345 localF // Flux in the ECS
3346 = RotateVector3D(&globalF, &(EleArr + ele - 1)->G.DC,
3347 global2local);
3348 double value1 = -localF.Y;
3349 double xminus = xerr - (EleArr + ele - 1)->G.DC.XUnit.X * normdisp;
3350 xminus -= (EleArr + ele - 1)->G.DC.YUnit.X * normdisp;
3351 xminus -= (EleArr + ele - 1)->G.DC.ZUnit.X * normdisp;
3352 double yminus = yerr - (EleArr + ele - 1)->G.DC.XUnit.Y * normdisp;
3353 yminus -= (EleArr + ele - 1)->G.DC.YUnit.Y * normdisp;
3354 yminus -= (EleArr + ele - 1)->G.DC.ZUnit.Y * normdisp;
3355 double zminus = zerr - (EleArr + ele - 1)->G.DC.XUnit.Z * normdisp;
3356 zminus -= (EleArr + ele - 1)->G.DC.YUnit.Z * normdisp;
3357 zminus -= (EleArr + ele - 1)->G.DC.ZUnit.Z * normdisp;
3358 globalP.X = xminus;
3359 globalP.Y = yminus;
3360 globalP.Z = zminus;
3361 PFAtPoint(&globalP, &Potential, &globalF);
3362 localF // Flux in the ECS
3363 = RotateVector3D(&globalF, &(EleArr + ele - 1)->G.DC,
3364 global2local);
3365 double value2 = -localF.Y;
3366 double epsratio = (Epsilon2[prim] / Epsilon1[prim]);
3367 Err = epsratio - (value1 / value2);
3368 fprintf(fErr, "%d\t%d\t%d\t%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
3369 prim, ele, 3, 4, xerr, yerr, zerr, epsratio,
3370 (value1 / value2), Err);
3371 if (fabs(Err) > fabs(MaxError)) {
3372 MaxError = Err;
3373 PrimitiveOfMaxError = prim;
3374 ElementOfMaxError = ele;
3375 xerrMax = xerr;
3376 yerrMax = yerr;
3377 zerrMax = zerr;
3378 }
3379 }
3380
3381 // barycentre of the triangular part towards +ve X-axis of ECS
3382 xerr = (0.5 * (x0 + x1) + 0.5 * (x1 + x2) + x1) / 3.0;
3383 yerr = (0.5 * (y0 + y1) + 0.5 * (y1 + y2) + y1) / 3.0;
3384 zerr = (0.5 * (z0 + z1) + 0.5 * (z1 + z2) + z1) / 3.0;
3385 globalP.X = xerr;
3386 globalP.Y = yerr;
3387 globalP.Z = zerr;
3388 // At present, error-accounting is maintained only for two types of
3389 // interfaces, C-D interfaces (specified voltage), D-D interfaces
3390 // (continuity of displacement current implied)
3391 if (InterfaceType[prim] == 1) {
3392 PFAtPoint(&globalP, &Potential, &globalF);
3393 Err = ApplPot[prim] - Potential;
3394 fprintf(fErr, "%d\t%d\t%d\t%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
3395 prim, ele, 3, 1, xerr, yerr, zerr, ApplPot[prim], Potential,
3396 Err);
3397 if (fabs(Err) > fabs(MaxError)) {
3398 MaxError = Err;
3399 PrimitiveOfMaxError = prim;
3400 ElementOfMaxError = ele;
3401 xerrMax = xerr;
3402 yerrMax = yerr;
3403 zerrMax = zerr;
3404 }
3405 }
3406 if (InterfaceType[prim] ==
3407 4) { // compute displacement currents in the two dielectrics
3408 double xplus = xerr + (EleArr + ele - 1)->G.DC.XUnit.X * normdisp;
3409 xplus += (EleArr + ele - 1)->G.DC.YUnit.X * normdisp;
3410 xplus += (EleArr + ele - 1)->G.DC.ZUnit.X * normdisp;
3411 double yplus = yerr + (EleArr + ele - 1)->G.DC.XUnit.Y * normdisp;
3412 yplus += (EleArr + ele - 1)->G.DC.YUnit.Y * normdisp;
3413 yplus += (EleArr + ele - 1)->G.DC.ZUnit.Y * normdisp;
3414 double zplus = zerr + (EleArr + ele - 1)->G.DC.XUnit.Z * normdisp;
3415 zplus += (EleArr + ele - 1)->G.DC.YUnit.Z * normdisp;
3416 zplus += (EleArr + ele - 1)->G.DC.ZUnit.Z * normdisp;
3417 globalP.X = xplus;
3418 globalP.Y = yplus;
3419 globalP.Z = zplus;
3420 PFAtPoint(&globalP, &Potential, &globalF);
3421 localF // Flux in the ECS
3422 = RotateVector3D(&globalF, &(EleArr + ele - 1)->G.DC,
3423 global2local);
3424 double value1 = -localF.Y;
3425 double xminus = xerr - (EleArr + ele - 1)->G.DC.XUnit.X * normdisp;
3426 xminus -= (EleArr + ele - 1)->G.DC.YUnit.X * normdisp;
3427 xminus -= (EleArr + ele - 1)->G.DC.ZUnit.X * normdisp;
3428 double yminus = yerr - (EleArr + ele - 1)->G.DC.XUnit.Y * normdisp;
3429 yminus -= (EleArr + ele - 1)->G.DC.YUnit.Y * normdisp;
3430 yminus -= (EleArr + ele - 1)->G.DC.ZUnit.Y * normdisp;
3431 double zminus = zerr - (EleArr + ele - 1)->G.DC.XUnit.Z * normdisp;
3432 zminus -= (EleArr + ele - 1)->G.DC.YUnit.Z * normdisp;
3433 zminus -= (EleArr + ele - 1)->G.DC.ZUnit.Z * normdisp;
3434 globalP.X = xminus;
3435 globalP.Y = yminus;
3436 globalP.Z = zminus;
3437 PFAtPoint(&globalP, &Potential, &globalF);
3438 localF // Flux in the ECS
3439 = RotateVector3D(&globalF, &(EleArr + ele - 1)->G.DC,
3440 global2local);
3441 double value2 = -localF.Y;
3442 double epsratio = (Epsilon2[prim] / Epsilon1[prim]);
3443 Err = epsratio - (value1 / value2);
3444 fprintf(fErr, "%d\t%d\t%d\t%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
3445 prim, ele, 3, 4, xerr, yerr, zerr, epsratio,
3446 (value1 / value2), Err);
3447 if (fabs(Err) > fabs(MaxError)) {
3448 MaxError = Err;
3449 PrimitiveOfMaxError = prim;
3450 ElementOfMaxError = ele;
3451 xerrMax = xerr;
3452 yerrMax = yerr;
3453 zerrMax = zerr;
3454 }
3455 }
3456
3457 // barycentre of the triangular part towards +ve Z-axis of ECS
3458 xerr = (0.5 * (x0 + x2) + 0.5 * (x1 + x2) + x2) / 3.0;
3459 yerr = (0.5 * (y0 + y2) + 0.5 * (y1 + y2) + y2) / 3.0;
3460 zerr = (0.5 * (z0 + z2) + 0.5 * (z1 + z2) + z2) / 3.0;
3461 globalP.X = xerr;
3462 globalP.Y = yerr;
3463 globalP.Z = zerr;
3464 // At present, error-accounting is maintained only for two types of
3465 // interfaces, C-D interfaces (specified voltage), D-D interfaces
3466 // (continuity of displacement current implied)
3467 if (InterfaceType[prim] == 1) {
3468 PFAtPoint(&globalP, &Potential, &globalF);
3469 Err = ApplPot[prim] - Potential;
3470 fprintf(fErr, "%d\t%d\t%d\t%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
3471 prim, ele, 3, 1, xerr, yerr, zerr, ApplPot[prim], Potential,
3472 Err);
3473 if (fabs(Err) > fabs(MaxError)) {
3474 MaxError = Err;
3475 PrimitiveOfMaxError = prim;
3476 ElementOfMaxError = ele;
3477 xerrMax = xerr;
3478 yerrMax = yerr;
3479 zerrMax = zerr;
3480 }
3481 }
3482 if (InterfaceType[prim] ==
3483 4) { // compute displacement currents in the two dielectrics
3484 double xplus = xerr + (EleArr + ele - 1)->G.DC.XUnit.X * normdisp;
3485 xplus += (EleArr + ele - 1)->G.DC.YUnit.X * normdisp;
3486 xplus += (EleArr + ele - 1)->G.DC.ZUnit.X * normdisp;
3487 double yplus = yerr + (EleArr + ele - 1)->G.DC.XUnit.Y * normdisp;
3488 yplus += (EleArr + ele - 1)->G.DC.YUnit.Y * normdisp;
3489 yplus += (EleArr + ele - 1)->G.DC.ZUnit.Y * normdisp;
3490 double zplus = zerr + (EleArr + ele - 1)->G.DC.XUnit.Z * normdisp;
3491 zplus += (EleArr + ele - 1)->G.DC.YUnit.Z * normdisp;
3492 zplus += (EleArr + ele - 1)->G.DC.ZUnit.Z * normdisp;
3493 globalP.X = xplus;
3494 globalP.Y = yplus;
3495 globalP.Z = zplus;
3496 PFAtPoint(&globalP, &Potential, &globalF);
3497 localF // Flux in the ECS
3498 = RotateVector3D(&globalF, &(EleArr + ele - 1)->G.DC,
3499 global2local);
3500 double value1 = -localF.Y;
3501 double xminus = xerr - (EleArr + ele - 1)->G.DC.XUnit.X * normdisp;
3502 xminus -= (EleArr + ele - 1)->G.DC.YUnit.X * normdisp;
3503 xminus -= (EleArr + ele - 1)->G.DC.ZUnit.X * normdisp;
3504 double yminus = yerr - (EleArr + ele - 1)->G.DC.XUnit.Y * normdisp;
3505 yminus -= (EleArr + ele - 1)->G.DC.YUnit.Y * normdisp;
3506 yminus -= (EleArr + ele - 1)->G.DC.ZUnit.Y * normdisp;
3507 double zminus = zerr - (EleArr + ele - 1)->G.DC.XUnit.Z * normdisp;
3508 zminus -= (EleArr + ele - 1)->G.DC.YUnit.Z * normdisp;
3509 zminus -= (EleArr + ele - 1)->G.DC.ZUnit.Z * normdisp;
3510 globalP.X = xminus;
3511 globalP.Y = yminus;
3512 globalP.Z = zminus;
3513 PFAtPoint(&globalP, &Potential, &globalF);
3514 localF // Flux in the ECS
3515 = RotateVector3D(&globalF, &(EleArr + ele - 1)->G.DC,
3516 global2local);
3517 double value2 = -localF.Y;
3518 double epsratio = (Epsilon2[prim] / Epsilon1[prim]);
3519 Err = epsratio - (value1 / value2);
3520 fprintf(fErr, "%d\t%d\t%d\t%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
3521 prim, ele, 4, 4, xerr, yerr, zerr, epsratio,
3522 (value1 / value2), Err);
3523 if (fabs(Err) > fabs(MaxError)) {
3524 MaxError = Err;
3525 PrimitiveOfMaxError = prim;
3526 ElementOfMaxError = ele;
3527 xerrMax = xerr;
3528 yerrMax = yerr;
3529 zerrMax = zerr;
3530 }
3531 }
3532 } // if triangle
3533
3534 if ((EleArr + ele - 1)->G.Type == 4) // rectangle
3535 { // 4 points need to be considered for estimating error (above fig)
3536 Point3D globalP;
3537 double Potential;
3538 Vector3D globalF, localF;
3539
3540 double x0 = (EleArr + ele - 1)->G.Vertex[0].X;
3541 double y0 = (EleArr + ele - 1)->G.Vertex[0].Y;
3542 double z0 = (EleArr + ele - 1)->G.Vertex[0].Z;
3543 double x1 = (EleArr + ele - 1)->G.Vertex[1].X;
3544 double y1 = (EleArr + ele - 1)->G.Vertex[1].Y;
3545 double z1 = (EleArr + ele - 1)->G.Vertex[1].Z;
3546 double x2 = (EleArr + ele - 1)->G.Vertex[2].X;
3547 double y2 = (EleArr + ele - 1)->G.Vertex[2].Y;
3548 double z2 = (EleArr + ele - 1)->G.Vertex[2].Z;
3549 double x3 = (EleArr + ele - 1)->G.Vertex[3].X;
3550 double y3 = (EleArr + ele - 1)->G.Vertex[3].Y;
3551 double z3 = (EleArr + ele - 1)->G.Vertex[3].Z;
3552 double xo = 0.25 * (x0 + x1 + x2 + x3); // o for origin
3553 double yo = 0.25 * (y0 + y1 + y2 + y3); // o for origin
3554 double zo = 0.25 * (z0 + z1 + z2 + z3); // o for origin
3555
3556 // check values at the centroid of the element
3557 globalP.X = xo;
3558 globalP.Y = yo;
3559 globalP.Z = zo;
3560 if (InterfaceType[prim] == 1) {
3561 PFAtPoint(&globalP, &Potential, &globalF);
3562 Err = ApplPot[prim] - Potential;
3563 fprintf(fErr, "%d\t%d\t%d\t%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
3564 prim, ele, 4, 1, xo, yo, zo, ApplPot[prim], Potential, Err);
3565 if (fabs(Err) > fabs(MaxError)) {
3566 MaxError = Err;
3567 PrimitiveOfMaxError = prim;
3568 ElementOfMaxError = ele;
3569 xerrMax = xo;
3570 yerrMax = yo;
3571 zerrMax = zo;
3572 }
3573 }
3574 if (InterfaceType[prim] == 4) {
3575 // compute displacement currents in the two dielectrics
3576 double xplus = xo + (EleArr + ele - 1)->G.DC.XUnit.X * normdisp;
3577 xplus += (EleArr + ele - 1)->G.DC.YUnit.X * normdisp;
3578 xplus += (EleArr + ele - 1)->G.DC.ZUnit.X * normdisp;
3579 double yplus = yo + (EleArr + ele - 1)->G.DC.XUnit.Y * normdisp;
3580 yplus += (EleArr + ele - 1)->G.DC.YUnit.Y * normdisp;
3581 yplus += (EleArr + ele - 1)->G.DC.ZUnit.Y * normdisp;
3582 double zplus = zo + (EleArr + ele - 1)->G.DC.XUnit.Z * normdisp;
3583 zplus += (EleArr + ele - 1)->G.DC.YUnit.Z * normdisp;
3584 zplus += (EleArr + ele - 1)->G.DC.ZUnit.Z * normdisp;
3585 globalP.X = xplus;
3586 globalP.Y = yplus;
3587 globalP.Z = zplus;
3588 PFAtPoint(&globalP, &Potential, &globalF);
3589 localF // Flux in the ECS
3590 = RotateVector3D(&globalF, &(EleArr + ele - 1)->G.DC,
3591 global2local);
3592 double dispfld1 = Epsilon1[prim] * localF.Y;
3593 double xminus = xo - (EleArr + ele - 1)->G.DC.XUnit.X * normdisp;
3594 xminus -= (EleArr + ele - 1)->G.DC.YUnit.X * normdisp;
3595 xminus -= (EleArr + ele - 1)->G.DC.ZUnit.X * normdisp;
3596 double yminus = yo - (EleArr + ele - 1)->G.DC.XUnit.Y * normdisp;
3597 yminus -= (EleArr + ele - 1)->G.DC.YUnit.Y * normdisp;
3598 yminus -= (EleArr + ele - 1)->G.DC.ZUnit.Y * normdisp;
3599 double zminus = zo - (EleArr + ele - 1)->G.DC.XUnit.Z * normdisp;
3600 zminus -= (EleArr + ele - 1)->G.DC.YUnit.Z * normdisp;
3601 zminus -= (EleArr + ele - 1)->G.DC.ZUnit.Z * normdisp;
3602 globalP.X = xminus;
3603 globalP.Y = yminus;
3604 globalP.Z = zminus;
3605 PFAtPoint(&globalP, &Potential, &globalF);
3606 localF // Flux in the ECS
3607 = RotateVector3D(&globalF, &(EleArr + ele - 1)->G.DC,
3608 global2local);
3609 double dispfld2 = Epsilon2[prim] * localF.Y;
3610 globalP.X = xo;
3611 globalP.Y = yo;
3612 globalP.Z = zo;
3613 PFAtPoint(&globalP, &Potential, &globalF);
3614 localF // Flux in the ECS
3615 = RotateVector3D(&globalF, &(EleArr + ele - 1)->G.DC,
3616 global2local);
3617 double dispfldo = Epsilon1[prim] * localF.Y;
3618 Err = (dispfld2 - dispfld1) /
3619 dispfldo; // - (&(EleArr+ele-1)->Assigned);
3620 fprintf(fErr, "%d\t%d\t%d\t%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
3621 prim, ele, 4, 4, xo, yo, zo, dispfld1, dispfld2, Err);
3622 if ((prim == 91) && (ele == 337)) {
3623 // debug switches are turned on
3624 double TotalInfl = 0.0;
3625 for (int elesrc = 1; elesrc <= NbElements; ++elesrc) {
3626 TotalInfl += Inf[ele][elesrc] * (EleArr + elesrc - 1)->Solution;
3627 }
3628 printf("TotalInfl: %lg\n", TotalInfl);
3629 printf(
3630 "%d\t%d\t%d\t%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\t%"
3631 "lg\n",
3632 prim, ele, 4, 4, xo, yo, zo, Epsilon1[prim], Epsilon2[prim],
3633 dispfld1, dispfld2, dispfldo, Err);
3634 }
3635 if (fabs(Err) > fabs(MaxError)) {
3636 MaxError = Err;
3637 PrimitiveOfMaxError = prim;
3638 ElementOfMaxError = ele;
3639 xerrMax = xo;
3640 yerrMax = yo;
3641 zerrMax = zo;
3642 }
3643 }
3644
3645 // centroid of bottom-left rectangle
3646 double xerr = 0.25 * (x0 + 0.5 * (x1 + x0) + xo + 0.5 * (x0 + x3));
3647 double yerr = 0.25 * (y0 + 0.5 * (y1 + y0) + yo + 0.5 * (y0 + y3));
3648 double zerr = 0.25 * (z0 + 0.5 * (z1 + z0) + zo + 0.5 * (z0 + z3));
3649 globalP.X = xerr;
3650 globalP.Y = yerr;
3651 globalP.Z = zerr;
3652 if (InterfaceType[prim] == 1) {
3653 PFAtPoint(&globalP, &Potential, &globalF);
3654 Err = ApplPot[prim] - Potential;
3655 fprintf(fErr, "%d\t%d\t%d\t%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
3656 prim, ele, 4, 1, xerr, yerr, zerr, ApplPot[prim], Potential,
3657 Err);
3658 if (fabs(Err) > fabs(MaxError)) {
3659 MaxError = Err;
3660 PrimitiveOfMaxError = prim;
3661 ElementOfMaxError = ele;
3662 xerrMax = xerr;
3663 yerrMax = yerr;
3664 zerrMax = zerr;
3665 }
3666 }
3667 if (InterfaceType[prim] ==
3668 4) { // compute displacement currents in the two dielectrics
3669 double xplus = xerr + (EleArr + ele - 1)->G.DC.XUnit.X * normdisp;
3670 xplus += (EleArr + ele - 1)->G.DC.YUnit.X * normdisp;
3671 xplus += (EleArr + ele - 1)->G.DC.ZUnit.X * normdisp;
3672 double yplus = yerr + (EleArr + ele - 1)->G.DC.XUnit.Y * normdisp;
3673 yplus += (EleArr + ele - 1)->G.DC.YUnit.Y * normdisp;
3674 yplus += (EleArr + ele - 1)->G.DC.ZUnit.Y * normdisp;
3675 double zplus = zerr + (EleArr + ele - 1)->G.DC.XUnit.Z * normdisp;
3676 zplus += (EleArr + ele - 1)->G.DC.YUnit.Z * normdisp;
3677 zplus += (EleArr + ele - 1)->G.DC.ZUnit.Z * normdisp;
3678 globalP.X = xplus;
3679 globalP.Y = yplus;
3680 globalP.Z = zplus;
3681 PFAtPoint(&globalP, &Potential, &globalF);
3682 localF // Flux in the ECS
3683 = RotateVector3D(&globalF, &(EleArr + ele - 1)->G.DC,
3684 global2local);
3685 double value1 = -localF.Y;
3686 double xminus = xerr - (EleArr + ele - 1)->G.DC.XUnit.X * normdisp;
3687 xminus -= (EleArr + ele - 1)->G.DC.YUnit.X * normdisp;
3688 xminus -= (EleArr + ele - 1)->G.DC.ZUnit.X * normdisp;
3689 double yminus = yerr - (EleArr + ele - 1)->G.DC.XUnit.Y * normdisp;
3690 yminus -= (EleArr + ele - 1)->G.DC.YUnit.Y * normdisp;
3691 yminus -= (EleArr + ele - 1)->G.DC.ZUnit.Y * normdisp;
3692 double zminus = zerr - (EleArr + ele - 1)->G.DC.XUnit.Z * normdisp;
3693 zminus -= (EleArr + ele - 1)->G.DC.YUnit.Z * normdisp;
3694 zminus -= (EleArr + ele - 1)->G.DC.ZUnit.Z * normdisp;
3695 globalP.X = xminus;
3696 globalP.Y = yminus;
3697 globalP.Z = zminus;
3698 PFAtPoint(&globalP, &Potential, &globalF);
3699 localF // Flux in the ECS
3700 = RotateVector3D(&globalF, &(EleArr + ele - 1)->G.DC,
3701 global2local);
3702 double value2 = -localF.Y;
3703 double epsratio = (Epsilon2[prim] / Epsilon1[prim]);
3704 Err = epsratio - (value1 / value2);
3705 fprintf(fErr, "%d\t%d\t%d\t%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
3706 prim, ele, 4, 4, xerr, yerr, zerr, epsratio,
3707 (value1 / value2), Err);
3708 if (fabs(Err) > fabs(MaxError)) {
3709 MaxError = Err;
3710 PrimitiveOfMaxError = prim;
3711 ElementOfMaxError = ele;
3712 xerrMax = xerr;
3713 yerrMax = yerr;
3714 zerrMax = zerr;
3715 }
3716 }
3717
3718 // centroid of bottom-right rectangle
3719 xerr = 0.25 * (0.5 * (x1 + x0) + x1 + 0.5 * (x1 + x2) + xo);
3720 yerr = 0.25 * (0.5 * (y1 + y0) + y1 + 0.5 * (y1 + y2) + yo);
3721 zerr = 0.25 * (0.5 * (z1 + z0) + z1 + 0.5 * (z1 + z2) + zo);
3722 globalP.X = xerr;
3723 globalP.Y = yerr;
3724 globalP.Z = zerr;
3725 // At present, error-accounting is maintained only for two types of
3726 // interfaces, C-D interfaces (specified voltage), D-D interfaces
3727 // (continuity of displacement current implied)
3728 if (InterfaceType[prim] == 1) {
3729 PFAtPoint(&globalP, &Potential, &globalF);
3730 Err = ApplPot[prim] - Potential;
3731 fprintf(fErr, "%d\t%d\t%d\t%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
3732 prim, ele, 4, 1, xerr, yerr, zerr, ApplPot[prim], Potential,
3733 Err);
3734 if (fabs(Err) > fabs(MaxError)) {
3735 MaxError = Err;
3736 PrimitiveOfMaxError = prim;
3737 ElementOfMaxError = ele;
3738 xerrMax = xerr;
3739 yerrMax = yerr;
3740 zerrMax = zerr;
3741 }
3742 }
3743 if (InterfaceType[prim] ==
3744 4) { // compute displacement currents in the two dielectrics
3745 double xplus = xerr + (EleArr + ele - 1)->G.DC.XUnit.X * normdisp;
3746 xplus += (EleArr + ele - 1)->G.DC.YUnit.X * normdisp;
3747 xplus += (EleArr + ele - 1)->G.DC.ZUnit.X * normdisp;
3748 double yplus = yerr + (EleArr + ele - 1)->G.DC.XUnit.Y * normdisp;
3749 yplus += (EleArr + ele - 1)->G.DC.YUnit.Y * normdisp;
3750 yplus += (EleArr + ele - 1)->G.DC.ZUnit.Y * normdisp;
3751 double zplus = zerr + (EleArr + ele - 1)->G.DC.XUnit.Z * normdisp;
3752 zplus += (EleArr + ele - 1)->G.DC.YUnit.Z * normdisp;
3753 zplus += (EleArr + ele - 1)->G.DC.ZUnit.Z * normdisp;
3754 globalP.X = xplus;
3755 globalP.Y = yplus;
3756 globalP.Z = zplus;
3757 PFAtPoint(&globalP, &Potential, &globalF);
3758 localF // Flux in the ECS
3759 = RotateVector3D(&globalF, &(EleArr + ele - 1)->G.DC,
3760 global2local);
3761 double value1 = -localF.Y;
3762 double xminus = xerr - (EleArr + ele - 1)->G.DC.XUnit.X * normdisp;
3763 xminus -= (EleArr + ele - 1)->G.DC.YUnit.X * normdisp;
3764 xminus -= (EleArr + ele - 1)->G.DC.ZUnit.X * normdisp;
3765 double yminus = yerr - (EleArr + ele - 1)->G.DC.XUnit.Y * normdisp;
3766 yminus -= (EleArr + ele - 1)->G.DC.YUnit.Y * normdisp;
3767 yminus -= (EleArr + ele - 1)->G.DC.ZUnit.Y * normdisp;
3768 double zminus = zerr - (EleArr + ele - 1)->G.DC.XUnit.Z * normdisp;
3769 zminus -= (EleArr + ele - 1)->G.DC.YUnit.Z * normdisp;
3770 zminus -= (EleArr + ele - 1)->G.DC.ZUnit.Z * normdisp;
3771 globalP.X = xminus;
3772 globalP.Y = yminus;
3773 globalP.Z = zminus;
3774 PFAtPoint(&globalP, &Potential, &globalF);
3775 localF // Flux in the ECS
3776 = RotateVector3D(&globalF, &(EleArr + ele - 1)->G.DC,
3777 global2local);
3778 double value2 = -localF.Y;
3779 double epsratio = (Epsilon2[prim] / Epsilon1[prim]);
3780 Err = epsratio - (value1 / value2);
3781 fprintf(fErr, "%d\t%d\t%d\t%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
3782 prim, ele, 4, 4, xerr, yerr, zerr, epsratio,
3783 (value1 / value2), Err);
3784 if (fabs(Err) > fabs(MaxError)) {
3785 MaxError = Err;
3786 PrimitiveOfMaxError = prim;
3787 ElementOfMaxError = ele;
3788 xerrMax = xerr;
3789 yerrMax = yerr;
3790 zerrMax = zerr;
3791 }
3792 }
3793
3794 // centroid of top-right rectangle
3795 xerr = 0.25 * (xo + 0.5 * (x1 + x2) + x2 + 0.5 * (x3 + x2));
3796 yerr = 0.25 * (yo + 0.5 * (y1 + y2) + y2 + 0.5 * (y3 + y2));
3797 zerr = 0.25 * (zo + 0.5 * (z1 + z2) + z2 + 0.5 * (z3 + z2));
3798 globalP.X = xerr;
3799 globalP.Y = yerr;
3800 globalP.Z = zerr;
3801 // At present, error-accounting is maintained only for two types of
3802 // interfaces, C-D interfaces (specified voltage), D-D interfaces
3803 // (continuity of displacement current implied)
3804 if (InterfaceType[prim] == 1) {
3805 PFAtPoint(&globalP, &Potential, &globalF);
3806 Err = ApplPot[prim] - Potential;
3807 fprintf(fErr, "%d\t%d\t%d\t%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
3808 prim, ele, 4, 1, xerr, yerr, zerr, ApplPot[prim], Potential,
3809 Err);
3810 if (fabs(Err) > fabs(MaxError)) {
3811 MaxError = Err;
3812 PrimitiveOfMaxError = prim;
3813 ElementOfMaxError = ele;
3814 xerrMax = xerr;
3815 yerrMax = yerr;
3816 zerrMax = zerr;
3817 }
3818 }
3819 if (InterfaceType[prim] ==
3820 4) { // compute displacement currents in the two dielectrics
3821 double xplus = xerr + (EleArr + ele - 1)->G.DC.XUnit.X * normdisp;
3822 xplus += (EleArr + ele - 1)->G.DC.YUnit.X * normdisp;
3823 xplus += (EleArr + ele - 1)->G.DC.ZUnit.X * normdisp;
3824 double yplus = yerr + (EleArr + ele - 1)->G.DC.XUnit.Y * normdisp;
3825 yplus += (EleArr + ele - 1)->G.DC.YUnit.Y * normdisp;
3826 yplus += (EleArr + ele - 1)->G.DC.ZUnit.Y * normdisp;
3827 double zplus = zerr + (EleArr + ele - 1)->G.DC.XUnit.Z * normdisp;
3828 zplus += (EleArr + ele - 1)->G.DC.YUnit.Z * normdisp;
3829 zplus += (EleArr + ele - 1)->G.DC.ZUnit.Z * normdisp;
3830 globalP.X = xplus;
3831 globalP.Y = yplus;
3832 globalP.Z = zplus;
3833 PFAtPoint(&globalP, &Potential, &globalF);
3834 localF // Flux in the ECS
3835 = RotateVector3D(&globalF, &(EleArr + ele - 1)->G.DC,
3836 global2local);
3837 double value1 = -localF.Y;
3838 double xminus = xerr - (EleArr + ele - 1)->G.DC.XUnit.X * normdisp;
3839 xminus -= (EleArr + ele - 1)->G.DC.YUnit.X * normdisp;
3840 xminus -= (EleArr + ele - 1)->G.DC.ZUnit.X * normdisp;
3841 double yminus = yerr - (EleArr + ele - 1)->G.DC.XUnit.Y * normdisp;
3842 yminus -= (EleArr + ele - 1)->G.DC.YUnit.Y * normdisp;
3843 yminus -= (EleArr + ele - 1)->G.DC.ZUnit.Y * normdisp;
3844 double zminus = zerr - (EleArr + ele - 1)->G.DC.XUnit.Z * normdisp;
3845 zminus -= (EleArr + ele - 1)->G.DC.YUnit.Z * normdisp;
3846 zminus -= (EleArr + ele - 1)->G.DC.ZUnit.Z * normdisp;
3847 globalP.X = xminus;
3848 globalP.Y = yminus;
3849 globalP.Z = zminus;
3850 PFAtPoint(&globalP, &Potential, &globalF);
3851 localF // Flux in the ECS
3852 = RotateVector3D(&globalF, &(EleArr + ele - 1)->G.DC,
3853 global2local);
3854 double value2 = -localF.Y;
3855 double epsratio = (Epsilon2[prim] / Epsilon1[prim]);
3856 Err = epsratio - (value1 / value2);
3857 fprintf(fErr, "%d\t%d\t%d\t%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
3858 prim, ele, 4, 4, xerr, yerr, zerr, epsratio,
3859 (value1 / value2), Err);
3860 if (fabs(Err) > fabs(MaxError)) {
3861 MaxError = Err;
3862 PrimitiveOfMaxError = prim;
3863 ElementOfMaxError = ele;
3864 xerrMax = xerr;
3865 yerrMax = yerr;
3866 zerrMax = zerr;
3867 }
3868 }
3869
3870 // centroid of top-left rectangle
3871 xerr = 0.25 * (0.5 * (x0 + x3) + xo + 0.5 * (x3 + x2) + x3);
3872 yerr = 0.25 * (0.5 * (y0 + y3) + yo + 0.5 * (y3 + y2) + y3);
3873 zerr = 0.25 * (0.5 * (z0 + z3) + zo + 0.5 * (z3 + z2) + z3);
3874 globalP.X = xerr;
3875 globalP.Y = yerr;
3876 globalP.Z = zerr;
3877 // At present, error-accounting is maintained only for two types of
3878 // interfaces, C-D interfaces (specified voltage), D-D interfaces
3879 // (continuity of displacement current implied)
3880 if (InterfaceType[prim] == 1) {
3881 PFAtPoint(&globalP, &Potential, &globalF);
3882 Err = ApplPot[prim] - Potential;
3883 fprintf(fErr, "%d\t%d\t%d\t%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
3884 prim, ele, 4, 1, xerr, yerr, zerr, ApplPot[prim], Potential,
3885 Err);
3886 if (fabs(Err) > fabs(MaxError)) {
3887 MaxError = Err;
3888 PrimitiveOfMaxError = prim;
3889 ElementOfMaxError = ele;
3890 xerrMax = xerr;
3891 yerrMax = yerr;
3892 zerrMax = zerr;
3893 }
3894 }
3895 if (InterfaceType[prim] ==
3896 4) { // compute displacement currents in the two dielectrics
3897 double xplus = xerr + (EleArr + ele - 1)->G.DC.XUnit.X * normdisp;
3898 xplus += (EleArr + ele - 1)->G.DC.YUnit.X * normdisp;
3899 xplus += (EleArr + ele - 1)->G.DC.ZUnit.X * normdisp;
3900 double yplus = yerr + (EleArr + ele - 1)->G.DC.XUnit.Y * normdisp;
3901 yplus += (EleArr + ele - 1)->G.DC.YUnit.Y * normdisp;
3902 yplus += (EleArr + ele - 1)->G.DC.ZUnit.Y * normdisp;
3903 double zplus = zerr + (EleArr + ele - 1)->G.DC.XUnit.Z * normdisp;
3904 zplus += (EleArr + ele - 1)->G.DC.YUnit.Z * normdisp;
3905 zplus += (EleArr + ele - 1)->G.DC.ZUnit.Z * normdisp;
3906 globalP.X = xplus;
3907 globalP.Y = yplus;
3908 globalP.Z = zplus;
3909 PFAtPoint(&globalP, &Potential, &globalF);
3910 localF // Flux in the ECS
3911 = RotateVector3D(&globalF, &(EleArr + ele - 1)->G.DC,
3912 global2local);
3913 double value1 = -localF.Y;
3914 double xminus = xerr - (EleArr + ele - 1)->G.DC.XUnit.X * normdisp;
3915 xminus -= (EleArr + ele - 1)->G.DC.YUnit.X * normdisp;
3916 xminus -= (EleArr + ele - 1)->G.DC.ZUnit.X * normdisp;
3917 double yminus = yerr - (EleArr + ele - 1)->G.DC.XUnit.Y * normdisp;
3918 yminus -= (EleArr + ele - 1)->G.DC.YUnit.Y * normdisp;
3919 yminus -= (EleArr + ele - 1)->G.DC.ZUnit.Y * normdisp;
3920 double zminus = zerr - (EleArr + ele - 1)->G.DC.XUnit.Z * normdisp;
3921 zminus -= (EleArr + ele - 1)->G.DC.YUnit.Z * normdisp;
3922 zminus -= (EleArr + ele - 1)->G.DC.ZUnit.Z * normdisp;
3923 globalP.X = xminus;
3924 globalP.Y = yminus;
3925 globalP.Z = zminus;
3926 PFAtPoint(&globalP, &Potential, &globalF);
3927 localF // Flux in the ECS
3928 = RotateVector3D(&globalF, &(EleArr + ele - 1)->G.DC,
3929 global2local);
3930 double value2 = -localF.Y;
3931 double epsratio = (Epsilon2[prim] / Epsilon1[prim]);
3932 Err = epsratio - (value1 / value2);
3933 fprintf(fErr, "%d\t%d\t%d\t%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
3934 prim, ele, 4, 4, xerr, yerr, zerr, epsratio,
3935 (value1 / value2), Err);
3936 if (fabs(Err) > fabs(MaxError)) {
3937 MaxError = Err;
3938 PrimitiveOfMaxError = prim;
3939 ElementOfMaxError = ele;
3940 xerrMax = xerr;
3941 yerrMax = yerr;
3942 zerrMax = zerr;
3943 }
3944 }
3945 } // if rectangle
3946
3947 if (DebugLevel == 1001) exit(1);
3948 } // loop over primitives and elements
3949
3950 fprintf(fErr,
3951 "#Error maximum on element %d on primitive %d with x,y,z %lg, "
3952 "%lg, %lg and its magnitude is %lg.\n",
3953 ElementOfMaxError, PrimitiveOfMaxError, xerrMax, yerrMax, zerrMax,
3954 MaxError);
3955 fclose(fErr);
3956 } // if(OptEstimateError)
3957
3958 return (0);
3959} // Solve ends here
int PFAtPoint(Point3D *globalP, double *Potential, Vector3D *globalF)
neBEMGLOBAL double * ApplPot
Definition neBEM.h:82
neBEMGLOBAL int OptRepeatLHMatrix
Definition neBEM.h:58
neBEMGLOBAL double * PrimOriginZ
Definition neBEM.h:80
neBEMGLOBAL int OptEstimateError
Definition neBEM.h:46
neBEMGLOBAL double * Epsilon1
Definition neBEM.h:82
neBEMGLOBAL double * PrimOriginY
Definition neBEM.h:80
neBEMGLOBAL int * InterfaceType
Definition neBEM.h:75
neBEMGLOBAL double * PrimOriginX
Definition neBEM.h:80
neBEMGLOBAL int OptForceValidation
Definition neBEM.h:45
neBEMGLOBAL double * Epsilon2
Definition neBEM.h:82

Referenced by ComputeSolution(), and Garfield::ComponentNeBem2d::Initialise().

◆ UpdateChargingUp()

int UpdateChargingUp ( void )

Definition at line 4267 of file neBEM.c.

4267{ return 0; } // UpdateChargingUp ends

Referenced by ComputeSolution().

◆ UpdateKnownCharges()

int UpdateKnownCharges ( void )

Definition at line 4265 of file neBEM.c.

4265{ return 0; } // UpdateKnownCharges ends

Referenced by ComputeSolution().

◆ ValueChUp()

double ValueChUp ( int elefld)

Definition at line 2470 of file neBEM.c.

2470 {
2471 int dbgFn = 0;
2472
2473 if (dbgFn) printf("\nelefld: %d\n", elefld);
2474 if (dbgFn) {
2475 printf("In ValueChUp ...\n");
2476 }
2477
2478 double value = 0.0;
2479 double assigned = 0.0;
2480 double xfld = (EleArr + elefld - 1)->BC.CollPt.X;
2481 double yfld = (EleArr + elefld - 1)->BC.CollPt.Y;
2482 double zfld = (EleArr + elefld - 1)->BC.CollPt.Z;
2483
2484 // Retrieve element properties at the field point
2485 // Location needed for Dirichlet (potential)
2486
2487 // OMPCheck - parallelize
2488
2489 // Effect of known charges on the interface elements
2490 for (int elesrc = 1; elesrc <= NbElements; ++elesrc) {
2491 Point3D localP;
2492
2493 assigned = (EleArr + elesrc - 1)->Assigned;
2494 if (fabs(assigned) <= 1.0e-16) continue;
2495
2496 // Retrieve element properties from the structure
2497 if ((EleArr + elesrc - 1)->E.Type == 0) {
2498 printf("Wrong EType for elesrc %d element %d on %dth primitive!\n",
2499 elesrc, (EleArr + elesrc - 1)->Id,
2500 (EleArr + elesrc - 1)->PrimitiveNb);
2501 exit(-1);
2502 }
2503
2504 Point3D *pOrigin = &(EleArr + elesrc - 1)->G.Origin;
2505
2506 { // Rotate point3D from global to local system
2507 double InitialVector[3]
2508 = {xfld - pOrigin->X, yfld - pOrigin->Y, zfld - pOrigin->Z};
2509 double TransformationMatrix[3][3] = {{0.0, 0.0, 0.0},
2510 {0.0, 0.0, 0.0},
2511 {0.0, 0.0, 0.0}};
2512 DirnCosn3D *DirCos = &(EleArr + elesrc - 1)->G.DC;
2513 TransformationMatrix[0][0] = DirCos->XUnit.X;
2514 TransformationMatrix[0][1] = DirCos->XUnit.Y;
2515 TransformationMatrix[0][2] = DirCos->XUnit.Z;
2516 TransformationMatrix[1][0] = DirCos->YUnit.X;
2517 TransformationMatrix[1][1] = DirCos->YUnit.Y;
2518 TransformationMatrix[1][2] = DirCos->YUnit.Z;
2519 TransformationMatrix[2][0] = DirCos->ZUnit.X;
2520 TransformationMatrix[2][1] = DirCos->ZUnit.Y;
2521 TransformationMatrix[2][2] = DirCos->ZUnit.Z;
2522 double FinalVector[3];
2523
2524 for (int i = 0; i < 3; ++i) {
2525 FinalVector[i] = 0.0;
2526 for (int j = 0; j < 3; ++j) {
2527 FinalVector[i] += TransformationMatrix[i][j] * InitialVector[j];
2528 }
2529 }
2530
2531 localP.X = FinalVector[0];
2532 localP.Y = FinalVector[1];
2533 localP.Z = FinalVector[2];
2534 } // Point3D rotated
2535
2536 switch ((EleArr + elesrc - 1)->G.Type) {
2537 case 4: // rectangular element
2538 value += assigned * RecPot(elesrc, &localP);
2539 // return(value/dA);
2540 break;
2541 case 3: // triangular element
2542 value += assigned * TriPot(elesrc, &localP);
2543 // return(value/dA);
2544 break;
2545 case 2: // linear (wire) element
2546 value += assigned * WirePot(elesrc, &localP);
2547 // return(value/dA);
2548 break;
2549 default:
2550 printf("Geometrical type out of range! ... exiting ...\n");
2551 exit(-1);
2552 break; // never comes here
2553 } // switch over gtsrc ends
2554 } // for all source elements - elesrc
2555
2556 value *= MyFACTOR;
2557 if (dbgFn) {
2558 printf("value after known charges on elements (*MyFACTOR): %g\n", value);
2559 }
2560
2561 // globalP is now required with a different definition
2562 Point3D globalP;
2563 globalP.X = xfld;
2564 globalP.Y = yfld;
2565 globalP.Z = zfld;
2566
2567 // Contribution due to known point charges
2568 Vector3D tmpglobalF; // flux not being used to evaluate Dirichlet value.
2569 for (int point = 1; point <= NbPointsKnCh; ++point) {
2570 value += (PointKnChArr + point - 1)->Assigned *
2571 PointKnChPF((PointKnChArr + point - 1)->P, globalP, &tmpglobalF);
2572 } // for all points
2573 if (dbgFn) {
2574 printf("value after known charges at points: %g\n", value);
2575 }
2576
2577 // Contribution due to known line charges
2578 for (int line = 1; line <= NbLinesKnCh; ++line) {
2579 value += (LineKnChArr + line - 1)->Assigned *
2580 LineKnChPF((LineKnChArr + line - 1)->Start,
2581 (LineKnChArr + line - 1)->Stop, globalP, &tmpglobalF);
2582 } // for lines
2583 if (dbgFn) {
2584 printf("value after known charges on lines: %g\n", value);
2585 }
2586
2587 // Contribution due to known area charges
2588 for (int area = 1; area <= NbAreasKnCh; ++area) {
2589 value +=
2590 (AreaKnChArr + area - 1)->Assigned *
2591 AreaKnChPF((AreaKnChArr + area - 1)->NbVertices,
2592 ((AreaKnChArr + area - 1)->Vertex), globalP, &tmpglobalF);
2593 } // for areas
2594 if (dbgFn) {
2595 printf("value after known charges on areas: %g\n", value);
2596 }
2597
2598 // Contribution due to known volume charges
2599 for (int vol = 1; vol <= NbVolumesKnCh; ++vol) {
2600 value += (VolumeKnChArr + vol - 1)->Assigned *
2602 ((VolumeKnChArr + vol - 1)->Vertex), globalP,
2603 &tmpglobalF);
2604 } // for vols
2605
2606 value /= MyFACTOR;
2607 if (dbgFn) {
2608 printf("value after known charges in volumes (/ MyFACTOR): %g\n", value);
2609 printf("Exiting ValueChUp ...\n");
2610 }
2611
2612 return (value);
2613} // ValueChUp ends

Referenced by RHVector().

◆ ValueKnCh()

double ValueKnCh ( int elefld)

Definition at line 2120 of file neBEM.c.

2120 {
2121 int dbgFn = 0;
2122
2123 if (dbgFn) printf("\nelefld: %d\n", elefld);
2124
2125 double value = 0.0;
2126 double assigned = 0.0;
2127 double xfld = (EleArr + elefld - 1)->BC.CollPt.X;
2128 double yfld = (EleArr + elefld - 1)->BC.CollPt.Y;
2129 double zfld = (EleArr + elefld - 1)->BC.CollPt.Z;
2130
2131 // Retrieve element properties at the field point
2132 // Location needed for Dirichlet (potential)
2133
2134 // OMPCheck - parallelize
2135
2136 // Effect of known charges on the interface elements
2137 for (int elesrc = 1; elesrc <= NbElements; ++elesrc) {
2138 Point3D localP;
2139
2140 assigned = (EleArr + elesrc - 1)->Assigned;
2141 if (fabs(assigned) <= 1.0e-16) continue;
2142
2143 // Retrieve element properties from the structure
2144 if ((EleArr + elesrc - 1)->E.Type == 0) {
2145 printf("Wrong EType for elesrc %d element %d on %dth primitive!\n",
2146 elesrc, (EleArr + elesrc - 1)->Id,
2147 (EleArr + elesrc - 1)->PrimitiveNb);
2148 exit(-1);
2149 }
2150
2151 Point3D *pOrigin = &(EleArr + elesrc - 1)->G.Origin;
2152
2153 { // Rotate point3D from global to local system
2154 double InitialVector[3] =
2155 {xfld - pOrigin->X, yfld - pOrigin->Y, zfld - pOrigin->Z};
2156 double TransformationMatrix[3][3] = {{0.0, 0.0, 0.0},
2157 {0.0, 0.0, 0.0},
2158 {0.0, 0.0, 0.0}};
2159 DirnCosn3D *DirCos = &(EleArr + elesrc - 1)->G.DC;
2160 TransformationMatrix[0][0] = DirCos->XUnit.X;
2161 TransformationMatrix[0][1] = DirCos->XUnit.Y;
2162 TransformationMatrix[0][2] = DirCos->XUnit.Z;
2163 TransformationMatrix[1][0] = DirCos->YUnit.X;
2164 TransformationMatrix[1][1] = DirCos->YUnit.Y;
2165 TransformationMatrix[1][2] = DirCos->YUnit.Z;
2166 TransformationMatrix[2][0] = DirCos->ZUnit.X;
2167 TransformationMatrix[2][1] = DirCos->ZUnit.Y;
2168 TransformationMatrix[2][2] = DirCos->ZUnit.Z;
2169 double FinalVector[3];
2170
2171 for (int i = 0; i < 3; ++i) {
2172 FinalVector[i] = 0.0;
2173 for (int j = 0; j < 3; ++j) {
2174 FinalVector[i] += TransformationMatrix[i][j] * InitialVector[j];
2175 }
2176 }
2177
2178 localP.X = FinalVector[0];
2179 localP.Y = FinalVector[1];
2180 localP.Z = FinalVector[2];
2181 } // Point3D rotated
2182
2183 switch ((EleArr + elesrc - 1)->G.Type) {
2184 case 4: // rectangular element
2185 value += assigned * RecPot(elesrc, &localP);
2186 // return(value/dA);
2187 break;
2188 case 3: // triangular element
2189 value += assigned * TriPot(elesrc, &localP);
2190 // return(value/dA);
2191 break;
2192 case 2: // linear (wire) element
2193 value += assigned * WirePot(elesrc, &localP);
2194 // return(value/dA);
2195 break;
2196 default:
2197 printf("Geometrical type out of range! ... exiting ...\n");
2198 exit(-1);
2199 break; // never comes here
2200 } // switch over gtsrc ends
2201 } // for all source elements - elesrc
2202
2203 value += MyFACTOR; // in order reduce divisions by MyFACTOR later
2204 if (dbgFn) {
2205 printf("value after known charges on elements (* MyFACTOR): %g\n", value);
2206 }
2207
2208 // globalP is now required with a different definition
2209 Point3D fieldPt;
2210 fieldPt.X = xfld;
2211 fieldPt.Y = yfld;
2212 fieldPt.Z = zfld;
2213
2214 // Contribution due to known point charges
2215 Vector3D tmpglobalF; // flux not being used to evaluate Dirichlet value.
2216 for (int point = 1; point <= NbPointsKnCh; ++point) {
2217 Point3D sourcePt;
2218 sourcePt.X = PointKnChArr[point].P.X;
2219 sourcePt.Y = PointKnChArr[point].P.Y;
2220 sourcePt.Z = PointKnChArr[point].P.Z;
2221 value += PointKnChArr[point].Assigned *
2222 PointKnChPF(sourcePt, fieldPt, &tmpglobalF);
2223 } // for all points
2224 if (dbgFn) {
2225 printf("value after known charges at points: %g\n", value);
2226 }
2227
2228 // Contribution due to known line charges
2229 for (int line = 1; line <= NbLinesKnCh; ++line) {
2230 Point3D startPt, stopPt;
2231 startPt.X = LineKnChArr[line].Start.X;
2232 startPt.Y = LineKnChArr[line].Start.Y;
2233 startPt.Z = LineKnChArr[line].Start.Z;
2234 stopPt.X = LineKnChArr[line].Stop.X;
2235 stopPt.Y = LineKnChArr[line].Stop.Y;
2236 stopPt.Z = LineKnChArr[line].Stop.Z;
2237 double radius = LineKnChArr[line].Radius;
2238 if (dbgFn) {
2239 printf(
2240 "In ValueKnCh, Nb: %d, X1Y1Z1: %lg %lg %lg X2Y2Z2 %lg %lg %lg R: %lg "
2241 "Lmda:%lg\n",
2242 LineKnChArr[line].Nb, startPt.X, startPt.Y, startPt.Z, stopPt.X,
2243 stopPt.Y, stopPt.Z, radius, LineKnChArr[line].Assigned);
2244 }
2245 value += LineKnChArr[line].Assigned *
2246 LineKnChPF(startPt, stopPt, fieldPt, &tmpglobalF);
2247 } // for lines
2248 if (dbgFn) {
2249 printf("value after known charges on lines: %g\n", value);
2250 }
2251
2252 // Contribution due to known area charges
2253 // We may need to convert the information to simpler structures, as done
2254 // for points and lines, above.
2255 for (int area = 1; area <= NbAreasKnCh; ++area) {
2256 value +=
2257 (AreaKnChArr + area - 1)->Assigned *
2258 AreaKnChPF((AreaKnChArr + area - 1)->NbVertices,
2259 ((AreaKnChArr + area - 1)->Vertex), fieldPt, &tmpglobalF);
2260 } // for areas
2261 if (dbgFn) {
2262 printf("value after known charges on areas: %g\n", value);
2263 }
2264
2265 // Contribution due to known volume charges
2266 for (int vol = 1; vol <= NbVolumesKnCh; ++vol) {
2267 value += (VolumeKnChArr + vol - 1)->Assigned *
2269 ((VolumeKnChArr + vol - 1)->Vertex), fieldPt,
2270 &tmpglobalF);
2271 } // for vols
2272
2273 value /= MyFACTOR;
2274 if (dbgFn) {
2275 printf("value after known charges in volumes (/ MyFACTOR): %g\n", value);
2276 }
2277
2278 return (value);
2279} // end of ValueKnCh

Referenced by RHVector().

◆ WeightingFieldSolution()

int WeightingFieldSolution ( int NbPrimsWtField,
int PrimListWtField[],
double solnarray[] )

Definition at line 4034 of file neBEM.c.

4035 {
4036 // Check for the inverted matrix
4037 if (!InvMat) {
4038 printf(
4039 "WeightingFieldSolution: Capacitance matrix not in memory, can not "
4040 "calculate weighting charges.\n");
4041 return (-1);
4042 }
4043
4044 for (int i = 1; i <= NbUnknowns; i++) solnarray[i] = 0.0;
4045
4046 for (int ele = 1, InList; ele <= NbElements; ++ele) {
4047 int prim = (EleArr + ele - 1)->PrimitiveNb;
4048
4049 InList = 0; // assume that this prim is not in the list
4050 for (int primwtfl = 0; primwtfl < NbPrimsWtField; ++primwtfl) {
4051 if (prim == PrimListWtField[primwtfl]) {
4052 InList = 1;
4053 break; // get out of the for loop
4054 }
4055 } // for primwtfl
4056
4057 if (InList) {
4058 for (int i = 1; i <= NbUnknowns; ++i) {
4059 solnarray[i] += InvMat[i][ele];
4060 }
4061 }
4062 } // for ele
4063
4064 return (0);
4065} // WtFieldSolution ends

Referenced by neBEMPrepareWeightingField().

Variable Documentation

◆ InfluenceMatrixFlag

int InfluenceMatrixFlag

Definition at line 29 of file neBEM.c.

Referenced by ComputeSolution(), and Solve().