Garfield++ 4.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
neBEM.h File Reference
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Vector.h"

Go to the source code of this file.

Classes

struct  GeomProp
 
struct  ElecProp
 
struct  BCProp
 
struct  Element
 
struct  PointKnCh
 
struct  LineKnCh
 
struct  AreaKnCh
 
struct  VolumeKnCh
 
struct  VoxelVol
 
struct  MapVol
 
struct  FastAlgoVol
 
struct  WtFldFastAlgoVol
 

Macros

#define neBEMGLOBAL   extern
 
#define EPS0   8.854187817e-12
 
#define MyFACTOR   111.26500547e-12
 
#define Q_E   -1.60217646e-19
 
#define Q_I   1.60217646e-19
 

Functions

neBEMGLOBAL int SurfaceElements (int prim, int nvertex, double xvert[], double yvert[], double zvert[], double xnorm, double ynorm, double znorm, int volref1, int volref2, int inttype, double potential, double charge, double lambda, int NbSegX, int NbSegZ)
 
neBEMGLOBAL int WireElements (int prim, int nvertex, double xvert[], double yvert[], double zvert[], double radius, int volref1, int volref2, int inttype, double potential, double charge, double lambda, int NbWireSeg)
 
neBEMGLOBAL int BoundaryConditions (void)
 
neBEMGLOBAL int AnalyzePrimitive (int, int *, int *)
 
neBEMGLOBAL int AnalyzeWire (int, int *)
 
neBEMGLOBAL int AnalyzeSurface (int, int *, int *)
 
neBEMGLOBAL int DiscretizeWire (int prim, int nvertex, double xvert[], double yvert[], double zvert[], double radius, int volref1, int volref2, int inttype, double potential, double charge, double lambda, int NbSegs)
 
neBEMGLOBAL int DiscretizeTriangle (int prim, int nvertex, double xvert[], double yvert[], double zvert[], double xnorm, double ynorm, double znorm, int volref1, int volref2, int inttype, double potential, double charge, double lambda, int NbSegX, int NbSegZ)
 
neBEMGLOBAL int DiscretizeRectangle (int prim, int nvertex, double xvert[], double yvert[], double zvert[], double xnorm, double ynorm, double znorm, int volref1, int volref2, int inttype, double potential, double charge, double lambda, int NbSegX, int NbSegZ)
 
neBEMGLOBAL int DiscretizePolygon (int prim, int nvertex, double xvert[], double yvert[], double zvert[], double xnorm, double ynorm, double znorm, int volref1, int volref2, int inttype, double potential, double charge, double lambda, int NbSegX, int NbSegZ)
 
neBEMGLOBAL int ComputeSolution (void)
 
neBEMGLOBAL int ReadSolution (void)
 
neBEMGLOBAL double ComputeInfluence (int fld, int src, Point3D *localPt, DirnCosn3D *DirCos)
 
neBEMGLOBAL double SatisfyValue (int src, Point3D *localPt)
 
neBEMGLOBAL double SatisfyContinuity (int fld, int src, Point3D *localPt, DirnCosn3D *DirCos)
 
neBEMGLOBAL double EffectChUp (int fld)
 
neBEMGLOBAL double ValueChUp (int fld)
 
neBEMGLOBAL double ContinuityChUp (int fld)
 
neBEMGLOBAL double EffectKnCh (int fld)
 
neBEMGLOBAL double ValueKnCh (int fld)
 
neBEMGLOBAL double ContinuityKnCh (int fld)
 
neBEMGLOBAL int WeightingFieldSolution (int NbPrimsWtField, int PrimListWtField[], double WtFieldChDen[])
 
neBEMGLOBAL Point3D ReflectPrimitiveOnMirror (char Axis, int prim, Point3D srcpt, Point3D fieldpt, double distance, DirnCosn3D *DirCos)
 
neBEMGLOBAL Point3D ReflectOnMirror (char Axis, int elesrc, Point3D srcpt, Point3D fieldpt, double distance, DirnCosn3D *DirCos)
 
neBEMGLOBAL int PFAtPoint (Point3D *globalPt, double *Pot, Vector3D *Flux)
 
neBEMGLOBAL int ElePFAtPoint (Point3D *globalPt, double *Pot, Vector3D *Flux)
 
neBEMGLOBAL int KnChPFAtPoint (Point3D *globalPt, double *Pot, Vector3D *Flux)
 
neBEMGLOBAL int VoxelFPR (void)
 
neBEMGLOBAL int MapFPR (void)
 
neBEMGLOBAL int FastVolPF (void)
 
neBEMGLOBAL int FastVolElePF (void)
 
neBEMGLOBAL int FastVolKnChPF (void)
 
neBEMGLOBAL int FastPFAtPoint (Point3D *globalPt, double *Pot, Vector3D *Flux)
 
neBEMGLOBAL int FastElePFAtPoint (Point3D *globalPt, double *Pot, Vector3D *Flux)
 
neBEMGLOBAL int FastKnChPFAtPoint (Point3D *globalPt, double *Pot, Vector3D *Flux)
 
neBEMGLOBAL int WtFldFastVolPF (void)
 
neBEMGLOBAL int WtFldFastPFAtPoint (Point3D *globalPt, double *Pot, Vector3D *Flux)
 
neBEMGLOBAL double GetPotential (int src, Point3D *localPt)
 
neBEMGLOBAL void GetFluxGCS (int src, Point3D *localPt, Vector3D *Flux)
 
neBEMGLOBAL void GetFlux (int src, Point3D *localPt, Vector3D *Flux)
 
neBEMGLOBAL double RecPot (int src, Point3D *localPt)
 
neBEMGLOBAL double TriPot (int src, Point3D *localPt)
 
neBEMGLOBAL double WirePot (int src, Point3D *localPt)
 
neBEMGLOBAL void RecFlux (int src, Point3D *localPt, Vector3D *Flux)
 
neBEMGLOBAL void TriFlux (int src, Point3D *localPt, Vector3D *Flux)
 
neBEMGLOBAL void WireFlux (int src, Point3D *localPt, Vector3D *Flux)
 
neBEMGLOBAL void GetPFGCS (int type, double a, double b, Point3D *localPt, double *Pot, Vector3D *Flux, DirnCosn3D *DirCos)
 
neBEMGLOBAL void GetPF (int type, double a, double b, double x, double y, double z, double *Pot, Vector3D *Flux)
 
neBEMGLOBAL void RecPF (double a, double b, double x, double y, double z, double *Pot, Vector3D *Flux)
 
neBEMGLOBAL void TriPF (double a, double b, double x, double y, double z, double *Pot, Vector3D *Flux)
 
neBEMGLOBAL void WirePF (double rW, double lW, double x, double y, double z, double *Pot, Vector3D *Flux)
 
neBEMGLOBAL void GetPrimPFGCS (int src, Point3D *localPt, double *Pot, Vector3D *Flux, DirnCosn3D *DirCos)
 
neBEMGLOBAL void GetPrimPF (int src, Point3D *localPt, double *Pot, Vector3D *Flux)
 
neBEMGLOBAL void RecPrimPF (int src, Point3D *localPt, double *Pot, Vector3D *Flux)
 
neBEMGLOBAL void TriPrimPF (int src, Point3D *localPt, double *Pot, Vector3D *Flux)
 
neBEMGLOBAL void WirePrimPF (int src, Point3D *localPt, double *Pot, Vector3D *Flux)
 
neBEMGLOBAL int WtPFAtPoint (Point3D *globalPt, double *Pot, Vector3D *Flux, int Id)
 

Variables

neBEMGLOBAL char neBEMVersion [10]
 
neBEMGLOBAL int OptInvMatProc
 
neBEMGLOBAL int OptValidateSolution
 
neBEMGLOBAL int OptForceValidation
 
neBEMGLOBAL int OptEstimateError
 
neBEMGLOBAL int OptStorePrimitives
 
neBEMGLOBAL int OptStoreElements
 
neBEMGLOBAL int OptStoreInflMatrix
 
neBEMGLOBAL int OptStoreInvMatrix
 
neBEMGLOBAL int OptFormattedFile
 
neBEMGLOBAL int OptUnformattedFile
 
neBEMGLOBAL int OptRepeatLHMatrix
 
neBEMGLOBAL int OptKnCh
 
neBEMGLOBAL int OptChargingUp
 
neBEMGLOBAL int NbVolumes
 
neBEMGLOBAL int NbPrimitives
 
neBEMGLOBAL int OrgnlNbPrimitives
 
neBEMGLOBAL int MaxNbVertices
 
neBEMGLOBAL int * volRef
 
neBEMGLOBAL int * volShape
 
neBEMGLOBAL int * volMaterial
 
neBEMGLOBAL int * volBoundaryType
 
neBEMGLOBAL double * volEpsilon
 
neBEMGLOBAL double * volPotential
 
neBEMGLOBAL double * volCharge
 
neBEMGLOBAL int * PrimType
 
neBEMGLOBAL int * InterfaceType
 
neBEMGLOBAL int ** OrgnlToEffPrim
 
neBEMGLOBAL int * NbVertices
 
neBEMGLOBAL double ** XVertex
 
neBEMGLOBAL double ** YVertex
 
neBEMGLOBAL double ** ZVertex
 
neBEMGLOBAL double * XNorm
 
neBEMGLOBAL double * YNorm
 
neBEMGLOBAL double * ZNorm
 
neBEMGLOBAL double * PrimLX
 
neBEMGLOBAL double * PrimLZ
 
neBEMGLOBAL double * Radius
 
neBEMGLOBAL double * PrimOriginX
 
neBEMGLOBAL double * PrimOriginY
 
neBEMGLOBAL double * PrimOriginZ
 
neBEMGLOBAL DirnCosn3DPrimDC
 
neBEMGLOBAL double * Epsilon1
 
neBEMGLOBAL double * Epsilon2
 
neBEMGLOBAL double * Lambda
 
neBEMGLOBAL double * ApplPot
 
neBEMGLOBAL double * ApplCh
 
neBEMGLOBAL int * VolRef1
 
neBEMGLOBAL int * VolRef2
 
neBEMGLOBAL int VolMax
 
neBEMGLOBAL int * PeriodicTypeX
 
neBEMGLOBAL int * PeriodicTypeY
 
neBEMGLOBAL int * PeriodicTypeZ
 
neBEMGLOBAL int * PeriodicInX
 
neBEMGLOBAL int * PeriodicInY
 
neBEMGLOBAL int * PeriodicInZ
 
neBEMGLOBAL double * XPeriod
 
neBEMGLOBAL double * YPeriod
 
neBEMGLOBAL double * ZPeriod
 
neBEMGLOBAL int * MirrorTypeX
 
neBEMGLOBAL int * MirrorTypeY
 
neBEMGLOBAL int * MirrorTypeZ
 
neBEMGLOBAL double * MirrorDistXFromOrigin
 
neBEMGLOBAL double * MirrorDistYFromOrigin
 
neBEMGLOBAL double * MirrorDistZFromOrigin
 
neBEMGLOBAL int * BndPlaneInXMin
 
neBEMGLOBAL int * BndPlaneInYMin
 
neBEMGLOBAL int * BndPlaneInZMin
 
neBEMGLOBAL int * BndPlaneInXMax
 
neBEMGLOBAL int * BndPlaneInYMax
 
neBEMGLOBAL int * BndPlaneInZMax
 
neBEMGLOBAL double * XBndPlaneInXMin
 
neBEMGLOBAL double * YBndPlaneInYMin
 
neBEMGLOBAL double * ZBndPlaneInZMin
 
neBEMGLOBAL double * XBndPlaneInXMax
 
neBEMGLOBAL double * YBndPlaneInYMax
 
neBEMGLOBAL double * ZBndPlaneInZMax
 
neBEMGLOBAL double * VBndPlaneInXMin
 
neBEMGLOBAL double * VBndPlaneInYMin
 
neBEMGLOBAL double * VBndPlaneInZMin
 
neBEMGLOBAL double * VBndPlaneInXMax
 
neBEMGLOBAL double * VBndPlaneInYMax
 
neBEMGLOBAL double * VBndPlaneInZMax
 
neBEMGLOBAL double * AvChDen
 
neBEMGLOBAL double * AvAsgndChDen
 
neBEMGLOBAL int * NbElmntsOnPrim
 
neBEMGLOBAL int * ElementBgn
 
neBEMGLOBAL int * ElementEnd
 
neBEMGLOBAL int NbSurfs
 
neBEMGLOBAL int NbWires
 
neBEMGLOBAL int * NbSurfSegX
 
neBEMGLOBAL int * NbSurfSegZ
 
neBEMGLOBAL int * NbWireSeg
 
neBEMGLOBAL int MinNbElementsOnLength
 
neBEMGLOBAL int MaxNbElementsOnLength
 
neBEMGLOBAL double ElementLengthRqstd
 
neBEMGLOBAL int EleCntr
 
neBEMGLOBAL int NbElements
 
neBEMGLOBAL FILE * fMeshLog
 
neBEMGLOBAL int OptSystemChargeZero
 
neBEMGLOBAL int NbSystemChargeZero
 
neBEMGLOBAL double VSystemChargeZero
 
neBEMGLOBAL int NbFloatingConductors
 
neBEMGLOBAL int NbFloatCon
 
neBEMGLOBAL double VFloatCon
 
neBEMGLOBAL ElementEleArr
 
neBEMGLOBAL int NbPointsKnCh
 
neBEMGLOBAL int NbLinesKnCh
 
neBEMGLOBAL int NbAreasKnCh
 
neBEMGLOBAL int NbVolumesKnCh
 
neBEMGLOBAL PointKnChPointKnChArr
 
neBEMGLOBAL LineKnChLineKnChArr
 
neBEMGLOBAL AreaKnChAreaKnChArr
 
neBEMGLOBAL VolumeKnChVolumeKnChArr
 
neBEMGLOBAL int NewModel
 
neBEMGLOBAL int NewMesh
 
neBEMGLOBAL int NewBC
 
neBEMGLOBAL int NewPP
 
neBEMGLOBAL int ModelCntr
 
neBEMGLOBAL int MeshCntr
 
neBEMGLOBAL int BCCntr
 
neBEMGLOBAL int PPCntr
 
neBEMGLOBAL int NbConstraints
 
neBEMGLOBAL int NbEqns
 
neBEMGLOBAL int NbUnknowns
 
neBEMGLOBAL int DebugLevel
 
neBEMGLOBAL int OptSVD
 
neBEMGLOBAL int OptLU
 
neBEMGLOBAL int OptGSL
 
neBEMGLOBAL double ** Inf
 
neBEMGLOBAL double ** InvMat
 
neBEMGLOBAL double * RHS
 
neBEMGLOBAL double * Solution
 
neBEMGLOBAL double LengthScale
 
neBEMGLOBAL int TimeStep
 
neBEMGLOBAL int EndOfTime
 
neBEMGLOBAL char TimeStr [256]
 
neBEMGLOBAL char GnuplotTmpDir [256]
 
neBEMGLOBAL char GnuplotScriptFile [256]
 
neBEMGLOBAL char DeviceOutDir [256]
 
neBEMGLOBAL char ModelOutDir [256]
 
neBEMGLOBAL char NativeOutDir [256]
 
neBEMGLOBAL char NativePrimDir [256]
 
neBEMGLOBAL char MeshOutDir [256]
 
neBEMGLOBAL char BCOutDir [256]
 
neBEMGLOBAL char PPOutDir [256]
 
neBEMGLOBAL double ** WtFieldChDen
 
neBEMGLOBAL double ** AvWtChDen
 
neBEMGLOBAL int PrimAfter
 
neBEMGLOBAL int OptVoxel
 
neBEMGLOBAL int OptStaggerVoxel
 
neBEMGLOBAL VoxelVol Voxel
 
neBEMGLOBAL int OptMap
 
neBEMGLOBAL int OptStaggerMap
 
neBEMGLOBAL char MapVersion [10]
 
neBEMGLOBAL MapVol Map
 
neBEMGLOBAL int OptFastVol
 
neBEMGLOBAL int OptStaggerFastVol
 
neBEMGLOBAL int OptCreateFastPF
 
neBEMGLOBAL int OptReadFastPF
 
neBEMGLOBAL int NbPtSkip
 
neBEMGLOBAL int NbStgPtSkip
 
neBEMGLOBAL FastAlgoVol FastVol
 
neBEMGLOBAL int * BlkNbXCells
 
neBEMGLOBAL int * BlkNbYCells
 
neBEMGLOBAL int * BlkNbZCells
 
neBEMGLOBAL double * BlkLZ
 
neBEMGLOBAL double * BlkCrnrZ
 
neBEMGLOBAL double * OmitVolLX
 
neBEMGLOBAL double * OmitVolLY
 
neBEMGLOBAL double * OmitVolLZ
 
neBEMGLOBAL double * OmitVolCrnrX
 
neBEMGLOBAL double * OmitVolCrnrY
 
neBEMGLOBAL double * OmitVolCrnrZ
 
neBEMGLOBAL double * IgnoreVolLX
 
neBEMGLOBAL double * IgnoreVolLY
 
neBEMGLOBAL double * IgnoreVolLZ
 
neBEMGLOBAL double * IgnoreVolCrnrX
 
neBEMGLOBAL double * IgnoreVolCrnrY
 
neBEMGLOBAL double * IgnoreVolCrnrZ
 
neBEMGLOBAL double **** FastPot
 
neBEMGLOBAL double **** FastFX
 
neBEMGLOBAL double **** FastFY
 
neBEMGLOBAL double **** FastFZ
 
neBEMGLOBAL double **** FastStgPot
 
neBEMGLOBAL double **** FastStgFX
 
neBEMGLOBAL double **** FastStgFY
 
neBEMGLOBAL double **** FastStgFZ
 
neBEMGLOBAL double **** FastPotKnCh
 
neBEMGLOBAL double **** FastFXKnCh
 
neBEMGLOBAL double **** FastFYKnCh
 
neBEMGLOBAL double **** FastFZKnCh
 
neBEMGLOBAL double **** FastStgPotKnCh
 
neBEMGLOBAL double **** FastStgFXKnCh
 
neBEMGLOBAL double **** FastStgFYKnCh
 
neBEMGLOBAL double **** FastStgFZKnCh
 
neBEMGLOBAL int OptFixedWtField
 
neBEMGLOBAL double FixedWtPotential
 
neBEMGLOBAL double FixedWtFieldX
 
neBEMGLOBAL double FixedWtFieldY
 
neBEMGLOBAL double FixedWtFieldZ
 
neBEMGLOBAL int OptWtFldFastVol
 
neBEMGLOBAL int OptWtFldStaggerFastVol
 
neBEMGLOBAL int OptWtFldCreateFastPF
 
neBEMGLOBAL int OptWtFldReadFastPF
 
neBEMGLOBAL int WtFldNbPtSkip
 
neBEMGLOBAL int WtFldNbStgPtSkip
 
neBEMGLOBAL WtFldFastAlgoVol WtFldFastVol
 
neBEMGLOBAL int * WtFldBlkNbXCells
 
neBEMGLOBAL int * WtFldBlkNbYCells
 
neBEMGLOBAL int * WtFldBlkNbZCells
 
neBEMGLOBAL double * WtFldBlkLZ
 
neBEMGLOBAL double * WtFldBlkCrnrZ
 
neBEMGLOBAL double * WtFldOmitVolLX
 
neBEMGLOBAL double * WtFldOmitVolLY
 
neBEMGLOBAL double * WtFldOmitVolLZ
 
neBEMGLOBAL double * WtFldOmitVolCrnrX
 
neBEMGLOBAL double * WtFldOmitVolCrnrY
 
neBEMGLOBAL double * WtFldOmitVolCrnrZ
 
neBEMGLOBAL double * WtFldIgnoreVolLX
 
neBEMGLOBAL double * WtFldIgnoreVolLY
 
neBEMGLOBAL double * WtFldIgnoreVolLZ
 
neBEMGLOBAL double * WtFldIgnoreVolCrnrX
 
neBEMGLOBAL double * WtFldIgnoreVolCrnrY
 
neBEMGLOBAL double * WtFldIgnoreVolCrnrZ
 
neBEMGLOBAL double **** WtFldFastPot
 
neBEMGLOBAL double **** WtFldFastFX
 
neBEMGLOBAL double **** WtFldFastFY
 
neBEMGLOBAL double **** WtFldFastFZ
 
neBEMGLOBAL double **** WtFldFastStgPot
 
neBEMGLOBAL double **** WtFldFastStgFX
 
neBEMGLOBAL double **** WtFldFastStgFY
 
neBEMGLOBAL double **** WtFldFastStgFZ
 

Macro Definition Documentation

◆ EPS0

#define EPS0   8.854187817e-12

Definition at line 20 of file neBEM.h.

◆ MyFACTOR

#define MyFACTOR   111.26500547e-12

Definition at line 21 of file neBEM.h.

◆ neBEMGLOBAL

#define neBEMGLOBAL   extern

Definition at line 10 of file neBEM.h.

◆ Q_E

#define Q_E   -1.60217646e-19

Definition at line 27 of file neBEM.h.

◆ Q_I

#define Q_I   1.60217646e-19

Definition at line 28 of file neBEM.h.

Function Documentation

◆ AnalyzePrimitive()

neBEMGLOBAL int AnalyzePrimitive ( int  prim,
int *  NbSegCoord1,
int *  NbSegCoord2 
)

Definition at line 121 of file ReTriM.c.

121 {
122 int fstatus;
123
124 switch (NbVertices[prim]) {
125 case 2: // wire
126 fstatus = AnalyzeWire(prim, NbSegCoord1);
127 *NbSegCoord2 = 0;
128 // assert(fstatus == 0);
129 if (fstatus != 0) {
130 neBEMMessage("AnalyzePrimitive - AnalyzeWire");
131 return -1;
132 }
133 return (2);
134 break;
135 case 3: // triangle
136 fstatus = AnalyzeSurface(prim, NbSegCoord1, NbSegCoord2);
137 // assert(fstatus == 0);
138 if (fstatus != 0) {
139 neBEMMessage("AnalyzePrimitive - AnalyzeSurface");
140 return -1;
141 }
142 return (3);
143 break;
144 case 4: // rectangle
145 fstatus = AnalyzeSurface(prim, NbSegCoord1, NbSegCoord2);
146 // assert(fstatus == 0);
147 if (fstatus != 0) {
148 neBEMMessage("AnalyzePrimitive - AnalyzeSurface");
149 return -1;
150 }
151 return (4);
152 break;
153 default: // no shape!
154 return (0);
155 }
156} // end of AnalyzePrimitive
int AnalyzeSurface(int prim, int *NbSegCoord1, int *NbSegCoord2)
Definition: ReTriM.c:246
int AnalyzeWire(int prim, int *NbSeg)
Definition: ReTriM.c:158
int neBEMMessage(const char *message)
neBEMGLOBAL int * NbVertices
Definition: neBEM.h:70

Referenced by neBEMDiscretize().

◆ AnalyzeSurface()

neBEMGLOBAL int AnalyzeSurface ( int  prim,
int *  NbSegCoord1,
int *  NbSegCoord2 
)

Definition at line 246 of file ReTriM.c.

246 {
247 int nb1 = *NbSegCoord1, nb2 = *NbSegCoord2;
248
249 if ((nb1 < 1) || (nb2 < 1)) // absurd! use the trio: target, min, max
250 {
251 // Triangle primitives have their right angle on vertex 1
252 double l1 = (XVertex[prim][0] - XVertex[prim][1]) *
253 (XVertex[prim][0] - XVertex[prim][1]) +
254 (YVertex[prim][0] - YVertex[prim][1]) *
255 (YVertex[prim][0] - YVertex[prim][1]) +
256 (ZVertex[prim][0] - ZVertex[prim][1]) *
257 (ZVertex[prim][0] - ZVertex[prim][1]);
258 l1 = sqrt(l1);
259 double l2 = (XVertex[prim][2] - XVertex[prim][1]) *
260 (XVertex[prim][2] - XVertex[prim][1]) +
261 (YVertex[prim][2] - YVertex[prim][1]) *
262 (YVertex[prim][2] - YVertex[prim][1]) +
263 (ZVertex[prim][2] - ZVertex[prim][1]) *
264 (ZVertex[prim][2] - ZVertex[prim][1]);
265 l2 = sqrt(l2);
266
267 // We can use the lengths independently and forget about area
268 // for the time being
269
270 // double area = l1 * l2;
271
272 nb1 = (int)(l1 / ElementLengthRqstd);
273 if ((nb1 > MinNbElementsOnLength) &&
274 (nb1 < MaxNbElementsOnLength)) {
275 // nothing to be done
276 } else if (l1 < MINDIST) {
277 fprintf(fMeshLog, "Length1 too small on primitive %d!\n", prim);
278 nb1 = 1;
279 } else if (nb1 < MinNbElementsOnLength) {
280 // Need to have at least MinNbElementsOnLength elements per wire primitive
282 double ellength = l1 / (double)nb1;
283 // which may not be possible if the length is small
284 if (ellength < MINDIST) {
285 nb1 = (int)(l1 / MINDIST);
286 // However, it is necessary to have at least one element!
287 if (nb1 < 1) {
288 fprintf(fMeshLog, "Length1 very small on primitive %d!\n", prim);
289 nb1 = 1;
290 }
291 }
292 } // else if nb1 < MinNbElementsOnLength
293
294 if (nb1 > MaxNbElementsOnLength) {
295 fprintf(fMeshLog, "Too many elements on Length1 for primitive %d!\n",
296 prim);
297 fprintf(fMeshLog, "Number of elements reduced to maximum allowed %d\n",
300 }
301
302 nb2 = (int)(l2 / ElementLengthRqstd);
303 if ((nb2 > MinNbElementsOnLength) &&
304 (nb2 < MaxNbElementsOnLength)) {
305 // nothing to be done
306 } else if (l2 < MINDIST) {
307 fprintf(fMeshLog, "Length2 element too small on primitive %d!\n", prim);
308 nb2 = 1;
309 } else if (nb2 < MinNbElementsOnLength) {
310 // Need to have at least MinNbElementsOnLength elements per wire primitive
312 double ellength = l2 / (double)nb2;
313 // which may not be possible if the length is small
314 if (ellength < MINDIST) {
315 // However, it is necessary to have at least one element!
316 nb2 = (int)(l2 / MINDIST);
317 if (nb2 < 1) {
318 fprintf(fMeshLog, "Length2 element very small on primitive %d!\n",
319 prim);
320 nb2 = 1;
321 }
322 }
323 } // else if nb2 < MinNbElementsOnLength
324
325 if (nb2 > MaxNbElementsOnLength) {
326 fprintf(fMeshLog, "Too many elements on Length2 of primitive %d!\n",
327 prim);
328 fprintf(fMeshLog, "Number of elements reduced to maximum allowed %d\n",
331 }
332
333 *NbSegCoord1 = nb1;
334 *NbSegCoord2 = nb2;
335
336 fprintf(fMeshLog,
337 "Number of elements on surface primitive %d is %d X %d.\n\n", prim,
338 *NbSegCoord1, *NbSegCoord2);
339 } else { // number of discretization specified by the user
340 // Triangle primitives have their right angle on the vertex 1
341 double l1 = (XVertex[prim][0] - XVertex[prim][1]) *
342 (XVertex[prim][0] - XVertex[prim][1]) +
343 (YVertex[prim][0] - YVertex[prim][1]) *
344 (YVertex[prim][0] - YVertex[prim][1]) +
345 (ZVertex[prim][0] - ZVertex[prim][1]) *
346 (ZVertex[prim][0] - ZVertex[prim][1]);
347 l1 = sqrt(l1);
348 double l2 = (XVertex[prim][2] - XVertex[prim][1]) *
349 (XVertex[prim][2] - XVertex[prim][1]) +
350 (YVertex[prim][2] - YVertex[prim][1]) *
351 (YVertex[prim][2] - YVertex[prim][1]) +
352 (ZVertex[prim][2] - ZVertex[prim][1]) *
353 (ZVertex[prim][2] - ZVertex[prim][1]);
354 l2 = sqrt(l2);
355
356 if (l1 > l2) {
357 if (nb2 > nb1) {
358 // swap numbers to allow larger number to larger side
359 int tmpnb = nb1;
360 nb1 = nb2;
361 nb2 = tmpnb;
362 }
363 } // if l1 > l2
364
365 double ellength1 = l1 / (double)nb1;
366 double ellength2 = l2 / (double)nb2;
367
368 if (l1 < MINDIST) {
369 nb1 = 1;
370 fprintf(fMeshLog, "Fatal: Side length l1 too small! prim: %d\n", prim);
371 } else if (ellength1 < MINDIST) // element length more than twice MINDIST
372 {
373 nb1 = (int)(l1 / (2.0 * MINDIST));
374 if (nb1 < 1) {
375 nb1 = 1;
376 fprintf(fMeshLog, "Fatal: Side length l1 too small on primitive %d!\n",
377 prim);
378 }
379 } // if ellength1 < MINDIST
380
381 if (l2 < MINDIST) {
382 nb2 = 1;
383 fprintf(fMeshLog, "Fatal: Side length l2 too small! prim: %d\n", prim);
384 } else if (ellength2 < MINDIST) // element length more than twice MINDIST
385 {
386 nb2 = (int)(l2 / (2.0 * MINDIST));
387 if (nb2 < 1) {
388 nb2 = 1;
389 fprintf(fMeshLog, "Fatal: Side length l2 too small on primitive %d!\n",
390 prim);
391 }
392 } // if ellength2 < MINDIST
393
394 *NbSegCoord1 = nb1;
395 *NbSegCoord2 = nb2;
396
397 fprintf(fMeshLog,
398 "Number of elements on surface primitive %d is %d X %d.\n\n", prim,
399 *NbSegCoord1, *NbSegCoord2);
400 }
401
402 if ((nb1 > 0) && (nb2 > 0))
403 return 0;
404 else
405 return -1;
406} // AnalyzeSurface ends
#define MINDIST
Definition: Isles.h:17
DoubleAc sqrt(const DoubleAc &f)
Definition: DoubleAc.cpp:314
neBEMGLOBAL double ** ZVertex
Definition: neBEM.h:71
neBEMGLOBAL double ElementLengthRqstd
Definition: neBEM.h:107
neBEMGLOBAL double ** YVertex
Definition: neBEM.h:71
neBEMGLOBAL double ** XVertex
Definition: neBEM.h:71
neBEMGLOBAL FILE * fMeshLog
Definition: neBEM.h:114
neBEMGLOBAL int MaxNbElementsOnLength
Definition: neBEM.h:105
neBEMGLOBAL int MinNbElementsOnLength
Definition: neBEM.h:103

Referenced by AnalyzePrimitive().

◆ AnalyzeWire()

neBEMGLOBAL int AnalyzeWire ( int  prim,
int *  NbSeg 
)

Definition at line 158 of file ReTriM.c.

158 {
159 int nb = *NbSeg;
160
161 if (nb < 1) // absurd! use the trio: target, min, max
162 {
163 double lWire = (XVertex[prim][1] - XVertex[prim][0]) *
164 (XVertex[prim][1] - XVertex[prim][0]) +
165 (YVertex[prim][1] - YVertex[prim][0]) *
166 (YVertex[prim][1] - YVertex[prim][0]) +
167 (ZVertex[prim][1] - ZVertex[prim][0]) *
168 (ZVertex[prim][1] - ZVertex[prim][0]);
169 lWire = sqrt(lWire);
170
171 nb = (int)(lWire / ElementLengthRqstd);
172
173 if ((nb > MinNbElementsOnLength) &&
174 (nb < MaxNbElementsOnLength)) { // nothing to be done
175 }
176 // Check whether the length of the wire primitive is long enough
177 else if (lWire < MINDIST) {
178 nb = 1;
179 fprintf(fMeshLog, "Wire element too small on primitive %d!\n", prim);
180 } // if lWire < MINDIST
181 // Need to have at least MinNbElementsOnLength elements per wire primitive
182 else if (nb < MinNbElementsOnLength) {
184 double ellength = lWire / (double)nb;
185 if (ellength <
186 MINDIST) // which may not be possible if the length is small
187 {
188 nb = (int)(lWire / MINDIST);
189 if (nb < 1) // However, it is necessary to have at least one element!
190 {
191 nb = 1;
192 fprintf(fMeshLog, "Wire element very small on primitive %d!\n", prim);
193 }
194 }
195 } // if nb < MinNbElementsOnLength
196 else if (nb > MaxNbElementsOnLength) {
198 fprintf(fMeshLog, "Too many elements on wire primitive %d!\n", prim);
199 fprintf(fMeshLog, "Number of elements reduced to maximum allowed %d\n",
201 } // if nb > MaxNbElementsOnLength
202
203 *NbSeg = nb;
204
205 fprintf(fMeshLog, "Number of elements on wire primitive %d is %d.\n\n",
206 prim, *NbSeg);
207 } else { // number of dicretization specified by user
208 double lWire = (XVertex[prim][1] - XVertex[prim][0]) *
209 (XVertex[prim][1] - XVertex[prim][0]) +
210 (YVertex[prim][1] - YVertex[prim][0]) *
211 (YVertex[prim][1] - YVertex[prim][0]) +
212 (ZVertex[prim][1] - ZVertex[prim][0]) *
213 (ZVertex[prim][1] - ZVertex[prim][0]);
214 lWire = sqrt(lWire);
215
216 double ellength = lWire / (double)nb;
217
218 if (lWire < MINDIST) // at least one element is a necessity
219 {
220 nb = 1;
221 fprintf(fMeshLog, "Fatal: Wire element too small on primitive %d!\n",
222 prim);
223 } // if lWire < MINDIST
224 else if (ellength < MINDIST) // element length more than twice MINDIST
225 {
226 nb = (int)(lWire / (2.0 * MINDIST));
227 if (nb < 1) {
228 nb = 1;
229 fprintf(fMeshLog, "Fatal: Wire element too small on primitive %d!\n",
230 prim);
231 }
232 } // if ellength < MINDIST
233
234 *NbSeg = nb;
235
236 fprintf(fMeshLog, "Number of elements on wire primitive %d is %d.\n\n",
237 prim, *NbSeg);
238 }
239
240 if (nb)
241 return 0;
242 else
243 return -1;
244} // AnalyzeWire ends

Referenced by AnalyzePrimitive().

◆ BoundaryConditions()

neBEMGLOBAL int BoundaryConditions ( void  )

Definition at line 2121 of file ReTriM.c.

2121 {
2122 // Loop over all the elements of all the primitives.
2123 // Some of the primitives do not have a boundary condition to be satisfied
2124 // We'll omit these primitives but before doing that we need to know to
2125 // which primitive a particular element belongs to.
2126 // The RHS will also need to be modified to accommodate the presence of
2127 // floating conductors and charged (known) substances.
2128 // Looping on primitives (rather than elements) can save precious time!
2129 for (int ele = 1; ele <= NbElements; ++ele) {
2130 int prim = (EleArr + ele - 1)->PrimitiveNb;
2131 // Note this condition is pure geometry, not electric!
2132 switch (PrimType[prim]) {
2133 case 2:
2134 case 3: // for floating conductor and for dielectric-dielectric intfc
2135 case 4: // the BC is zero (may be modified due to known charges, later)
2136 (EleArr + ele - 1)->BC.Value = ApplPot[prim];
2137 break;
2138
2139 default:
2140 printf("Primitive out of range in BoundaryConditions ... returning\n");
2141 return (-1);
2142 } // switch on PrimType over
2143 } // ele loop over
2144
2145 return (0);
2146} // end of BoundaryConditions
neBEMGLOBAL Element * EleArr
Definition: neBEM.h:169
neBEMGLOBAL double * ApplPot
Definition: neBEM.h:75
neBEMGLOBAL int NbElements
Definition: neBEM.h:113
neBEMGLOBAL int * PrimType
Definition: neBEM.h:67

Referenced by neBEMBoundaryConditions().

◆ ComputeInfluence()

neBEMGLOBAL double ComputeInfluence ( int  fld,
int  src,
Point3D localPt,
DirnCosn3D DirCos 
)

Definition at line 1579 of file neBEM.c.

1580 {
1581 if (DebugLevel == 301) {
1582 printf("In ComputeInfluence ...\n");
1583 }
1584
1585 double value; // influence coefficient
1586
1587 if (0) {
1588 printf("\nContinuity satisfaction using following parameters ...\n");
1589 printf("gtsrc: %d, lxsrc: %lg, lzsrc% lg, dA: %lg\n",
1590 (EleArr + elesrc - 1)->G.Type, (EleArr + elesrc - 1)->G.LX,
1591 (EleArr + elesrc - 1)->G.LZ, (EleArr + elesrc - 1)->G.dA);
1592 printf("xlocal: %lg, ylocal: %lg, zlocal: %lg\n", localP->X, localP->Y,
1593 localP->Z);
1594 }
1595
1596 switch ((EleArr + elefld - 1)
1597 ->E.Type) // depending on the etype at the field point
1598 { // different boundary conditions need to be applied
1599 case 1: // conductor with known potential
1600 value = SatisfyValue(elesrc, localP);
1601 return (value);
1602 break;
1603
1604 case 2: // Conductor with a specified charge - has to have a BC as well!
1605 printf("Conductors with specific charge not implemented yet.\n");
1606 return -1; // The potential has to be the same for the complete
1607 // component.
1608 break; // If the value of pot is known, the situation is same as above.
1609 // if not, it is similar to a floating conductor.
1610
1611 case 3: // floating conductor
1612 value = SatisfyValue(elesrc, localP);
1613 return (value);
1614 // printf("Floating conductors not implemented yet.\n");
1615 // return -1;
1616 break;
1617
1618 // normal component of the displacement vector is continuous across each
1619 // dielectric-to-dielectric interface
1620 case 4: // DD interface
1621 value = SatisfyContinuity(elefld, elesrc, localP, DirCos);
1622 return (value);
1623 break;
1624
1625 case 5: // Dielectric with surface charge density known; same as above BC?
1626 value = SatisfyContinuity(elefld, elesrc, localP, DirCos);
1627 return (value);
1628 // The BC has to be the same and some part of the charge
1629 break; // density necessary to satisfy the BC needs to be solved for.
1630
1631 case 6: // Symmetry boundary, E parallel
1632 printf("Symmetry boundary, E parallel not implemented yet. \n");
1633 return -1;
1634 break;
1635
1636 case 7: // Symmetry boundary, E perpendicular (not likely to be used)
1637 printf("Symmetry boundary, E perpendicular not implemented yet. \n");
1638 return -1;
1639 break;
1640
1641 default:
1642 printf("Electric type %d out of range! ... exiting.\n",
1643 (EleArr + elefld - 1)->E.Type);
1644 return (-1);
1645 break; // unreachable
1646 } // switch on etfld ends
1647} // end of ComputeInfluence
double SatisfyContinuity(int elefld, int elesrc, Point3D *localP, DirnCosn3D *DirCos)
Definition: neBEM.c:1724
double SatisfyValue(int elesrc, Point3D *localP)
Definition: neBEM.c:1686
neBEMGLOBAL int DebugLevel
Definition: neBEM.h:235

Referenced by LHMatrix().

◆ ComputeSolution()

neBEMGLOBAL int ComputeSolution ( void  )

Definition at line 36 of file neBEM.c.

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

Referenced by neBEMSolve().

◆ ContinuityChUp()

neBEMGLOBAL double ContinuityChUp ( int  fld)

◆ ContinuityKnCh()

neBEMGLOBAL double ContinuityKnCh ( int  fld)

Definition at line 2182 of file neBEM.c.

2182 {
2183 int dbgFn = 0;
2184
2185 double value = 0.0;
2186 double xfld = (EleArr + elefld - 1)->BC.CollPt.X;
2187 double yfld = (EleArr + elefld - 1)->BC.CollPt.Y;
2188 double zfld = (EleArr + elefld - 1)->BC.CollPt.Z;
2189 // Point3D globalP;
2190 Point3D localP;
2191 Vector3D localF, globalF;
2192
2193 // OMPCheck - parallelize
2194
2195 // Effect of known charges on interface elements
2196 for (int elesrc = 1; elesrc <= NbElements; ++elesrc) {
2197 double assigned = (EleArr + elesrc - 1)->Assigned;
2198 if (fabs(assigned) <= 1.0e-16) continue;
2199
2200 Point3D *pOrigin = &(EleArr + elesrc - 1)->G.Origin;
2201
2202 // Retrieve element properties from the structure
2203 if ((EleArr + elesrc - 1)->E.Type == 0) {
2204 printf("Wrong EType for elesrc %d element %d on %dth primitive!\n",
2205 elesrc, (EleArr + elesrc - 1)->Id,
2206 (EleArr + elesrc - 1)->PrimitiveNb);
2207 exit(-1);
2208 }
2209
2210 // translated to local origin but axes direction as in GCS
2211 // globalP.X = xfld - pOrigin->X;
2212 // globalP.Y = yfld - pOrigin->Y;
2213 // globalP.Z = zfld - pOrigin->Z;
2214
2215 { // Rotate point3D from global to local system
2216 double TransformationMatrix[3][3] = {{0.0, 0.0, 0.0},
2217 {0.0, 0.0, 0.0},
2218 {0.0, 0.0, 0.0}};
2219 DirnCosn3D *DirCos = &(EleArr + elesrc - 1)->G.DC;
2220
2221 TransformationMatrix[0][0] = DirCos->XUnit.X;
2222 TransformationMatrix[0][1] = DirCos->XUnit.Y;
2223 TransformationMatrix[0][2] = DirCos->XUnit.Z;
2224 TransformationMatrix[1][0] = DirCos->YUnit.X;
2225 TransformationMatrix[1][1] = DirCos->YUnit.Y;
2226 TransformationMatrix[1][2] = DirCos->YUnit.Z;
2227 TransformationMatrix[2][0] = DirCos->ZUnit.X;
2228 TransformationMatrix[2][1] = DirCos->ZUnit.Y;
2229 TransformationMatrix[2][2] = DirCos->ZUnit.Z;
2230
2231 double InitialVector[3] = {xfld - pOrigin->X, yfld - pOrigin->Y, zfld - pOrigin->Z};
2232 double FinalVector[3] = {0., 0., 0.};
2233 for (int i = 0; i < 3; ++i) {
2234 for (int j = 0; j < 3; ++j) {
2235 FinalVector[i] += TransformationMatrix[i][j] * InitialVector[j];
2236 }
2237 }
2238
2239 localP.X = FinalVector[0];
2240 localP.Y = FinalVector[1];
2241 localP.Z = FinalVector[2];
2242 } // Point3D rotated
2243
2244 // if((((EleArr+elesrc-1)->E.Type == 4) && (elefld == elesrc)) //
2245 // self-influence
2246 // || (((EleArr+elesrc-1)->E.Type == 5) && (elefld == elesrc))) // DD
2247 // intfce
2248 // For self-influence, lmsrc is equal to lmfld which allows the following.
2249 if ((elefld == elesrc) &&
2250 (fabs(localP.X) < (EleArr + elesrc - 1)->G.LX / 2.0) &&
2251 (fabs(localP.Y) < MINDIST) &&
2252 (fabs(localP.Z) < (EleArr + elesrc - 1)->G.LZ / 2.0)) {
2253 value += assigned * 1.0 / (2.0 * EPS0 * (EleArr + elesrc - 1)->E.Lambda);
2254 } else {
2255 // Retrieve element properties from the structure
2256 if ((EleArr + elesrc - 1)->E.Type == 0) {
2257 printf("Wrong EType for elesrc %d element %d on %dth primitive!\n",
2258 elesrc, (EleArr + elesrc - 1)->Id,
2259 (EleArr + elesrc - 1)->PrimitiveNb);
2260 exit(-1);
2261 }
2262
2263 // Following fluxes in the influencing ECS
2264 switch ((EleArr + elesrc - 1)->G.Type) {
2265 case 4: // rectangular element
2266 RecFlux(elesrc, &localP, &localF);
2267 break;
2268 case 3: // triangular element
2269 TriFlux(elesrc, &localP, &localF);
2270 break;
2271 case 2: // linear (wire) element
2272 WireFlux(elesrc, &localP, &localF);
2273 break;
2274 default:
2275 printf("Geometrical type out of range! ... exiting ...\n");
2276 exit(-1);
2277 break; // never comes here
2278 } // switch over gtsrc ends
2279
2280 // in GCS - mirror points?!
2281 globalF =
2282 RotateVector3D(&localF, &(EleArr + elesrc - 1)->G.DC, local2global);
2283 // in ECS (local to the field element)
2284 localF =
2285 RotateVector3D(&globalF, &(EleArr + elefld - 1)->G.DC, global2local);
2286
2287 value -= assigned * localF.Y; // +ve gradient of Green's is -ve normal
2288 // force (changed from -= to += on 02/11/11
2289 // - CHECK!!! - and back to -= on 05/11/11)
2290 } // else self-influence
2291 }
2292
2293 if (dbgFn) {
2294 printf("value: %g\n", value);
2295 }
2296
2297 // Contributions from points, lines areas and volumes carrying known charge
2298 // (density).
2299 // globalP.X = xfld;
2300 // globalP.Y = yfld;
2301 // globalP.Z = zfld;
2302 for (int point = 1; point <= NbPointsKnCh; ++point) {
2303 // potential not being used to evaluate Neumann continuity
2304 // double tempPot =
2305 // PointKnChPF((PointKnChArr + point - 1)->P, globalP, &globalF);
2306 localF =
2307 RotateVector3D(&globalF, &(EleArr + elefld - 1)->G.DC, global2local);
2308 value -= (PointKnChArr + point - 1)->Assigned * localF.Y / MyFACTOR;
2309 } // loop over points NbPointsKnCh
2310
2311 for (int line = 1; line <= NbLinesKnCh; ++line) {
2312 // potential not being used to evaluate Neumann continuity
2313 // double tempPot = LineKnChPF(
2314 // (LineKnChArr + line - 1)->Start, (LineKnChArr + line - 1)->Stop,
2315 // (LineKnChArr + line - 1)->Radius, globalP, &globalF);
2316 localF =
2317 RotateVector3D(&globalF, &(EleArr + elefld - 1)->G.DC, global2local);
2318 value -= (LineKnChArr + line - 1)->Assigned * localF.Y / MyFACTOR;
2319 } // loop over lines
2320
2321 for (int area = 1; area <= NbAreasKnCh; ++area) {
2322 // potential not being used to evaluate Neumann continuity
2323 // double tempPot =
2324 // AreaKnChPF((AreaKnChArr + area - 1)->NbVertices,
2325 // ((AreaKnChArr + area - 1)->Vertex), globalP, &globalF);
2326 localF =
2327 RotateVector3D(&globalF, &(EleArr + elefld - 1)->G.DC, global2local);
2328 value -= (AreaKnChArr + area - 1)->Assigned * localF.Y / MyFACTOR;
2329 } // loop over areas
2330
2331 for (int vol = 1; vol <= NbVolumesKnCh; ++vol) {
2332 // potential not being used to evaluate Neumann continuity
2333 // double tempPot =
2334 // VolumeKnChPF((VolumeKnChArr + vol - 1)->NbVertices,
2335 // ((VolumeKnChArr + vol - 1)->Vertex), globalP, &globalF);
2336 localF =
2337 RotateVector3D(&globalF, &(EleArr + elefld - 1)->G.DC, global2local);
2338 value -= (VolumeKnChArr + vol - 1)->Assigned * localF.Y / MyFACTOR;
2339 } // loop over volumes
2340
2341 return (value);
2342} // end of ContinuityKnCh
void TriFlux(int ele, Point3D *localP, Vector3D *localF)
void RecFlux(int ele, Point3D *localP, Vector3D *localF)
void WireFlux(int ele, Point3D *localP, Vector3D *localF)
Vector3D RotateVector3D(Vector3D *A, DirnCosn3D *DC, int Sense)
Definition: Vector.c:397
#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:181
neBEMGLOBAL VolumeKnCh * VolumeKnChArr
Definition: neBEM.h:216
neBEMGLOBAL int NbPointsKnCh
Definition: neBEM.h:172
neBEMGLOBAL AreaKnCh * AreaKnChArr
Definition: neBEM.h:204
neBEMGLOBAL int NbLinesKnCh
Definition: neBEM.h:172
neBEMGLOBAL int NbVolumesKnCh
Definition: neBEM.h:172
neBEMGLOBAL int NbAreasKnCh
Definition: neBEM.h:172
neBEMGLOBAL LineKnCh * LineKnChArr
Definition: neBEM.h:192
#define MyFACTOR
Definition: neBEM.h:21
Vector3D ZUnit
Definition: Vector.h:38
Vector3D YUnit
Definition: Vector.h:37
Vector3D XUnit
Definition: Vector.h:36
Definition: Vector.h:21
double X
Definition: Vector.h:22
double Z
Definition: Vector.h:24
double Y
Definition: Vector.h:23
double Z
Definition: Vector.h:31
double Y
Definition: Vector.h:30
double X
Definition: Vector.h:29

◆ DiscretizePolygon()

neBEMGLOBAL int DiscretizePolygon ( int  prim,
int  nvertex,
double  xvert[],
double  yvert[],
double  zvert[],
double  xnorm,
double  ynorm,
double  znorm,
int  volref1,
int  volref2,
int  inttype,
double  potential,
double  charge,
double  lambda,
int  NbSegX,
int  NbSegZ 
)

Definition at line 2106 of file ReTriM.c.

2111 {
2112 // Check inputs
2113 if ((NbSegX <= 0) || (NbSegZ <= 0)) {
2114 printf("segmentation input wrong in DiscretizePolygon ...\n");
2115 return -1;
2116 }
2117
2118 return (0);
2119} // end of DiscretizePolygon

◆ DiscretizeRectangle()

neBEMGLOBAL int DiscretizeRectangle ( int  prim,
int  nvertex,
double  xvert[],
double  yvert[],
double  zvert[],
double  xnorm,
double  ynorm,
double  znorm,
int  volref1,
int  volref2,
int  inttype,
double  potential,
double  charge,
double  lambda,
int  NbSegX,
int  NbSegZ 
)

Definition at line 1590 of file ReTriM.c.

1594 {
1595 int SurfParentObj, SurfEType;
1596 double SurfX, SurfY, SurfZ, SurfLX, SurfLZ;
1597 double SurfElX, SurfElY, SurfElZ, SurfElLX, SurfElLZ;
1598 DirnCosn3D PrimDirnCosn; // direction cosine of the current primitive
1599 char primstr[10];
1600 char gpElem[256], gpMesh[256];
1601 FILE *fPrim, *fElem, *fgpPrim, *fgpElem, *fgpMesh;
1602
1603 // Check inputs
1604 if ((NbSegX <= 0) || (NbSegZ <= 0)) {
1605 printf("segmentation input wrong in DiscretizeRectangle ...\n");
1606 return -1;
1607 }
1608
1610 printf("nvertex: %d\n", nvertex);
1611 for (int vert = 0; vert < nvertex; ++vert) {
1612 printf("vert: %d, x: %lg, y: %lg, z: %lg\n", vert, xvert[vert],
1613 yvert[vert], zvert[vert]);
1614 }
1615 printf("Normal: %lg, %lg, %lg\n", xnorm, ynorm, znorm);
1616 } // if OptPrintVertexAndNormal
1617
1618 // necessary for separating filenames
1619 sprintf(primstr, "%d", prim);
1620
1621 // in order to avoid warning messages
1622 fPrim = NULL;
1623 fElem = NULL;
1624 fgpMesh = NULL;
1625 fgpElem = NULL;
1626
1627 // Get volume information, to begin with
1628 // int shape, material, boundarytype;
1629 // double eps, potential, charge;
1630 // neBEMVolumeDescription(volref1, &shape, &material,
1631 // &eps, &potential, &charge, &boundarytype);
1632
1633 // compute all the properties of this surface
1634 SurfParentObj = 1;
1635 SurfEType = inttype;
1636 if (SurfEType == 0) {
1637 printf("Wrong SurfEType for prim %d\n", prim);
1638 exit(-1);
1639 }
1640 // centroid of the local coordinate system
1641 SurfX = 0.25 * (xvert[0] + xvert[1] + xvert[2] + xvert[3]);
1642 SurfY = 0.25 * (yvert[0] + yvert[1] + yvert[2] + yvert[3]);
1643 SurfZ = 0.25 * (zvert[0] + zvert[1] + zvert[2] + zvert[3]);
1644 // lengths of the sides
1645 SurfLX = sqrt((xvert[1] - xvert[0]) * (xvert[1] - xvert[0]) +
1646 (yvert[1] - yvert[0]) * (yvert[1] - yvert[0]) +
1647 (zvert[1] - zvert[0]) * (zvert[1] - zvert[0]));
1648 SurfLZ = sqrt((xvert[2] - xvert[1]) * (xvert[2] - xvert[1]) +
1649 (yvert[2] - yvert[1]) * (yvert[2] - yvert[1]) +
1650 (zvert[2] - zvert[1]) * (zvert[2] - zvert[1]));
1651 // Direction cosines
1652 PrimDirnCosn.XUnit.X = (xvert[1] - xvert[0]) / SurfLX;
1653 PrimDirnCosn.XUnit.Y = (yvert[1] - yvert[0]) / SurfLX;
1654 PrimDirnCosn.XUnit.Z = (zvert[1] - zvert[0]) / SurfLX;
1655 PrimDirnCosn.YUnit.X = xnorm;
1656 PrimDirnCosn.YUnit.Y = ynorm;
1657 PrimDirnCosn.YUnit.Z = znorm;
1658 PrimDirnCosn.ZUnit =
1659 Vector3DCrossProduct(&PrimDirnCosn.XUnit, &PrimDirnCosn.YUnit);
1660
1661 // primitive direction cosine assignments
1662 PrimDC[prim].XUnit.X = PrimDirnCosn.XUnit.X;
1663 PrimDC[prim].XUnit.Y = PrimDirnCosn.XUnit.Y;
1664 PrimDC[prim].XUnit.Z = PrimDirnCosn.XUnit.Z;
1665 PrimDC[prim].YUnit.X = PrimDirnCosn.YUnit.X;
1666 PrimDC[prim].YUnit.Y = PrimDirnCosn.YUnit.Y;
1667 PrimDC[prim].YUnit.Z = PrimDirnCosn.YUnit.Z;
1668 PrimDC[prim].ZUnit.X = PrimDirnCosn.ZUnit.X;
1669 PrimDC[prim].ZUnit.Y = PrimDirnCosn.ZUnit.Y;
1670 PrimDC[prim].ZUnit.Z = PrimDirnCosn.ZUnit.Z;
1671
1672 // primitive origin: also the barcenter for a rectangular element
1673 PrimOriginX[prim] = SurfX;
1674 PrimOriginY[prim] = SurfY;
1675 PrimOriginZ[prim] = SurfZ;
1676 PrimLX[prim] = SurfLX;
1677 PrimLZ[prim] = SurfLZ;
1678
1679 double SurfLambda = lambda;
1680 double SurfV = potential;
1681
1682 // file output for a primitive
1683 if (OptPrimitiveFiles) {
1684 char OutPrim[256];
1685 strcpy(OutPrim, ModelOutDir);
1686 strcat(OutPrim, "/Primitives/Primitive");
1687 strcat(OutPrim, primstr);
1688 strcat(OutPrim, ".out");
1689 fPrim = fopen(OutPrim, "w");
1690 if (fPrim == NULL) {
1691 neBEMMessage("DiscretizeRectangle - OutPrim");
1692 return -1;
1693 }
1694 fprintf(fPrim, "#prim: %d, nvertex: %d\n", prim, nvertex);
1695 fprintf(fPrim, "Node1: %lg\t%lg\t%lg\n", xvert[0], yvert[0], zvert[0]);
1696 fprintf(fPrim, "Node2: %lg\t%lg\t%lg\n", xvert[1], yvert[1], zvert[1]);
1697 fprintf(fPrim, "Node3: %lg\t%lg\t%lg\n", xvert[2], yvert[2], zvert[2]);
1698 fprintf(fPrim, "Node4: %lg\t%lg\t%lg\n", xvert[3], yvert[3], zvert[3]);
1699 fprintf(fPrim, "PrimOrigin: %lg\t%lg\t%lg\n", PrimOriginX[prim],
1700 PrimOriginY[prim], PrimOriginZ[prim]);
1701 fprintf(fPrim, "Primitive lengths: %lg\t%lg\n", PrimLX[prim], PrimLZ[prim]);
1702 fprintf(fPrim, "Norm: %lg\t%lg\t%lg\n", xnorm, ynorm, znorm);
1703 fprintf(fPrim, "#volref1: %d, volref2: %d\n", volref1, volref2);
1704 fprintf(fPrim, "#NbSegX: %d, NbSegZ: %d\n", NbSegX, NbSegZ);
1705 fprintf(fPrim, "#ParentObj: %d\tEType: %d\n", SurfParentObj, SurfEType);
1706 fprintf(fPrim, "#SurfX\tSurfY\tSurfZ\tSurfLZ\tSurfLZ\n");
1707 fprintf(fPrim, "%lg\t%lg\t%lg\t%lg\t%lg\n", SurfX, SurfY, SurfZ, SurfLX,
1708 SurfLZ);
1709 // fprintf(fPrim, "#SurfRX: %lg\tSurfRY: %lg\tSurfRZ: %lg\n",
1710 // SurfRX, SurfRY, SurfRZ);
1711 fprintf(fPrim, "#DirnCosn: \n");
1712 fprintf(fPrim, "%lg, %lg, %lg\n", PrimDirnCosn.XUnit.X,
1713 PrimDirnCosn.XUnit.Y, PrimDirnCosn.XUnit.Z);
1714 fprintf(fPrim, "%lg, %lg, %lg\n", PrimDirnCosn.YUnit.X,
1715 PrimDirnCosn.YUnit.Y, PrimDirnCosn.YUnit.Z);
1716 fprintf(fPrim, "%lg, %lg, %lg\n", PrimDirnCosn.ZUnit.X,
1717 PrimDirnCosn.ZUnit.Y, PrimDirnCosn.ZUnit.Z);
1718 fprintf(fPrim, "#SurfLambda: %lg\tSurfV: %lg\n", SurfLambda, SurfV);
1719 } // if OptPrimitiveFiles
1720
1721 // necessary for gnuplot
1723 char gpPrim[256];
1724 strcpy(gpPrim, MeshOutDir);
1725 strcat(gpPrim, "/GViewDir/gpPrim");
1726 strcat(gpPrim, primstr);
1727 strcat(gpPrim, ".out");
1728 fgpPrim = fopen(gpPrim, "w");
1729 if (fgpPrim == NULL) {
1730 neBEMMessage("DiscretizeRectangle - OutgpPrim");
1731 return -1;
1732 }
1733 fprintf(fgpPrim, "%g\t%g\t%g\n\n", xvert[0], yvert[0], zvert[0]);
1734 fprintf(fgpPrim, "%g\t%g\t%g\n\n", xvert[1], yvert[1], zvert[1]);
1735 fprintf(fgpPrim, "%g\t%g\t%g\n\n", xvert[2], yvert[2], zvert[2]);
1736 fprintf(fgpPrim, "%g\t%g\t%g\n\n", xvert[3], yvert[3], zvert[3]);
1737 fprintf(fgpPrim, "%g\t%g\t%g\n", xvert[0], yvert[0], zvert[0]);
1738 fclose(fgpPrim);
1739
1740 if (prim == 1)
1741 fprintf(fgnuPrim, " '%s\' w l", gpPrim);
1742 else
1743 fprintf(fgnuPrim, ", \\\n \'%s\' w l", gpPrim);
1744 } // if OptGnuplot && OptGnuplotPrimitives
1745
1746 // file outputs for elements on primitive
1747 if (OptElementFiles) {
1748 char OutElem[256];
1749 strcpy(OutElem, MeshOutDir);
1750 strcat(OutElem, "/Elements/ElemOnPrim");
1751 strcat(OutElem, primstr);
1752 strcat(OutElem, ".out");
1753 fElem = fopen(OutElem, "w");
1754 // assert(fElem != NULL);
1755 if (fElem == NULL) {
1756 neBEMMessage("DiscretizeRectangle - OutElem");
1757 return -1;
1758 }
1759 } // if OptElementFiles
1760
1761 // gnuplot friendly file outputs for elements on primitive
1763 strcpy(gpElem, MeshOutDir);
1764 strcat(gpElem, "/GViewDir/gpElemOnPrim");
1765 strcat(gpElem, primstr);
1766 strcat(gpElem, ".out");
1767 fgpElem = fopen(gpElem, "w");
1768 // assert(fgpElem != NULL);
1769 if (fgpElem == NULL) {
1770 neBEMMessage("DiscretizeRectangle - OutgpElem");
1771 if (fElem) fclose(fElem);
1772 return -1;
1773 }
1774 // gnuplot friendly file outputs for elements on primitive
1775 strcpy(gpMesh, MeshOutDir);
1776 strcat(gpMesh, "/GViewDir/gpMeshOnPrim");
1777 strcat(gpMesh, primstr);
1778 strcat(gpMesh, ".out");
1779 fgpMesh = fopen(gpMesh, "w");
1780 if (fgpMesh == NULL) {
1781 neBEMMessage("DiscretizeRectangle - OutgpMesh");
1782 fclose(fgpElem);
1783 return -1;
1784 }
1785 } // if OptGnuplot && OptElements
1786
1787 // Compute element positions (CGs) in the primitive local coordinate system.
1788 // Then map these CGs to the global coordinate system.
1789 // (xav, 0, zav) is the CG of an element wrt the primitive coordinate system
1790 // From this, we find the offset of the element from the primitive CG in the
1791 // global coordinate system by just rotating the displacement vector
1792 // (0,0,0) -> (xav,0,zav) using the known DCM of the surface.
1793 // This rotated vector (now in the global system) is then added to the
1794 // position vector of the primitive CG (always in the global system) to get
1795 // the CG of the element in the global system. Make sure that the larger
1796 // number is being used to discretize the longer side - can be OverSmart in
1797 // certain cases - there may be cases where smaller number of elements suffice
1798 // for a longer side
1799 if (NbSegX == NbSegZ) {
1800 SurfElLX = SurfLX / NbSegX; // element sizes
1801 SurfElLZ = SurfLZ / NbSegZ;
1802 } else if (NbSegX > NbSegZ) {
1803 if (SurfLX > SurfLZ) {
1804 SurfElLX = SurfLX / NbSegX; // element sizes
1805 SurfElLZ = SurfLZ / NbSegZ;
1806 } else // interchange NbSegX and NbSegZ
1807 {
1808 int tmp = NbSegZ;
1809 NbSegZ = NbSegX;
1810 NbSegX = tmp;
1811 SurfElLX = SurfLX / NbSegX; // element sizes
1812 SurfElLZ = SurfLZ / NbSegZ;
1813 }
1814 } // NbSegX > NbSegZ
1815 else // NbSegX < NbSegZ
1816 {
1817 if (SurfLX < SurfLZ) {
1818 SurfElLX = SurfLX / NbSegX; // element sizes
1819 SurfElLZ = SurfLZ / NbSegZ;
1820 } else // interchange NbSegX and NbSegZ
1821 {
1822 int tmp = NbSegZ;
1823 NbSegZ = NbSegX;
1824 NbSegX = tmp;
1825 SurfElLX = SurfLX / NbSegX; // element sizes
1826 SurfElLZ = SurfLZ / NbSegZ;
1827 }
1828 }
1829
1830 // Analysis of element aspect ratio.
1831 // Note that we can afford only to reduce the total number of elements.
1832 // Otherwise, we'll have to realloc `EleArr' array.
1833 // Later, we'll make the corrections such that the total number of elements
1834 // remain close to the originally intended value.
1835 double AR = SurfElLX / SurfElLZ; // indicative element aspect ratio
1836 if (OptPrimitiveFiles) {
1837 fprintf(fPrim,
1838 "Using the input, the aspect ratio of the elements on prim: %d\n",
1839 prim);
1840 fprintf(fPrim,
1841 "NbSegX: %d, SurfElLX: %lg, NbSegZ: %d, SurfElLZ: %lg, AR: %lg\n",
1842 NbSegX, SurfElLX, NbSegZ, SurfElLZ, AR);
1843 }
1844 if (AR > 10.0) // NbSegZ needs to be reduced
1845 {
1846 double tmpElLZ = SurfElLX / 10.0;
1847 NbSegZ = (int)(SurfLZ / tmpElLZ);
1848 if (NbSegZ <= 0) NbSegZ = 1;
1849 SurfElLZ = SurfLZ / NbSegZ;
1850 }
1851 if (AR < 0.1) // NbSegX need to be reduced
1852 {
1853 double tmpElLX = SurfElLZ * 0.1;
1854 NbSegX = (int)(SurfLX / tmpElLX);
1855 if (NbSegX <= 0) NbSegX = 1;
1856 SurfElLX = SurfLX / NbSegX;
1857 }
1858 AR = SurfElLX / SurfElLZ; // indicative element aspect ratio
1859 if (OptPrimitiveFiles) {
1860 fprintf(fPrim, "After analyzing the aspect ratio of the elements\n");
1861 fprintf(fPrim,
1862 "NbSegX: %d, SurfElLX: %lg, NbSegZ: %d, SurfElLZ: %lg, AR: %lg\n",
1863 NbSegX, SurfElLX, NbSegZ, SurfElLZ, AR);
1864 }
1865
1866 double x0, y0, z0, x1, y1, z1, x2, y2, z2, x3, y3, z3, xav, zav;
1867 ElementBgn[prim] = EleCntr + 1;
1868 for (int i = 1; i <= NbSegX; ++i) {
1869 x1 = -SurfLX / 2.0 +
1870 (double)(i - 1) * SurfElLX; // assuming centroid at 0,0,0
1871 x2 = -SurfLX / 2.0 + (double)(i)*SurfElLX;
1872 xav = 0.5 * (x1 + x2);
1873
1874 for (int k = 1; k <= NbSegZ; ++k) {
1875 z1 = -SurfLZ / 2.0 + (double)(k - 1) * SurfElLZ;
1876 z2 = -SurfLZ / 2.0 + (double)(k)*SurfElLZ;
1877 zav = 0.5 * (z1 + z2);
1878
1879 { // Separate block for position rotation - local2global
1880 Point3D localDisp, globalDisp;
1881
1882 localDisp.X = xav;
1883 localDisp.Y = 0.0;
1884 localDisp.Z = zav;
1885 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1886 SurfElX = SurfX + globalDisp.X;
1887 SurfElY = SurfY + globalDisp.Y;
1888 SurfElZ = SurfZ + globalDisp.Z;
1889 } // vector rotation over
1890
1891 // Assign element values and write in the file
1892 ++EleCntr;
1893 if (EleCntr > NbElements) {
1894 neBEMMessage("DiscretizeRectangle - EleCntr more than NbElements!");
1895 if (fgpMesh) fclose(fgpMesh);
1896 return -1;
1897 }
1898
1899 (EleArr + EleCntr - 1)->DeviceNb =
1900 1; // At present, there is only one device
1901 (EleArr + EleCntr - 1)->ComponentNb = SurfParentObj;
1902 (EleArr + EleCntr - 1)->PrimitiveNb = prim;
1903 (EleArr + EleCntr - 1)->Id = EleCntr;
1904 (EleArr + EleCntr - 1)->G.Type = 4; // rectangular here
1905 (EleArr + EleCntr - 1)->G.Origin.X = SurfElX;
1906 (EleArr + EleCntr - 1)->G.Origin.Y = SurfElY;
1907 (EleArr + EleCntr - 1)->G.Origin.Z = SurfElZ;
1908 (EleArr + EleCntr - 1)->G.LX = SurfElLX;
1909 (EleArr + EleCntr - 1)->G.LZ = SurfElLZ;
1910 (EleArr + EleCntr - 1)->G.dA =
1911 (EleArr + EleCntr - 1)->G.LX * (EleArr + EleCntr - 1)->G.LZ;
1912 (EleArr + EleCntr - 1)->G.DC.XUnit.X = PrimDirnCosn.XUnit.X;
1913 (EleArr + EleCntr - 1)->G.DC.XUnit.Y = PrimDirnCosn.XUnit.Y;
1914 (EleArr + EleCntr - 1)->G.DC.XUnit.Z = PrimDirnCosn.XUnit.Z;
1915 (EleArr + EleCntr - 1)->G.DC.YUnit.X = PrimDirnCosn.YUnit.X;
1916 (EleArr + EleCntr - 1)->G.DC.YUnit.Y = PrimDirnCosn.YUnit.Y;
1917 (EleArr + EleCntr - 1)->G.DC.YUnit.Z = PrimDirnCosn.YUnit.Z;
1918 (EleArr + EleCntr - 1)->G.DC.ZUnit.X = PrimDirnCosn.ZUnit.X;
1919 (EleArr + EleCntr - 1)->G.DC.ZUnit.Y = PrimDirnCosn.ZUnit.Y;
1920 (EleArr + EleCntr - 1)->G.DC.ZUnit.Z = PrimDirnCosn.ZUnit.Z;
1921 (EleArr + EleCntr - 1)->E.Type = SurfEType;
1922 (EleArr + EleCntr - 1)->E.Lambda = SurfLambda;
1923 (EleArr + EleCntr - 1)->Solution = 0.0;
1924 (EleArr + EleCntr - 1)->Assigned = charge;
1925 (EleArr + EleCntr - 1)->BC.NbOfBCs = 1; // assume one BC per element
1926 (EleArr + EleCntr - 1)->BC.CollPt.X = (EleArr + EleCntr - 1)->G.Origin.X;
1927 (EleArr + EleCntr - 1)->BC.CollPt.Y = (EleArr + EleCntr - 1)->G.Origin.Y;
1928 (EleArr + EleCntr - 1)->BC.CollPt.Z = (EleArr + EleCntr - 1)->G.Origin.Z;
1929
1930 // find element vertices
1931 // 1) displacement vector in the ECS is first identified
1932 // 2) this vector is transformed to the GCS
1933 // 3) the global displacement vector, when added to the centroid in GCS,
1934 // gives the node positions in GCS.
1935 x0 = -0.5 *
1936 (EleArr + EleCntr - 1)->G.LX; // xyz displacement of node wrt ECS
1937 y0 = 0.0;
1938 z0 = -0.5 * (EleArr + EleCntr - 1)->G.LZ;
1939 { // Separate block for position rotation - local2global
1940 Point3D localDisp, globalDisp;
1941
1942 localDisp.X = x0;
1943 localDisp.Y = y0;
1944 localDisp.Z = z0; // displacement in GCS
1945 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1946 x0 = (EleArr + EleCntr - 1)->G.Origin.X +
1947 globalDisp.X; // xyz position in GCS
1948 y0 = (EleArr + EleCntr - 1)->G.Origin.Y + globalDisp.Y;
1949 z0 = (EleArr + EleCntr - 1)->G.Origin.Z + globalDisp.Z;
1950 } // position rotation over
1951
1952 x1 = 0.5 * (EleArr + EleCntr - 1)->G.LX;
1953 y1 = 0.0;
1954 z1 = -0.5 * (EleArr + EleCntr - 1)->G.LZ;
1955 { // Separate block for position rotation - local2global
1956 Point3D localDisp, globalDisp;
1957
1958 localDisp.X = x1;
1959 localDisp.Y = y1;
1960 localDisp.Z = z1;
1961 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1962 x1 = (EleArr + EleCntr - 1)->G.Origin.X + globalDisp.X;
1963 y1 = (EleArr + EleCntr - 1)->G.Origin.Y + globalDisp.Y;
1964 z1 = (EleArr + EleCntr - 1)->G.Origin.Z + globalDisp.Z;
1965 } // position rotation over
1966
1967 x2 = 0.5 * (EleArr + EleCntr - 1)->G.LX;
1968 y2 = 0.0;
1969 z2 = 0.5 * (EleArr + EleCntr - 1)->G.LZ;
1970 { // Separate block for position rotation - local2global
1971 Point3D localDisp, globalDisp;
1972
1973 localDisp.X = x2;
1974 localDisp.Y = y2;
1975 localDisp.Z = z2;
1976 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1977 x2 = (EleArr + EleCntr - 1)->G.Origin.X + globalDisp.X;
1978 y2 = (EleArr + EleCntr - 1)->G.Origin.Y + globalDisp.Y;
1979 z2 = (EleArr + EleCntr - 1)->G.Origin.Z + globalDisp.Z;
1980 } // position rotation over
1981
1982 x3 = -0.5 * (EleArr + EleCntr - 1)->G.LX;
1983 y3 = 0.0;
1984 z3 = 0.5 * (EleArr + EleCntr - 1)->G.LZ;
1985 { // Separate block for position rotation - local2global
1986 Point3D localDisp, globalDisp;
1987
1988 localDisp.X = x3;
1989 localDisp.Y = y3;
1990 localDisp.Z = z3;
1991 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1992 x3 = (EleArr + EleCntr - 1)->G.Origin.X + globalDisp.X;
1993 y3 = (EleArr + EleCntr - 1)->G.Origin.Y + globalDisp.Y;
1994 z3 = (EleArr + EleCntr - 1)->G.Origin.Z + globalDisp.Z;
1995 } // position rotation over
1996
1997 // assign vertices of the element
1998 (EleArr + EleCntr - 1)->G.Vertex[0].X = x0;
1999 (EleArr + EleCntr - 1)->G.Vertex[0].Y = y0;
2000 (EleArr + EleCntr - 1)->G.Vertex[0].Z = z0;
2001 (EleArr + EleCntr - 1)->G.Vertex[1].X = x1;
2002 (EleArr + EleCntr - 1)->G.Vertex[1].Y = y1;
2003 (EleArr + EleCntr - 1)->G.Vertex[1].Z = z1;
2004 (EleArr + EleCntr - 1)->G.Vertex[2].X = x2;
2005 (EleArr + EleCntr - 1)->G.Vertex[2].Y = y2;
2006 (EleArr + EleCntr - 1)->G.Vertex[2].Z = z2;
2007 (EleArr + EleCntr - 1)->G.Vertex[3].X = x3;
2008 (EleArr + EleCntr - 1)->G.Vertex[3].Y = y3;
2009 (EleArr + EleCntr - 1)->G.Vertex[3].Z = z3;
2010
2011 if (OptElementFiles) {
2012 fprintf(fElem, "##Element Counter: %d\n", EleCntr);
2013 fprintf(fElem, "#DevNb\tCompNb\tPrimNb\tId\n");
2014 fprintf(fElem, "%d\t%d\t%d\t%d\n", (EleArr + EleCntr - 1)->DeviceNb,
2015 (EleArr + EleCntr - 1)->ComponentNb,
2016 (EleArr + EleCntr - 1)->PrimitiveNb,
2017 (EleArr + EleCntr - 1)->Id);
2018 fprintf(fElem, "#GType\tX\tY\tZ\tLX\tLZ\tdA\n");
2019 fprintf(
2020 fElem, "%d\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n",
2021 (EleArr + EleCntr - 1)->G.Type, (EleArr + EleCntr - 1)->G.Origin.X,
2022 (EleArr + EleCntr - 1)->G.Origin.Y,
2023 (EleArr + EleCntr - 1)->G.Origin.Z, (EleArr + EleCntr - 1)->G.LX,
2024 (EleArr + EleCntr - 1)->G.LZ, (EleArr + EleCntr - 1)->G.dA);
2025 fprintf(fElem, "#DirnCosn: \n");
2026 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.XUnit.X,
2027 (EleArr + EleCntr - 1)->G.DC.XUnit.Y,
2028 (EleArr + EleCntr - 1)->G.DC.XUnit.Z);
2029 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.YUnit.X,
2030 (EleArr + EleCntr - 1)->G.DC.YUnit.Y,
2031 (EleArr + EleCntr - 1)->G.DC.YUnit.Z);
2032 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.ZUnit.X,
2033 (EleArr + EleCntr - 1)->G.DC.ZUnit.Y,
2034 (EleArr + EleCntr - 1)->G.DC.ZUnit.Z);
2035 fprintf(fElem, "#EType\tLambda\n");
2036 fprintf(fElem, "%d\t%lg\n", (EleArr + EleCntr - 1)->E.Type,
2037 (EleArr + EleCntr - 1)->E.Lambda);
2038 fprintf(fElem, "#NbBCs\tCPX\tCPY\tCPZ\tValue\n");
2039 fprintf(fElem, "%d\t%lg\t%lg\t%lg\t%lg\n",
2040 (EleArr + EleCntr - 1)->BC.NbOfBCs,
2041 (EleArr + EleCntr - 1)->BC.CollPt.X,
2042 (EleArr + EleCntr - 1)->BC.CollPt.Y,
2043 (EleArr + EleCntr - 1)->BC.CollPt.Z,
2044 (EleArr + EleCntr - 1)->BC.Value);
2045 } // if OptElementFiles
2046
2047 // mark centroid
2049 fprintf(fgpElem, "%g\t%g\t%g\n", (EleArr + EleCntr - 1)->BC.CollPt.X,
2050 (EleArr + EleCntr - 1)->BC.CollPt.Y,
2051 (EleArr + EleCntr - 1)->BC.CollPt.Z);
2052 } // if OptGnuplot && OptGnuplotElements
2053
2055 fprintf(fgpMesh, "%g\t%g\t%g\n", x0, y0, z0);
2056 fprintf(fgpMesh, "%g\t%g\t%g\n", x1, y1, z1);
2057 fprintf(fgpMesh, "%g\t%g\t%g\n", x2, y2, z2);
2058 fprintf(fgpMesh, "%g\t%g\t%g\n", x3, y3, z3);
2059 fprintf(fgpMesh, "%g\t%g\t%g\n\n", x0, y0, z0);
2060 /*
2061 fprintf(fgpMesh, "%g\t%g\t%g\t%d\n", x0, y0, z0, 1);
2062 fprintf(fgpMesh, "%g\t%g\t%g\t%d\n\n", x1, y1, z1, 2);
2063 fprintf(fgpMesh, "%g\t%g\t%g\t%d\n", x2, y2, z2, 1);
2064 fprintf(fgpMesh, "%g\t%g\t%g\t%d\n\n\n", x2, y2, z2, 2);
2065 fprintf(fgpMesh, "%g\t%g\t%g\t%d\n", x0, y0, z0, 1);
2066 fprintf(fgpMesh, "%g\t%g\t%g\t%d\n\n", x3, y3, z3, 2);
2067 fprintf(fgpMesh, "%g\t%g\t%g\t%d\n", x2, y2, z2, 1);
2068 fprintf(fgpMesh, "%g\t%g\t%g\t%d\n\n\n", x2, y2, z2, 2);
2069 */
2070 } // if(OptGnuplot && OptGnuplotElements)
2071 } // for k
2072 } // for i
2073 ElementEnd[prim] = EleCntr;
2074 NbElmntsOnPrim[prim] = ElementEnd[prim] - ElementBgn[prim] + 1;
2075
2076 if (OptPrimitiveFiles) {
2077 fprintf(fPrim, "Element begin: %d, Element end: %d\n", ElementBgn[prim],
2078 ElementEnd[prim]);
2079 fprintf(fPrim, "Number of elements on primitive: %d\n",
2080 NbElmntsOnPrim[prim]);
2081 fclose(fPrim);
2082 }
2083
2084 if (OptElementFiles) fclose(fElem);
2085
2087 if (prim == 1)
2088 fprintf(fgnuElem, " '%s\' w p", gpElem);
2089 else
2090 fprintf(fgnuElem, ", \\\n \'%s\' w p", gpElem);
2091 if (prim == 1) {
2092 fprintf(fgnuMesh, " '%s\' w l", gpMesh);
2093 fprintf(fgnuMesh, ", \\\n \'%s\' w p ps 1", gpElem);
2094 } else {
2095 fprintf(fgnuMesh, ", \\\n \'%s\' w l", gpMesh);
2096 fprintf(fgnuMesh, ", \\\n \'%s\' w p ps 1", gpElem);
2097 }
2098
2099 fclose(fgpElem);
2100 fclose(fgpMesh);
2101 }
2102
2103 return (0);
2104} // end of DiscretizeRectangle
Point3D RotatePoint3D(Point3D *A, DirnCosn3D *DC, int Sense)
Definition: Vector.c:339
Vector3D Vector3DCrossProduct(Vector3D *A, Vector3D *B)
Definition: Vector.c:246
INTFACEGLOBAL int OptPrimitiveFiles
INTFACEGLOBAL FILE * fgnuPrim
INTFACEGLOBAL FILE * fgnuElem
INTFACEGLOBAL FILE * fgnuMesh
INTFACEGLOBAL int OptGnuplotPrimitives
INTFACEGLOBAL int OptPrintVertexAndNormal
INTFACEGLOBAL int OptElementFiles
INTFACEGLOBAL int OptGnuplot
INTFACEGLOBAL int OptGnuplotElements
neBEMGLOBAL int * NbElmntsOnPrim
Definition: neBEM.h:94
neBEMGLOBAL int EleCntr
Definition: neBEM.h:112
neBEMGLOBAL char MeshOutDir[256]
Definition: neBEM.h:263
neBEMGLOBAL double * PrimOriginZ
Definition: neBEM.h:73
neBEMGLOBAL double * PrimOriginY
Definition: neBEM.h:73
neBEMGLOBAL DirnCosn3D * PrimDC
Definition: neBEM.h:74
neBEMGLOBAL char ModelOutDir[256]
Definition: neBEM.h:262
neBEMGLOBAL int * ElementEnd
Definition: neBEM.h:94
neBEMGLOBAL double * PrimLX
Definition: neBEM.h:72
neBEMGLOBAL double * Solution
Definition: neBEM.h:237
neBEMGLOBAL int * ElementBgn
Definition: neBEM.h:94
neBEMGLOBAL double * PrimOriginX
Definition: neBEM.h:73
neBEMGLOBAL double * PrimLZ
Definition: neBEM.h:72

Referenced by SurfaceElements().

◆ DiscretizeTriangle()

neBEMGLOBAL int DiscretizeTriangle ( int  prim,
int  nvertex,
double  xvert[],
double  yvert[],
double  zvert[],
double  xnorm,
double  ynorm,
double  znorm,
int  volref1,
int  volref2,
int  inttype,
double  potential,
double  charge,
double  lambda,
int  NbSegX,
int  NbSegZ 
)

Definition at line 788 of file ReTriM.c.

791 {
792 int SurfParentObj, SurfEType;
793 double SurfX, SurfY, SurfZ, SurfLX, SurfLZ;
794 double SurfElX, SurfElY, SurfElZ, SurfElLX, SurfElLZ;
795 DirnCosn3D PrimDirnCosn; // direction cosine of the current primitive
796 char primstr[10];
797 char gpElem[256], gpMesh[256];
798 FILE *fPrim, *fElem, *fgpPrim, *fgpElem, *fgpMesh;
799
800 // Check inputs
801 if ((NbSegX <= 0) || (NbSegZ <= 0)) {
802 printf("segmentation input wrong in DiscretizeTriangle ...\n");
803 return -1;
804 }
805
807 printf("nvertex: %d\n", nvertex);
808 for (int vert = 0; vert < nvertex; ++vert) {
809 printf("vert: %d, x: %lg, y: %lg, z: %lg\n", vert, xvert[vert],
810 yvert[vert], zvert[vert]);
811 }
812 printf("Normal: %lg, %lg, %lg\n", xnorm, ynorm, znorm);
813 } // if OptPrintVertexAndNormal
814
815 // necessary for separating filenames
816 sprintf(primstr, "%d", prim);
817
818 // in order to avoid warning messages
819 fPrim = NULL;
820 fElem = NULL;
821 fgpMesh = NULL;
822 fgpElem = NULL;
823
824 // Compute all the properties of this surface
825 // Boundary types from 1 to 7 have been defined
826 SurfParentObj = 1;
827 SurfEType = inttype;
828 if ((SurfEType <= 0) || (SurfEType >= 8)) {
829 printf("Wrong SurfEType for prim %d\n", prim);
830 exit(-1);
831 }
832 // Origin of the local coordinate center is at the right angle corner
833 SurfX = xvert[1];
834 SurfY = yvert[1];
835 SurfZ = zvert[1];
836
837 // Find the proper direction cosines first - little more tricky that in the
838 // rectangular case
839 int flagDC = 0; // DC has not been ascertained as yet
840 // We begin with trial 1: one of the possible orientations
841 // Intially, the lengths are necessary
842 // lengths of the sides - note that right angle corner is [1]-th element
843 SurfLX = sqrt((xvert[0] - xvert[1]) * (xvert[0] - xvert[1]) +
844 (yvert[0] - yvert[1]) * (yvert[0] - yvert[1]) +
845 (zvert[0] - zvert[1]) * (zvert[0] - zvert[1]));
846 SurfLZ = sqrt((xvert[2] - xvert[1]) * (xvert[2] - xvert[1]) +
847 (yvert[2] - yvert[1]) * (yvert[2] - yvert[1]) +
848 (zvert[2] - zvert[1]) * (zvert[2] - zvert[1]));
849 // Direction cosines - note that right angle corner is [1]-th element
850 PrimDirnCosn.XUnit.X = (xvert[0] - xvert[1]) / SurfLX;
851 PrimDirnCosn.XUnit.Y = (yvert[0] - yvert[1]) / SurfLX;
852 PrimDirnCosn.XUnit.Z = (zvert[0] - zvert[1]) / SurfLX;
853 PrimDirnCosn.ZUnit.X = (xvert[2] - xvert[1]) / SurfLZ;
854 PrimDirnCosn.ZUnit.Y = (yvert[2] - yvert[1]) / SurfLZ;
855 PrimDirnCosn.ZUnit.Z = (zvert[2] - zvert[1]) / SurfLZ;
856 PrimDirnCosn.YUnit =
857 Vector3DCrossProduct(&PrimDirnCosn.ZUnit, &PrimDirnCosn.XUnit);
858 if ((fabs(PrimDirnCosn.YUnit.X - xnorm) <= 1.0e-3) &&
859 (fabs(PrimDirnCosn.YUnit.Y - ynorm) <= 1.0e-3) &&
860 (fabs(PrimDirnCosn.YUnit.Z - znorm) <= 1.0e-3))
861 flagDC = 1;
862 if (DebugLevel == 202) {
863 printf("First attempt: \n");
864 PrintDirnCosn3D(PrimDirnCosn);
865 printf("\n");
866 }
867
868 if (!flagDC) // if DC search is unsuccessful, try the other orientation
869 {
870 SurfLX = sqrt((xvert[2] - xvert[1]) * (xvert[2] - xvert[1]) +
871 (yvert[2] - yvert[1]) * (yvert[2] - yvert[1]) +
872 (zvert[2] - zvert[1]) * (zvert[2] - zvert[1]));
873 SurfLZ = sqrt((xvert[0] - xvert[1]) * (xvert[0] - xvert[1]) +
874 (yvert[0] - yvert[1]) * (yvert[0] - yvert[1]) +
875 (zvert[0] - zvert[1]) * (zvert[0] - zvert[1]));
876 // Direction cosines - note that right angle corner is [1]-th element
877 PrimDirnCosn.XUnit.X = (xvert[2] - xvert[1]) / SurfLX;
878 PrimDirnCosn.XUnit.Y = (yvert[2] - yvert[1]) / SurfLX;
879 PrimDirnCosn.XUnit.Z = (zvert[2] - zvert[1]) / SurfLX;
880 PrimDirnCosn.ZUnit.X = (xvert[0] - xvert[1]) / SurfLZ;
881 PrimDirnCosn.ZUnit.Y = (yvert[0] - yvert[1]) / SurfLZ;
882 PrimDirnCosn.ZUnit.Z = (zvert[0] - zvert[1]) / SurfLZ;
883 PrimDirnCosn.YUnit =
884 Vector3DCrossProduct(&PrimDirnCosn.ZUnit, &PrimDirnCosn.XUnit);
885 if ((fabs(PrimDirnCosn.YUnit.X - xnorm) <= 1.0e-3) &&
886 (fabs(PrimDirnCosn.YUnit.Y - ynorm) <= 1.0e-3) &&
887 (fabs(PrimDirnCosn.YUnit.Z - znorm) <= 1.0e-3))
888 flagDC = 2;
889 if (DebugLevel == 202) {
890 printf("Second attempt: \n");
891 PrintDirnCosn3D(PrimDirnCosn);
892 printf("\n");
893 }
894 }
895
896 if (!flagDC) // No other possibility, DC search failed!!!
897 {
898 printf("Triangle DC problem ... returning ...\n");
899 // getchar();
900 return -1;
901 }
902
903 // primitive direction cosine assignments
904 PrimDC[prim].XUnit.X = PrimDirnCosn.XUnit.X;
905 PrimDC[prim].XUnit.Y = PrimDirnCosn.XUnit.Y;
906 PrimDC[prim].XUnit.Z = PrimDirnCosn.XUnit.Z;
907 PrimDC[prim].YUnit.X = PrimDirnCosn.YUnit.X;
908 PrimDC[prim].YUnit.Y = PrimDirnCosn.YUnit.Y;
909 PrimDC[prim].YUnit.Z = PrimDirnCosn.YUnit.Z;
910 PrimDC[prim].ZUnit.X = PrimDirnCosn.ZUnit.X;
911 PrimDC[prim].ZUnit.Y = PrimDirnCosn.ZUnit.Y;
912 PrimDC[prim].ZUnit.Z = PrimDirnCosn.ZUnit.Z;
913
914 // primitive origin - for a triangle, origin is at the right corner
915 PrimOriginX[prim] = SurfX;
916 PrimOriginY[prim] = SurfY;
917 PrimOriginZ[prim] = SurfZ;
918 PrimLX[prim] = SurfLX;
919 PrimLZ[prim] = SurfLZ;
920 if (flagDC == 1) {
921 int tmpVolRef1 = VolRef1[prim];
922 VolRef1[prim] = VolRef2[prim];
923 VolRef2[prim] = tmpVolRef1;
924 int tmpEpsilon1 = Epsilon1[prim];
925 Epsilon1[prim] = Epsilon2[prim];
926 Epsilon2[prim] = tmpEpsilon1;
927 }
928
929 double SurfLambda = lambda;
930 double SurfV = potential;
931
932 // file output for a primitive
933 if (OptPrimitiveFiles) {
934 char OutPrim[256];
935 strcpy(OutPrim, ModelOutDir);
936 strcat(OutPrim, "/Primitives/Primitive");
937 strcat(OutPrim, primstr);
938 strcat(OutPrim, ".out");
939 fPrim = fopen(OutPrim, "w");
940 if (fPrim == NULL) {
941 neBEMMessage("DiscretizeTriangle - OutPrim");
942 return -1;
943 }
944 fprintf(fPrim, "#prim: %d, nvertex: %d\n", prim, nvertex);
945 fprintf(fPrim, "Node1: %lg\t%lg\t%lg\n", xvert[0], yvert[0], zvert[0]);
946 fprintf(fPrim, "Node2: %lg\t%lg\t%lg\n", xvert[1], yvert[1], zvert[1]);
947 fprintf(fPrim, "Node3: %lg\t%lg\t%lg\n", xvert[2], yvert[2], zvert[2]);
948 fprintf(fPrim, "PrimOrigin: %lg\t%lg\t%lg\n", PrimOriginX[prim],
949 PrimOriginY[prim], PrimOriginZ[prim]);
950 fprintf(fPrim, "Primitive lengths: %lg\t%lg\n", PrimLX[prim], PrimLZ[prim]);
951 fprintf(fPrim, "Norm: %lg\t%lg\t%lg\n", xnorm, ynorm, znorm);
952 fprintf(fPrim, "#volref1: %d, volref2: %d\n", volref1, volref2);
953 fprintf(fPrim, "#NbSegX: %d, NbSegZ: %d (check note!)\n", NbSegX, NbSegZ);
954 fprintf(fPrim, "#ParentObj: %d\tEType: %d\n", SurfParentObj, SurfEType);
955 fprintf(fPrim, "#SurfX\tSurfY\tSurfZ\tSurfLX\tSurfLZ (Rt. Corner)\n");
956 fprintf(fPrim, "%lg\t%lg\t%lg\t%lg\t%lg\n", SurfX, SurfY, SurfZ, SurfLX,
957 SurfLZ);
958 fprintf(fPrim, "#DirnCosn: \n");
959 fprintf(fPrim, "%lg, %lg, %lg\n", PrimDirnCosn.XUnit.X,
960 PrimDirnCosn.XUnit.Y, PrimDirnCosn.XUnit.Z);
961 fprintf(fPrim, "%lg, %lg, %lg\n", PrimDirnCosn.YUnit.X,
962 PrimDirnCosn.YUnit.Y, PrimDirnCosn.YUnit.Z);
963 fprintf(fPrim, "%lg, %lg, %lg\n", PrimDirnCosn.ZUnit.X,
964 PrimDirnCosn.ZUnit.Y, PrimDirnCosn.ZUnit.Z);
965 fprintf(fPrim, "#SurfLambda: %lg\tSurfV: %lg\n", SurfLambda, SurfV);
966 }
967
968 // necessary for gnuplot
970 char gpPrim[256];
971 strcpy(gpPrim, MeshOutDir);
972 strcat(gpPrim, "/GViewDir/gpPrim");
973 strcat(gpPrim, primstr);
974 strcat(gpPrim, ".out");
975 fgpPrim = fopen(gpPrim, "w");
976 if (fgpPrim == NULL) {
977 neBEMMessage("DiscretizeTriangle - OutgpPrim");
978 return -1;
979 }
980 fprintf(fgpPrim, "%g\t%g\t%g\n\n", xvert[0], yvert[0], zvert[0]);
981 fprintf(fgpPrim, "%g\t%g\t%g\n\n", xvert[1], yvert[1], zvert[1]);
982 fprintf(fgpPrim, "%g\t%g\t%g\n\n", xvert[2], yvert[2], zvert[2]);
983 fprintf(fgpPrim, "%g\t%g\t%g\n", xvert[0], yvert[0], zvert[0]);
984 fclose(fgpPrim);
985
986 if (prim == 1)
987 fprintf(fgnuPrim, " '%s\' w l", gpPrim);
988 else
989 fprintf(fgnuPrim, ", \\\n \'%s\' w l", gpPrim);
990 }
991
992 // file outputs for elements on primitive
993 if (OptElementFiles) {
994 char OutElem[256];
995 strcpy(OutElem, MeshOutDir);
996 strcat(OutElem, "/Elements/ElemOnPrim");
997 strcat(OutElem, primstr);
998 strcat(OutElem, ".out");
999 fElem = fopen(OutElem, "w");
1000 if (fElem == NULL) {
1001 neBEMMessage("DiscretizeTriangle - OutElem");
1002 return -1;
1003 }
1004 }
1005 // gnuplot friendly file outputs for elements on primitive
1007 strcpy(gpElem, MeshOutDir);
1008 strcat(gpElem, "/GViewDir/gpElemOnPrim");
1009 strcat(gpElem, primstr);
1010 strcat(gpElem, ".out");
1011 fgpElem = fopen(gpElem, "w");
1012 // assert(fgpElem != NULL);
1013 if (fgpElem == NULL) {
1014 neBEMMessage("DiscretizeTriangle - OutgpElem");
1015 if (fElem) fclose(fElem);
1016 return -1;
1017 }
1018 // gnuplot friendly file outputs for elements on primitive
1019 strcpy(gpMesh, MeshOutDir);
1020 strcat(gpMesh, "/GViewDir/gpMeshOnPrim");
1021 strcat(gpMesh, primstr);
1022 strcat(gpMesh, ".out");
1023 fgpMesh = fopen(gpMesh, "w");
1024 if (fgpMesh == NULL) {
1025 neBEMMessage("DiscretizeTriangle - OutgpMesh");
1026 fclose(fgpElem);
1027 if (fElem) fclose(fElem);
1028 return -1;
1029 }
1030 }
1031
1032 // Compute element positions (CGs) in primitive local coordinate system (PCS).
1033 // Then map these CGs to the global coordinate system.
1034 // (xav, 0, zav) is the CG of an element wrt the primitive coordinate system
1035 // From this, we find the offset of the element from the primitive CG in the
1036 // global coordinate system by just rotating the displacement vector
1037 // (0,0,0) -> (xav,0,zav) using the known DCM of the surface.
1038 // This rotated vector (now in the global system) is then added to the
1039 // position vector of the primitive CG (always in the global system) to get
1040 // the CG of the element in the global system.
1041
1042 // Consult note for clarifications on the discretization algorithm.
1043 // SurfElLX is true for the lowest row of elements, but indicative of the
1044 // other rows
1045 // Make sure that the larger number is being used to discretize the longer
1046 // side - can be OverSmart in certain cases - there may be cases where
1047 // smaller number of elements suffice for a longer side
1048 if (NbSegX == NbSegZ) {
1049 SurfElLX = SurfLX / NbSegX; // element sizes
1050 SurfElLZ = SurfLZ / NbSegZ;
1051 } else if (NbSegX > NbSegZ) {
1052 if (SurfLX > SurfLZ) {
1053 SurfElLX = SurfLX / NbSegX; // element sizes
1054 SurfElLZ = SurfLZ / NbSegZ;
1055 } else // interchange NbSegX and NbSegZ
1056 {
1057 int tmp = NbSegZ;
1058 NbSegZ = NbSegX;
1059 NbSegX = tmp;
1060 SurfElLX = SurfLX / NbSegX; // element sizes
1061 SurfElLZ = SurfLZ / NbSegZ;
1062 }
1063 } // NbSegX > NbSegZ
1064 else // NbSegX < NbSegZ
1065 {
1066 if (SurfLX < SurfLZ) {
1067 SurfElLX = SurfLX / NbSegX; // element sizes
1068 SurfElLZ = SurfLZ / NbSegZ;
1069 } else // interchange NbSegX and NbSegZ
1070 {
1071 int tmp = NbSegZ;
1072 NbSegZ = NbSegX;
1073 NbSegX = tmp;
1074 SurfElLX = SurfLX / NbSegX; // element sizes
1075 SurfElLZ = SurfLZ / NbSegZ;
1076 }
1077 }
1078
1079 // Analysis of element aspect ratio.
1080 // Note that we can afford only to reduce the total number of elements.
1081 // Otherwise, we'll have to realloc `EleArr' array.
1082 // Later, we'll make the corrections such that the total number of elements
1083 // remain close to the originally intended value.
1084 double AR = SurfElLX / SurfElLZ; // indicative element aspect ratio
1085 if (OptPrimitiveFiles) {
1086 fprintf(fPrim,
1087 "Using the input, the aspect ratio of the elements on prim: %d\n",
1088 prim);
1089 fprintf(fPrim,
1090 "NbSegX: %d, SurfElLX: %lg, NbSegZ: %d, SurfElLZ: %lg, AR: %lg\n",
1091 NbSegX, SurfElLX, NbSegZ, SurfElLZ, AR);
1092 }
1093 if (AR > 10.0) // NbSegZ needs to be reduced
1094 {
1095 double tmpElLZ = SurfElLX / 10.0;
1096 NbSegZ = (int)(SurfLZ / tmpElLZ);
1097 if (NbSegZ <= 0) NbSegZ = 1;
1098 SurfElLZ = SurfLZ / NbSegZ;
1099 }
1100 if (AR < 0.1) // NbSegX need to be reduced
1101 {
1102 double tmpElLX = SurfElLZ * 0.1;
1103 NbSegX = (int)(SurfLX / tmpElLX);
1104 if (NbSegX <= 0) NbSegX = 1;
1105 SurfElLX = SurfLX / NbSegX;
1106 }
1107 AR = SurfElLX / SurfElLZ; // indicative element aspect ratio
1108 if (OptPrimitiveFiles) {
1109 fprintf(fPrim, "After analyzing the likely aspect ratio of the elements\n");
1110 fprintf(fPrim,
1111 "NbSegX: %d, SurfElLX: %lg, NbSegZ: %d, SurfElLZ: %lg, AR: %lg\n",
1112 NbSegX, SurfElLX, NbSegZ, SurfElLZ, AR);
1113 }
1114
1115 // The top-most right angle triangle is a lone element on the highest row, its
1116 // properties being determined irrespective of the others. Despite that, this
1117 // element is being treated as one among the others, especially to facilitate
1118 // element indexing, file output etc.
1119 // Each row, thus, has at least one triangle, and possibly several rectangular
1120 // elements. All the elements in any given row has the same SurfElLZ as has
1121 // been determined above.
1122 // First we create the triangular element and then move on to create the
1123 // rectangular ones.
1124 double xv0, yv0, zv0, xv1, yv1, zv1, xv2, yv2, zv2;
1125 ElementBgn[prim] = EleCntr + 1;
1126 for (int k = 1; k <= NbSegZ; ++k) // consider the k-th row
1127 {
1128 double grad = (SurfLZ / SurfLX);
1129 double zlopt = (k - 1) * SurfElLZ;
1130 double zhipt = (k)*SurfElLZ;
1131 double xlopt = (SurfLZ - zlopt) / grad; // used again on 21 Feb 2014
1132 double xhipt = (SurfLZ - zhipt) / grad;
1133
1134 // the triangular element on the k-th row can now be specified in PCS
1135 double xtorigin = xhipt;
1136 double ytorigin = 0.0;
1137 double ztorigin = zlopt;
1138 { // Separate block for position rotation - local2global
1139 Point3D localDisp, globalDisp;
1140
1141 localDisp.X = xtorigin;
1142 localDisp.Y = ytorigin;
1143 localDisp.Z = ztorigin;
1144 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1145 SurfElX =
1146 SurfX + globalDisp.X; // these are the coords in GCS of origin of
1147 SurfElY =
1148 SurfY + globalDisp.Y; // the triangluar element under consideration
1149 SurfElZ = SurfZ + globalDisp.Z;
1150 } // vector rotation over
1151
1152 // Assign element values and write in the file
1153 ++EleCntr;
1154 if (EleCntr > NbElements) {
1155 neBEMMessage("DiscretizeTriangle - EleCntr more than NbElements 1!");
1156 if (fgpElem) fclose(fgpElem);
1157 if (fgpMesh) fclose(fgpMesh);
1158 return -1;
1159 }
1160
1161 (EleArr + EleCntr - 1)->DeviceNb =
1162 1; // At present, there is only one device
1163 (EleArr + EleCntr - 1)->ComponentNb = SurfParentObj;
1164 (EleArr + EleCntr - 1)->PrimitiveNb = prim;
1165 (EleArr + EleCntr - 1)->Id = EleCntr;
1166 (EleArr + EleCntr - 1)->G.Type = 3; // triangular here
1167 (EleArr + EleCntr - 1)->G.Origin.X = SurfElX;
1168 (EleArr + EleCntr - 1)->G.Origin.Y = SurfElY;
1169 (EleArr + EleCntr - 1)->G.Origin.Z = SurfElZ;
1170 // (EleArr+EleCntr-1)->G.LX = SurfElLX; // previously written as xlopt -
1171 // xhipt;
1172 (EleArr + EleCntr - 1)->G.LX =
1173 xlopt - xhipt; // back to old ways on 21 Feb 2014
1174 (EleArr + EleCntr - 1)->G.LZ = SurfElLZ;
1175 (EleArr + EleCntr - 1)->G.LZ =
1176 zhipt - zlopt; // to be on the safe side, 21/2/14
1177 (EleArr + EleCntr - 1)->G.dA =
1178 0.5 * (EleArr + EleCntr - 1)->G.LX * (EleArr + EleCntr - 1)->G.LZ;
1179 // Safe to use the direction cosines obtained for the triangular primitive
1180 // since they are bound to remain unchanged for the rectangular sub-elements
1181 (EleArr + EleCntr - 1)->G.DC.XUnit.X = PrimDirnCosn.XUnit.X;
1182 (EleArr + EleCntr - 1)->G.DC.XUnit.Y = PrimDirnCosn.XUnit.Y;
1183 (EleArr + EleCntr - 1)->G.DC.XUnit.Z = PrimDirnCosn.XUnit.Z;
1184 (EleArr + EleCntr - 1)->G.DC.YUnit.X = PrimDirnCosn.YUnit.X;
1185 (EleArr + EleCntr - 1)->G.DC.YUnit.Y = PrimDirnCosn.YUnit.Y;
1186 (EleArr + EleCntr - 1)->G.DC.YUnit.Z = PrimDirnCosn.YUnit.Z;
1187 (EleArr + EleCntr - 1)->G.DC.ZUnit.X = PrimDirnCosn.ZUnit.X;
1188 (EleArr + EleCntr - 1)->G.DC.ZUnit.Y = PrimDirnCosn.ZUnit.Y;
1189 (EleArr + EleCntr - 1)->G.DC.ZUnit.Z = PrimDirnCosn.ZUnit.Z;
1190 (EleArr + EleCntr - 1)->E.Type = SurfEType;
1191 (EleArr + EleCntr - 1)->E.Lambda = SurfLambda;
1192 (EleArr + EleCntr - 1)->Solution = 0.0;
1193 (EleArr + EleCntr - 1)->Assigned = charge;
1194 // Boundary condition is applied at the barycenter, not at the origin
1195 // of the element coordinate system (ECS) which is at the right corner
1196 (EleArr + EleCntr - 1)->BC.NbOfBCs = 1; // assume one BC per element
1197
1198 xv0 = (EleArr + EleCntr - 1)->G.Origin.X;
1199 yv0 = (EleArr + EleCntr - 1)->G.Origin.Y;
1200 zv0 = (EleArr + EleCntr - 1)->G.Origin.Z;
1201 xv1 = (EleArr + EleCntr - 1)->G.Origin.X +
1202 (EleArr + EleCntr - 1)->G.LX * (EleArr + EleCntr - 1)->G.DC.XUnit.X;
1203 yv1 = (EleArr + EleCntr - 1)->G.Origin.Y +
1204 (EleArr + EleCntr - 1)->G.LX * (EleArr + EleCntr - 1)->G.DC.XUnit.Y;
1205 zv1 = (EleArr + EleCntr - 1)->G.Origin.Z +
1206 (EleArr + EleCntr - 1)->G.LX * (EleArr + EleCntr - 1)->G.DC.XUnit.Z;
1207 xv2 = (EleArr + EleCntr - 1)->G.Origin.X +
1208 (EleArr + EleCntr - 1)->G.LZ * (EleArr + EleCntr - 1)->G.DC.ZUnit.X;
1209 yv2 = (EleArr + EleCntr - 1)->G.Origin.Y +
1210 (EleArr + EleCntr - 1)->G.LZ * (EleArr + EleCntr - 1)->G.DC.ZUnit.Y;
1211 zv2 = (EleArr + EleCntr - 1)->G.Origin.Z +
1212 (EleArr + EleCntr - 1)->G.LZ * (EleArr + EleCntr - 1)->G.DC.ZUnit.Z;
1213 // assign vertices of the element
1214 (EleArr + EleCntr - 1)->G.Vertex[0].X = xv0;
1215 (EleArr + EleCntr - 1)->G.Vertex[0].Y = yv0;
1216 (EleArr + EleCntr - 1)->G.Vertex[0].Z = zv0;
1217 (EleArr + EleCntr - 1)->G.Vertex[1].X = xv1;
1218 (EleArr + EleCntr - 1)->G.Vertex[1].Y = yv1;
1219 (EleArr + EleCntr - 1)->G.Vertex[1].Z = zv1;
1220 (EleArr + EleCntr - 1)->G.Vertex[2].X = xv2;
1221 (EleArr + EleCntr - 1)->G.Vertex[2].Y = yv2;
1222 (EleArr + EleCntr - 1)->G.Vertex[2].Z = zv2;
1223 (EleArr + EleCntr - 1)->G.Vertex[3].X = 0.0;
1224 (EleArr + EleCntr - 1)->G.Vertex[3].Y = 0.0;
1225 (EleArr + EleCntr - 1)->G.Vertex[3].Z = 0.0;
1226
1227 if (DebugLevel == 201) {
1228 printf("Primitive nb: %d\n", (EleArr + EleCntr - 1)->PrimitiveNb);
1229 printf("Element id: %d\n", (EleArr + EleCntr - 1)->Id);
1230 printf("Element X, Y, Z: %lg %lg %lg\n",
1231 (EleArr + EleCntr - 1)->G.Origin.X,
1232 (EleArr + EleCntr - 1)->G.Origin.Y,
1233 (EleArr + EleCntr - 1)->G.Origin.Z);
1234 printf("Element LX, LZ: %lg %lg\n", (EleArr + EleCntr - 1)->G.LX,
1235 (EleArr + EleCntr - 1)->G.LZ);
1236 printf("Element (primitive) X axis dirn cosines: %lg, %lg, %lg\n",
1237 PrimDirnCosn.XUnit.X, PrimDirnCosn.XUnit.Y, PrimDirnCosn.XUnit.Z);
1238 printf("Element (primitive) Y axis dirn cosines: %lg, %lg, %lg\n",
1239 PrimDirnCosn.YUnit.X, PrimDirnCosn.YUnit.Y, PrimDirnCosn.YUnit.Z);
1240 printf("Element (primitive) Z axis dirn cosines: %lg, %lg, %lg\n",
1241 PrimDirnCosn.ZUnit.X, PrimDirnCosn.ZUnit.Y, PrimDirnCosn.ZUnit.Z);
1242 }
1243 // Following are the location in the ECS
1244 double dxl = (EleArr + EleCntr - 1)->G.LX / 3.0;
1245 double dyl = 0.0;
1246 double dzl = (EleArr + EleCntr - 1)->G.LZ / 3.0;
1247 { // Separate block for position rotation - local2global
1248 Point3D localDisp, globalDisp;
1249
1250 localDisp.X = dxl;
1251 localDisp.Y = dyl;
1252 localDisp.Z = dzl;
1253 if (DebugLevel == 201) {
1254 printf("Element dxl, dxy, dxz: %lg %lg %lg\n", localDisp.X, localDisp.Y,
1255 localDisp.Z);
1256 }
1257
1258 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1259 (EleArr + EleCntr - 1)->BC.CollPt.X =
1260 (EleArr + EleCntr - 1)->G.Origin.X + globalDisp.X;
1261 (EleArr + EleCntr - 1)->BC.CollPt.Y =
1262 (EleArr + EleCntr - 1)->G.Origin.Y + globalDisp.Y;
1263 (EleArr + EleCntr - 1)->BC.CollPt.Z =
1264 (EleArr + EleCntr - 1)->G.Origin.Z + globalDisp.Z;
1265 if (DebugLevel == 201) {
1266 printf("Element global dxl, dxy, dxz: %lg %lg %lg\n", globalDisp.X,
1267 globalDisp.Y, globalDisp.Z);
1268 printf("Element BCX, BCY, BCZ: %lg %lg %lg\n",
1269 (EleArr + EleCntr - 1)->BC.CollPt.X,
1270 (EleArr + EleCntr - 1)->BC.CollPt.Y,
1271 (EleArr + EleCntr - 1)->BC.CollPt.Z);
1272 }
1273 } // vector rotation over
1274 // (EleArr+EleCntr-1)->BC.Value = SurfV; // assigned in BoundaryConditions
1275
1276 if (OptElementFiles) {
1277 fprintf(fElem, "##Element Counter: %d\n", EleCntr);
1278 fprintf(fElem, "#DevNb\tCompNb\tPrimNb\tId\n");
1279 fprintf(fElem, "%d\t%d\t%d\t%d\n", (EleArr + EleCntr - 1)->DeviceNb,
1280 (EleArr + EleCntr - 1)->ComponentNb,
1281 (EleArr + EleCntr - 1)->PrimitiveNb, (EleArr + EleCntr - 1)->Id);
1282 fprintf(fElem, "#GType\tX\tY\tZ\tLX\tLZ\tdA\n");
1283 fprintf(fElem, "%d\t%.16lg\t%.16lg\t%.16lg\t%.16lg\t%.16lg\t%.16lg\n",
1284 (EleArr + EleCntr - 1)->G.Type,
1285 (EleArr + EleCntr - 1)->G.Origin.X,
1286 (EleArr + EleCntr - 1)->G.Origin.Y,
1287 (EleArr + EleCntr - 1)->G.Origin.Z, (EleArr + EleCntr - 1)->G.LX,
1288 (EleArr + EleCntr - 1)->G.LZ, (EleArr + EleCntr - 1)->G.dA);
1289 fprintf(fElem, "#DirnCosn: \n");
1290 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.XUnit.X,
1291 (EleArr + EleCntr - 1)->G.DC.XUnit.Y,
1292 (EleArr + EleCntr - 1)->G.DC.XUnit.Z);
1293 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.YUnit.X,
1294 (EleArr + EleCntr - 1)->G.DC.YUnit.Y,
1295 (EleArr + EleCntr - 1)->G.DC.YUnit.Z);
1296 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.ZUnit.X,
1297 (EleArr + EleCntr - 1)->G.DC.ZUnit.Y,
1298 (EleArr + EleCntr - 1)->G.DC.ZUnit.Z);
1299 fprintf(fElem, "#EType\tLambda\n");
1300 fprintf(fElem, "%d\t%lg\n", (EleArr + EleCntr - 1)->E.Type,
1301 (EleArr + EleCntr - 1)->E.Lambda);
1302 fprintf(fElem, "#NbBCs\tCPX\tCPY\tCPZ\tValue\n");
1303 fprintf(fElem, "%d\t%.16lg\t%.16lg\t%.16lg\t%lg\n",
1304 (EleArr + EleCntr - 1)->BC.NbOfBCs,
1305 (EleArr + EleCntr - 1)->BC.CollPt.X,
1306 (EleArr + EleCntr - 1)->BC.CollPt.Y,
1307 (EleArr + EleCntr - 1)->BC.CollPt.Z,
1308 (EleArr + EleCntr - 1)->BC.Value);
1309 } // if OptElementFiles
1310
1311 // mark bary-center and draw mesh
1313 fprintf(fgpElem, "%g\t%g\t%g\n", (EleArr + EleCntr - 1)->BC.CollPt.X,
1314 (EleArr + EleCntr - 1)->BC.CollPt.Y,
1315 (EleArr + EleCntr - 1)->BC.CollPt.Z);
1316
1317 // draw mesh
1318 // assign vertices of the element
1319 xv0 = (EleArr + EleCntr - 1)->G.Vertex[0].X;
1320 yv0 = (EleArr + EleCntr - 1)->G.Vertex[0].Y;
1321 zv0 = (EleArr + EleCntr - 1)->G.Vertex[0].Z;
1322 xv1 = (EleArr + EleCntr - 1)->G.Vertex[1].X;
1323 yv1 = (EleArr + EleCntr - 1)->G.Vertex[1].Y;
1324 zv1 = (EleArr + EleCntr - 1)->G.Vertex[1].Z;
1325 xv2 = (EleArr + EleCntr - 1)->G.Vertex[2].X;
1326 yv2 = (EleArr + EleCntr - 1)->G.Vertex[2].Y;
1327 zv2 = (EleArr + EleCntr - 1)->G.Vertex[2].Z;
1328
1329 fprintf(fgpMesh, "%g\t%g\t%g\n", xv0, yv0, zv0);
1330 fprintf(fgpMesh, "%g\t%g\t%g\n", xv1, yv1, zv1);
1331 fprintf(fgpMesh, "%g\t%g\t%g\n", xv2, yv2, zv2);
1332 fprintf(fgpMesh, "%g\t%g\t%g\n\n", xv0, yv0, zv0);
1333 } // if OptGnuplotElements
1334
1335 if (k == NbSegZ) // no rectangular element on this row
1336 continue;
1337
1338 // determine NbSegXOnThisRow and ElLXOnThisRow for the rectagnular elements
1339 // and then loop.
1340 double RowLX = xhipt; // the triangular portion is left outside the slice
1341 int NbSegXOnThisRow;
1342 double ElLXOnThisRow;
1343 if (RowLX <= SurfElLX) {
1344 NbSegXOnThisRow = 1;
1345 ElLXOnThisRow = RowLX;
1346 } else {
1347 NbSegXOnThisRow = (int)(RowLX / SurfElLX);
1348 ElLXOnThisRow = RowLX / NbSegXOnThisRow;
1349 }
1350 double x0, y0, z0, x1, y1, z1, x2, y2, z2, x3, y3, z3;
1351 for (int i = 1; i <= NbSegXOnThisRow; ++i) {
1352 double xorigin = (i - 1) * ElLXOnThisRow + 0.5 * ElLXOnThisRow; // PCS
1353 double yorigin = 0.0; // centroid of the rectagnular element
1354 double zorigin = 0.5 * (zlopt + zhipt);
1355 // printf("k: %d, i: %d, xo: %lg, yo: %lg, zo: %lg\n", k, i,
1356 // xorigin, yorigin, zorigin);
1357 // printf("xlopt: %lg, zlopt: %lg, xhipt: %lg, zhipt: %lg\n",
1358 // xlopt, zlopt, xhipt, zhipt);
1359
1360 { // Separate block for vector rotation
1361 Point3D localDisp, globalDisp;
1362
1363 localDisp.X = xorigin;
1364 localDisp.Y = yorigin;
1365 localDisp.Z = zorigin;
1366 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1367 SurfElX = SurfX + globalDisp.X; // GCS
1368 SurfElY = SurfY + globalDisp.Y;
1369 SurfElZ = SurfZ + globalDisp.Z;
1370 } // vector rotation over
1371 // printf("SurfX: %lg, SurfY: %lg, SurfZ: %lg\n",
1372 // SurfX, SurfY, SurfZ);
1373 // printf("SurfElX: %lg, SurfElY: %lg, SurfElZ: %lg\n",
1374 // SurfElX, SurfElY, SurfElZ);
1375
1376 // Assign element values and write in the file
1377 ++EleCntr;
1378 if (EleCntr > NbElements) {
1379 neBEMMessage("DiscretizeTriangle - EleCntr more than NbElements 2!");
1380 return -1;
1381 }
1382
1383 (EleArr + EleCntr - 1)->DeviceNb =
1384 1; // At present, there is only one device
1385 (EleArr + EleCntr - 1)->ComponentNb = SurfParentObj;
1386 (EleArr + EleCntr - 1)->PrimitiveNb = prim;
1387 (EleArr + EleCntr - 1)->Id = EleCntr;
1388 (EleArr + EleCntr - 1)->G.Type = 4; // rectagnular here
1389 (EleArr + EleCntr - 1)->G.Origin.X = SurfElX;
1390 (EleArr + EleCntr - 1)->G.Origin.Y = SurfElY;
1391 (EleArr + EleCntr - 1)->G.Origin.Z = SurfElZ;
1392 (EleArr + EleCntr - 1)->G.LX = ElLXOnThisRow;
1393 (EleArr + EleCntr - 1)->G.LZ = SurfElLZ;
1394 (EleArr + EleCntr - 1)->G.LZ =
1395 zhipt - zlopt; // to be on the safe side! 21/2/14
1396 (EleArr + EleCntr - 1)->G.dA =
1397 (EleArr + EleCntr - 1)->G.LX * (EleArr + EleCntr - 1)->G.LZ;
1398 // Safe to use the direction cosines obtained for the triangular primitive
1399 // since they are bound to remain unchanged for the triangular
1400 // sub-elements
1401 (EleArr + EleCntr - 1)->G.DC.XUnit.X = PrimDirnCosn.XUnit.X;
1402 (EleArr + EleCntr - 1)->G.DC.XUnit.Y = PrimDirnCosn.XUnit.Y;
1403 (EleArr + EleCntr - 1)->G.DC.XUnit.Z = PrimDirnCosn.XUnit.Z;
1404 (EleArr + EleCntr - 1)->G.DC.YUnit.X = PrimDirnCosn.YUnit.X;
1405 (EleArr + EleCntr - 1)->G.DC.YUnit.Y = PrimDirnCosn.YUnit.Y;
1406 (EleArr + EleCntr - 1)->G.DC.YUnit.Z = PrimDirnCosn.YUnit.Z;
1407 (EleArr + EleCntr - 1)->G.DC.ZUnit.X = PrimDirnCosn.ZUnit.X;
1408 (EleArr + EleCntr - 1)->G.DC.ZUnit.Y = PrimDirnCosn.ZUnit.Y;
1409 (EleArr + EleCntr - 1)->G.DC.ZUnit.Z = PrimDirnCosn.ZUnit.Z;
1410 (EleArr + EleCntr - 1)->E.Type = SurfEType;
1411 (EleArr + EleCntr - 1)->E.Lambda = SurfLambda;
1412 (EleArr + EleCntr - 1)->Solution = 0.0;
1413 (EleArr + EleCntr - 1)->Assigned = charge;
1414 // Boundary condition is applied at the origin for this rectangular
1415 // element coordinate system (ECS)
1416 (EleArr + EleCntr - 1)->BC.NbOfBCs = 1; // assume one BC per element
1417 // Following are the location in the ECS
1418 (EleArr + EleCntr - 1)->BC.CollPt.X = (EleArr + EleCntr - 1)->G.Origin.X;
1419 (EleArr + EleCntr - 1)->BC.CollPt.Y = (EleArr + EleCntr - 1)->G.Origin.Y;
1420 (EleArr + EleCntr - 1)->BC.CollPt.Z = (EleArr + EleCntr - 1)->G.Origin.Z;
1421 // find element vertices
1422 // 1) displacement vector in the ECS is first identified
1423 // 2) this vector is transformed to the GCS
1424 // 3) the global displacement vector, when added to the centroid in GCS,
1425 // gives the node positions in GCS.
1426 x0 = -0.5 *
1427 (EleArr + EleCntr - 1)->G.LX; // xyz displacement of node wrt ECS
1428 y0 = 0.0;
1429 z0 = -0.5 * (EleArr + EleCntr - 1)->G.LZ;
1430 { // Separate block for position rotation - local2global
1431 Point3D localDisp, globalDisp;
1432
1433 localDisp.X = x0;
1434 localDisp.Y = y0;
1435 localDisp.Z = z0; // displacement in GCS
1436 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1437 x0 = (EleArr + EleCntr - 1)->G.Origin.X +
1438 globalDisp.X; // xyz position in GCS
1439 y0 = (EleArr + EleCntr - 1)->G.Origin.Y + globalDisp.Y;
1440 z0 = (EleArr + EleCntr - 1)->G.Origin.Z + globalDisp.Z;
1441 } // position rotation over
1442
1443 x1 = 0.5 * (EleArr + EleCntr - 1)->G.LX;
1444 y1 = 0.0;
1445 z1 = -0.5 * (EleArr + EleCntr - 1)->G.LZ;
1446 { // Separate block for position rotation - local2global
1447 Point3D localDisp, globalDisp;
1448
1449 localDisp.X = x1;
1450 localDisp.Y = y1;
1451 localDisp.Z = z1;
1452 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1453 x1 = (EleArr + EleCntr - 1)->G.Origin.X + globalDisp.X;
1454 y1 = (EleArr + EleCntr - 1)->G.Origin.Y + globalDisp.Y;
1455 z1 = (EleArr + EleCntr - 1)->G.Origin.Z + globalDisp.Z;
1456 } // position rotation over
1457
1458 x2 = 0.5 * (EleArr + EleCntr - 1)->G.LX;
1459 y2 = 0.0;
1460 z2 = 0.5 * (EleArr + EleCntr - 1)->G.LZ;
1461 { // Separate block for position rotation - local2global
1462 Point3D localDisp, globalDisp;
1463
1464 localDisp.X = x2;
1465 localDisp.Y = y2;
1466 localDisp.Z = z2;
1467 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1468 x2 = (EleArr + EleCntr - 1)->G.Origin.X + globalDisp.X;
1469 y2 = (EleArr + EleCntr - 1)->G.Origin.Y + globalDisp.Y;
1470 z2 = (EleArr + EleCntr - 1)->G.Origin.Z + globalDisp.Z;
1471 } // position rotation over
1472
1473 x3 = -0.5 * (EleArr + EleCntr - 1)->G.LX;
1474 y3 = 0.0;
1475 z3 = 0.5 * (EleArr + EleCntr - 1)->G.LZ;
1476 { // Separate block for position rotation - local2global
1477 Point3D localDisp, globalDisp;
1478
1479 localDisp.X = x3;
1480 localDisp.Y = y3;
1481 localDisp.Z = z3;
1482 globalDisp = RotatePoint3D(&localDisp, &PrimDirnCosn, local2global);
1483 x3 = (EleArr + EleCntr - 1)->G.Origin.X + globalDisp.X;
1484 y3 = (EleArr + EleCntr - 1)->G.Origin.Y + globalDisp.Y;
1485 z3 = (EleArr + EleCntr - 1)->G.Origin.Z + globalDisp.Z;
1486 } // position rotation over
1487
1488 // assign vertices of the element
1489 (EleArr + EleCntr - 1)->G.Vertex[0].X = x0;
1490 (EleArr + EleCntr - 1)->G.Vertex[0].Y = y0;
1491 (EleArr + EleCntr - 1)->G.Vertex[0].Z = z0;
1492 (EleArr + EleCntr - 1)->G.Vertex[1].X = x1;
1493 (EleArr + EleCntr - 1)->G.Vertex[1].Y = y1;
1494 (EleArr + EleCntr - 1)->G.Vertex[1].Z = z1;
1495 (EleArr + EleCntr - 1)->G.Vertex[2].X = x2;
1496 (EleArr + EleCntr - 1)->G.Vertex[2].Y = y2;
1497 (EleArr + EleCntr - 1)->G.Vertex[2].Z = z2;
1498 (EleArr + EleCntr - 1)->G.Vertex[3].X = x3;
1499 (EleArr + EleCntr - 1)->G.Vertex[3].Y = y3;
1500 (EleArr + EleCntr - 1)->G.Vertex[3].Z = z3;
1501
1502 if (OptElementFiles) {
1503 fprintf(fElem, "##Element Counter: %d\n", EleCntr);
1504 fprintf(fElem, "#DevNb\tCompNb\tPrimNb\tId\n");
1505 fprintf(fElem, "%d\t%d\t%d\t%d\n", (EleArr + EleCntr - 1)->DeviceNb,
1506 (EleArr + EleCntr - 1)->ComponentNb,
1507 (EleArr + EleCntr - 1)->PrimitiveNb,
1508 (EleArr + EleCntr - 1)->Id);
1509 fprintf(fElem, "#GType\tX\tY\tZ\tLX\tLZ\tdA\n");
1510 fprintf(
1511 fElem, "%d\t%.16lg\t%.16lg\t%.16lg\t%.16lg\t%.16lg\t%.16lg\n",
1512 (EleArr + EleCntr - 1)->G.Type, (EleArr + EleCntr - 1)->G.Origin.X,
1513 (EleArr + EleCntr - 1)->G.Origin.Y,
1514 (EleArr + EleCntr - 1)->G.Origin.Z, (EleArr + EleCntr - 1)->G.LX,
1515 (EleArr + EleCntr - 1)->G.LZ, (EleArr + EleCntr - 1)->G.dA);
1516 fprintf(fElem, "#DirnCosn: \n");
1517 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.XUnit.X,
1518 (EleArr + EleCntr - 1)->G.DC.XUnit.Y,
1519 (EleArr + EleCntr - 1)->G.DC.XUnit.Z);
1520 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.YUnit.X,
1521 (EleArr + EleCntr - 1)->G.DC.YUnit.Y,
1522 (EleArr + EleCntr - 1)->G.DC.YUnit.Z);
1523 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.ZUnit.X,
1524 (EleArr + EleCntr - 1)->G.DC.ZUnit.Y,
1525 (EleArr + EleCntr - 1)->G.DC.ZUnit.Z);
1526 fprintf(fElem, "#EType\tLambda\n");
1527 fprintf(fElem, "%d\t%lg\n", (EleArr + EleCntr - 1)->E.Type,
1528 (EleArr + EleCntr - 1)->E.Lambda);
1529 fprintf(fElem, "#NbBCs\tCPX\tCPY\tCPZ\tValue\n");
1530 fprintf(fElem, "%d\t%.16lg\t%.16lg\t%.16lg\t%lg\n",
1531 (EleArr + EleCntr - 1)->BC.NbOfBCs,
1532 (EleArr + EleCntr - 1)->BC.CollPt.X,
1533 (EleArr + EleCntr - 1)->BC.CollPt.Y,
1534 (EleArr + EleCntr - 1)->BC.CollPt.Z,
1535 (EleArr + EleCntr - 1)->BC.Value);
1536 } // if OptElementFiles
1537
1538 // draw centroid and mesh
1540 fprintf(fgpElem, "%g\t%g\t%g\n", (EleArr + EleCntr - 1)->BC.CollPt.X,
1541 (EleArr + EleCntr - 1)->BC.CollPt.Y,
1542 (EleArr + EleCntr - 1)->BC.CollPt.Z);
1543 } // if OptGnuplot && OptGnuplotElements
1544
1546 fprintf(fgpMesh, "%g\t%g\t%g\n\n", x0, y0, z0);
1547 fprintf(fgpMesh, "%g\t%g\t%g\n\n", x1, y1, z1);
1548 fprintf(fgpMesh, "%g\t%g\t%g\n\n", x2, y2, z2);
1549 fprintf(fgpMesh, "%g\t%g\t%g\n\n", x3, y3, z3);
1550 fprintf(fgpMesh, "%g\t%g\t%g\n\n", x0, y0, z0);
1551 } // if OptGnuplot && OptGnuplotElements
1552 } // for i
1553 } // for k
1554 ElementEnd[prim] = EleCntr;
1555 NbElmntsOnPrim[prim] = ElementEnd[prim] - ElementBgn[prim] + 1;
1556
1557 if (OptPrimitiveFiles) {
1558 fprintf(fPrim, "Element begin: %d, Element end: %d\n", ElementBgn[prim],
1559 ElementEnd[prim]);
1560 fprintf(fPrim, "Number of elements on primitive: %d\n",
1561 NbElmntsOnPrim[prim]);
1562 fclose(fPrim);
1563 }
1564
1566 if (prim == 1)
1567 fprintf(fgnuElem, " '%s\' w p", gpElem);
1568 else
1569 fprintf(fgnuElem, ", \\\n \'%s\' w p", gpElem);
1570 if (prim == 1) {
1571 fprintf(fgnuMesh, " '%s\' w l", gpMesh);
1572 fprintf(fgnuMesh, ", \\\n \'%s\' w p ps 1", gpElem);
1573 } else {
1574 fprintf(fgnuMesh, ", \\\n \'%s\' w l", gpMesh);
1575 fprintf(fgnuMesh, ", \\\n \'%s\' w p ps 1", gpElem);
1576 }
1577
1578 fclose(fgpElem);
1579 fclose(fgpMesh);
1580 } // if OptGnuplot && OptGnuplotElements
1581
1582 if (OptElementFiles) fclose(fElem);
1583
1584 return (0);
1585} // end of DiscretizeTriangles
int PrintDirnCosn3D(DirnCosn3D A)
Definition: Vector.c:269
neBEMGLOBAL double * Epsilon1
Definition: neBEM.h:75
neBEMGLOBAL int * VolRef1
Definition: neBEM.h:76
neBEMGLOBAL int * VolRef2
Definition: neBEM.h:76
neBEMGLOBAL double * Epsilon2
Definition: neBEM.h:75

Referenced by SurfaceElements().

◆ DiscretizeWire()

neBEMGLOBAL int DiscretizeWire ( int  prim,
int  nvertex,
double  xvert[],
double  yvert[],
double  zvert[],
double  radius,
int  volref1,
int  volref2,
int  inttype,
double  potential,
double  charge,
double  lambda,
int  NbSegs 
)

Definition at line 409 of file ReTriM.c.

412 {
413 int WireParentObj, WireEType;
414 double WireR, WireL;
415 double WireLambda, WireV;
416 double WireElX, WireElY, WireElZ, WireElL;
417 DirnCosn3D PrimDirnCosn; // direction cosine of the current primitive
418 char primstr[10];
419 char gpElem[256];
420 FILE *fPrim, *fElem, *fgpPrim, *fgpElem;
421
422 // Check inputs
423 if (PrimType[prim] != 2) {
424 neBEMMessage("DiscretizeWire - PrimType in DiscretizeWire");
425 return -1;
426 }
427 if (nvertex != 2) {
428 neBEMMessage("DiscretizeWire - nvertex in DiscretizeWire");
429 return -1;
430 }
431 if (radius < MINDIST) {
432 neBEMMessage("DiscretizeWire - radius in DiscretizeWire");
433 return -1;
434 }
435 if (NbSegs <= 0) {
436 neBEMMessage("DiscretizeWire - NbSegs in DiscretizeWire");
437 return -1;
438 }
439
441 printf("nvertex: %d\n", nvertex);
442 for (int vert = 0; vert < nvertex; ++vert) {
443 printf("vert: %d, x: %lg, y: %lg, z: %lg\n", vert, xvert[vert],
444 yvert[vert], zvert[vert]);
445 }
446 printf("radius: %lg\n", radius);
447 } // if OptPrintVertexAndNormal
448
449 // necessary for separating filenames
450 sprintf(primstr, "%d", prim);
451
452 // in order to avoid warning messages
453 fPrim = NULL;
454 fElem = NULL;
455 fgpElem = NULL;
456
457 WireParentObj = 1; // ParentObj not being used now
458
459 WireL = sqrt((xvert[1] - xvert[0]) * (xvert[1] - xvert[0]) // length of wire
460 + (yvert[1] - yvert[0]) * (yvert[1] - yvert[0]) +
461 (zvert[1] - zvert[0]) * (zvert[1] - zvert[0]));
462 WireR = radius;
463 WireElL = WireL / NbSegs; // length of each wire element
464
465 // Direction cosines along the wire - note difference from surface primitives!
466 // The direction along the wire is considered to be the z axis of the LCS
467 // So, let us fix that axial vector first
468 PrimDirnCosn.ZUnit.X = (xvert[1] - xvert[0]) / WireL; // useful
469 PrimDirnCosn.ZUnit.Y = (yvert[1] - yvert[0]) / WireL;
470 PrimDirnCosn.ZUnit.Z = (zvert[1] - zvert[0]) / WireL; // useful
471 // Next, let us find out the coefficients of a plane that passes through the
472 // wire centroid and is normal to the axis of the wire. This is basically the
473 // mid-plane of the cylindrical wire
474 // Any vector OR on the plane normal to the axial direction satisfies
475 // \vec{OR} . \vec{OA} = 0
476 // where O is the wire centroid, A is a point on the axis and R is a point on
477 // the cylindrical surface of the wire. \vec{OA} can be easily replaced by the
478 // axial vector that is equivalent to the vector PrimDirnCosn.ZUnit
479 // The equation of the plane can be shown to be:
480 // XCoef * X + YCoef * Y + ZCoef * Z = Const
481 // double XCoef, YCoef, ZCoef, Const; - not needed any more
482 // double rnorm;
483 // Point3D O, R;
484 // Vector3D OR;
485 // O = CreatePoint3D(WireX, WireY, WireZ);
486 {
487 Vector3D XUnit, YUnit, ZUnit;
488 ZUnit.X = PrimDirnCosn.ZUnit.X;
489 ZUnit.Y = PrimDirnCosn.ZUnit.Y;
490 ZUnit.Z = PrimDirnCosn.ZUnit.Z;
491
492 /* old code - abs instead of fabs??!!
493 XCoef = ZUnit.X;
494 YCoef = ZUnit.Y;
495 ZCoef = ZUnit.Z;
496 double WireX = 0.5 * (xvert[1] + xvert[0]);
497 double WireY = 0.5 * (yvert[1] + yvert[0]);
498 double WireZ = 0.5 * (zvert[1] + zvert[0]);
499 Const = WireX * ZUnit.X + WireY * ZUnit.Y + WireZ * ZUnit.Z;
500 if(abs(XCoef) < 1.0e-12) // X can be anything!
501 {
502 XUnit.X = 1.0;
503 XUnit.Y = 0.0;
504 XUnit.Z = 0.0;
505 YUnit = Vector3DCrossProduct(ZUnit, XUnit);
506 }
507 else
508 {
509 // For a point on the above surface where both Y and Z are zero
510 O = CreatePoint3D(WireX, WireY, WireZ);
511 R = CreatePoint3D(Const, 0, 0);
512 // Create the vector joining O and R; find X and Y unit vectors
513 OR = CreateDistanceVector3D(O,R);
514 XUnit = UnitVector3D(OR);
515 YUnit = Vector3DCrossProduct(ZUnit, XUnit);
516 }
517 old code */
518
519 // replaced following Rob's suggestions (used functions instead of direct
520 // evaluation, although the latter is probably faster)
521 // x-Axis: orthogonal in the 2 largest components.
522 if (fabs(ZUnit.X) >= fabs(ZUnit.Z) && fabs(ZUnit.Y) >= fabs(ZUnit.Z)) {
523 XUnit.X = -ZUnit.Y;
524 XUnit.Y = ZUnit.X;
525 XUnit.Z = 0.0;
526 } else if (fabs(ZUnit.X) >= fabs(ZUnit.Y) &&
527 fabs(ZUnit.Z) >= fabs(ZUnit.Y)) {
528 XUnit.X = -ZUnit.Z;
529 XUnit.Y = 0.0;
530 XUnit.Z = ZUnit.X;
531 } else {
532 XUnit.X = 0.0;
533 XUnit.Y = ZUnit.Z;
534 XUnit.Z = -ZUnit.Y;
535 }
536 XUnit = UnitVector3D(&XUnit);
537
538 // y-Axis: vectorial product of axes 1 and 2.
539 YUnit = Vector3DCrossProduct(&ZUnit, &XUnit);
540 YUnit = UnitVector3D(&YUnit);
541 // end of replacement
542
543 PrimDirnCosn.XUnit.X = XUnit.X;
544 PrimDirnCosn.XUnit.Y = XUnit.Y;
545 PrimDirnCosn.XUnit.Z = XUnit.Z;
546 PrimDirnCosn.YUnit.X = YUnit.X;
547 PrimDirnCosn.YUnit.Y = YUnit.Y;
548 PrimDirnCosn.YUnit.Z = YUnit.Z;
549 } // X and Y direction cosines computed
550
551 // primitive direction cosine assignments
552 PrimDC[prim].XUnit.X = PrimDirnCosn.XUnit.X;
553 PrimDC[prim].XUnit.Y = PrimDirnCosn.XUnit.Y;
554 PrimDC[prim].XUnit.Z = PrimDirnCosn.XUnit.Z;
555 PrimDC[prim].YUnit.X = PrimDirnCosn.YUnit.X;
556 PrimDC[prim].YUnit.Y = PrimDirnCosn.YUnit.Y;
557 PrimDC[prim].YUnit.Z = PrimDirnCosn.YUnit.Z;
558 PrimDC[prim].ZUnit.X = PrimDirnCosn.ZUnit.X;
559 PrimDC[prim].ZUnit.Y = PrimDirnCosn.ZUnit.Y;
560 PrimDC[prim].ZUnit.Z = PrimDirnCosn.ZUnit.Z;
561
562 // primitive origin: also the barycenter for a wire element
563 PrimOriginX[prim] = 0.5 * (xvert[0] + xvert[1]);
564 PrimOriginY[prim] = 0.5 * (yvert[0] + yvert[1]);
565 PrimOriginZ[prim] = 0.5 * (zvert[0] + zvert[1]);
566 PrimLX[prim] = WireR; // radius for wire
567 PrimLZ[prim] = WireL; // length of wire
568
569 WireEType = inttype;
570 WireV = potential;
571 WireLambda = lambda;
572
573 // file output for a primitive
574 if (OptPrimitiveFiles) {
575 char OutPrim[256];
576 strcpy(OutPrim, ModelOutDir);
577 strcat(OutPrim, "/Primitives/Primitive");
578 strcat(OutPrim, primstr);
579 strcat(OutPrim, ".out");
580 fPrim = fopen(OutPrim, "w");
581 if (fPrim == NULL) {
582 neBEMMessage("DiscretizeWire - OutPrim");
583 return -1;
584 }
585 fprintf(fPrim, "#prim: %d, nvertex: %d\n", prim, nvertex);
586 fprintf(fPrim, "Node1: %lg\t%lg\t%lg\n", xvert[0], yvert[0], zvert[0]);
587 fprintf(fPrim, "Node2: %lg\t%lg\t%lg\n", xvert[1], yvert[1], zvert[1]);
588 fprintf(fPrim, "PrimOrigin: %lg\t%lg\t%lg\n", PrimOriginX[prim],
589 PrimOriginY[prim], PrimOriginZ[prim]);
590 fprintf(fPrim, "Primitive lengths: %lg\t%lg\n", PrimLX[prim], PrimLZ[prim]);
591 fprintf(fPrim, "#DirnCosn: \n");
592 fprintf(fPrim, "%lg, %lg, %lg\n", PrimDirnCosn.XUnit.X,
593 PrimDirnCosn.XUnit.Y, PrimDirnCosn.XUnit.Z);
594 fprintf(fPrim, "%lg, %lg, %lg\n", PrimDirnCosn.YUnit.X,
595 PrimDirnCosn.YUnit.Y, PrimDirnCosn.YUnit.Z);
596 fprintf(fPrim, "%lg, %lg, %lg\n", PrimDirnCosn.ZUnit.X,
597 PrimDirnCosn.ZUnit.Y, PrimDirnCosn.ZUnit.Z);
598 fprintf(fPrim, "#volref1: %d, volref2: %d\n", volref1, volref2);
599 fprintf(fPrim, "#NbSegs: %d\n", NbSegs);
600 fprintf(fPrim, "#ParentObj: %d\tEType: %d\n", WireParentObj, WireEType);
601 fprintf(fPrim, "#WireR: %lg\tWireL: %lg\n", WireR, WireL);
602 fprintf(fPrim, "#SurfLambda: %lg\tSurfV: %lg\n", WireLambda, WireV);
603 }
604
605 // necessary for gnuplot
607 char gpPrim[256];
608 strcpy(gpPrim, MeshOutDir);
609 strcat(gpPrim, "/GViewDir/gpPrim");
610 strcat(gpPrim, primstr);
611 strcat(gpPrim, ".out");
612 fgpPrim = fopen(gpPrim, "w");
613 if (fgpPrim == NULL) {
614 neBEMMessage("DiscretizeWire - OutgpPrim");
615 return -1;
616 }
617 fprintf(fgpPrim, "%g\t%g\t%g\n\n", xvert[0], yvert[0], zvert[0]);
618 fprintf(fgpPrim, "%g\t%g\t%g\n\n", xvert[1], yvert[1], zvert[1]);
619 fclose(fgpPrim);
620
621 if (prim == 1)
622 fprintf(fgnuPrim, " '%s\' w l", gpPrim);
623 else
624 fprintf(fgnuPrim, ", \\\n \'%s\' w l", gpPrim);
625 }
626
627 // file outputs for elements on primitive
628 if (OptElementFiles) {
629 char OutElem[256];
630 strcpy(OutElem, MeshOutDir);
631 strcat(OutElem, "/Elements/ElemOnPrim");
632 strcat(OutElem, primstr);
633 strcat(OutElem, ".out");
634 fElem = fopen(OutElem, "w");
635 if (fElem == NULL) {
636 neBEMMessage("DiscretizeWire - OutElem");
637 return -1;
638 }
639 }
640 // gnuplot friendly file outputs for elements on primitive
642 strcpy(gpElem, MeshOutDir);
643 strcat(gpElem, "/GViewDir/gpElemOnPrim");
644 strcat(gpElem, primstr);
645 strcat(gpElem, ".out");
646 fgpElem = fopen(gpElem, "w");
647 if (fgpElem == NULL) {
648 neBEMMessage("DiscretizeWire - OutgpElem");
649 if (fElem) fclose(fElem);
650 return -1;
651 }
652 }
653
654 double xincr = (xvert[1] - xvert[0]) / (double)NbSegs;
655 double yincr = (yvert[1] - yvert[0]) / (double)NbSegs;
656 double zincr = (zvert[1] - zvert[0]) / (double)NbSegs;
657
658 ElementBgn[prim] = EleCntr + 1;
659 double xv0, yv0, zv0, xv1, yv1, zv1;
660 for (int seg = 1; seg <= NbSegs; ++seg) {
661 xv0 = xvert[0] + ((double)seg - 1.0) * xincr;
662 yv0 = yvert[0] + ((double)seg - 1.0) * yincr;
663 zv0 = zvert[0] + ((double)seg - 1.0) * zincr;
664 xv1 = xvert[0] + ((double)seg) * xincr;
665 yv1 = yvert[0] + ((double)seg) * yincr;
666 zv1 = zvert[0] + ((double)seg) * zincr;
667 WireElX = xvert[0] + ((double)seg - 1.0) * xincr + 0.5 * xincr;
668 WireElY = yvert[0] + ((double)seg - 1.0) * yincr + 0.5 * yincr;
669 WireElZ = zvert[0] + ((double)seg - 1.0) * zincr + 0.5 * zincr;
670
671 // Assign element values and write in the file
672 // If element counter exceeds the maximum allowed number of elements, warn!
673 ++EleCntr;
674 if (EleCntr > NbElements) {
675 neBEMMessage("DiscretizeWire - EleCntr more than NbElements!");
676 if (fgpElem) fclose(fgpElem);
677 if (fElem) fclose(fElem);
678 return -1;
679 }
680
681 (EleArr + EleCntr - 1)->DeviceNb =
682 1; // At present, there is only one device
683 (EleArr + EleCntr - 1)->ComponentNb = WireParentObj;
684 (EleArr + EleCntr - 1)->PrimitiveNb = prim;
685 (EleArr + EleCntr - 1)->Id = EleCntr;
686 (EleArr + EleCntr - 1)->G.Type = 2; // linear (wire) here
687 (EleArr + EleCntr - 1)->G.Origin.X = WireElX;
688 (EleArr + EleCntr - 1)->G.Origin.Y = WireElY;
689 (EleArr + EleCntr - 1)->G.Origin.Z = WireElZ;
690 (EleArr + EleCntr - 1)->G.Vertex[0].X = xv0;
691 (EleArr + EleCntr - 1)->G.Vertex[0].Y = yv0;
692 (EleArr + EleCntr - 1)->G.Vertex[0].Z = zv0;
693 (EleArr + EleCntr - 1)->G.Vertex[1].X = xv1;
694 (EleArr + EleCntr - 1)->G.Vertex[1].Y = yv1;
695 (EleArr + EleCntr - 1)->G.Vertex[1].Z = zv1;
696 (EleArr + EleCntr - 1)->G.LX = WireR; // radius of the wire element
697 (EleArr + EleCntr - 1)->G.LZ = WireElL; // wire element length
698 (EleArr + EleCntr - 1)->G.dA = 2.0 * MyPI * (EleArr + EleCntr - 1)->G.LX *
699 (EleArr + EleCntr - 1)->G.LZ;
700 (EleArr + EleCntr - 1)->G.DC.XUnit.X = PrimDirnCosn.XUnit.X;
701 (EleArr + EleCntr - 1)->G.DC.XUnit.Y = PrimDirnCosn.XUnit.Y;
702 (EleArr + EleCntr - 1)->G.DC.XUnit.Z = PrimDirnCosn.XUnit.Z;
703 (EleArr + EleCntr - 1)->G.DC.YUnit.X = PrimDirnCosn.YUnit.X;
704 (EleArr + EleCntr - 1)->G.DC.YUnit.Y = PrimDirnCosn.YUnit.Y;
705 (EleArr + EleCntr - 1)->G.DC.YUnit.Z = PrimDirnCosn.YUnit.Z;
706 (EleArr + EleCntr - 1)->G.DC.ZUnit.X = PrimDirnCosn.ZUnit.X;
707 (EleArr + EleCntr - 1)->G.DC.ZUnit.Y = PrimDirnCosn.ZUnit.Y;
708 (EleArr + EleCntr - 1)->G.DC.ZUnit.Z = PrimDirnCosn.ZUnit.Z;
709 (EleArr + EleCntr - 1)->E.Type = WireEType;
710 (EleArr + EleCntr - 1)->E.Lambda = WireLambda;
711 (EleArr + EleCntr - 1)->Solution = 0.0;
712 (EleArr + EleCntr - 1)->Assigned = charge;
713 (EleArr + EleCntr - 1)->BC.NbOfBCs = 1; // assume one BC per element
714 (EleArr + EleCntr - 1)->BC.CollPt.X =
715 (EleArr + EleCntr - 1)->G.Origin.X; // modify
716 (EleArr + EleCntr - 1)->BC.CollPt.Y =
717 (EleArr + EleCntr - 1)->G.Origin.Y; // to be on
718 (EleArr + EleCntr - 1)->BC.CollPt.Z =
719 (EleArr + EleCntr - 1)->G.Origin.Z; // surface?
720
721 // File operations begin
722 // rfw = fwrite(&Ele, sizeof(Element), 1, fpEle);
723 // printf("Return of fwrite is %d\n", rfw);
724
725 if (OptElementFiles) {
726 fprintf(fElem, "##Element Counter: %d\n", EleCntr);
727 fprintf(fElem, "#DevNb\tCompNb\tPrimNb\tId\n");
728 fprintf(fElem, "%d\t%d\t%d\t%d\n", (EleArr + EleCntr - 1)->DeviceNb,
729 (EleArr + EleCntr - 1)->ComponentNb,
730 (EleArr + EleCntr - 1)->PrimitiveNb, (EleArr + EleCntr - 1)->Id);
731 fprintf(fElem, "#GType\tX\tY\tZ\tLX\tLZ\tdA\n");
732 fprintf(fElem, "%d\t%.16lg\t%.16lg\t%.16lg\t%.16lg\t%.16lg\t%.16lg\n",
733 (EleArr + EleCntr - 1)->G.Type,
734 (EleArr + EleCntr - 1)->G.Origin.X,
735 (EleArr + EleCntr - 1)->G.Origin.Y,
736 (EleArr + EleCntr - 1)->G.Origin.Z, (EleArr + EleCntr - 1)->G.LX,
737 (EleArr + EleCntr - 1)->G.LZ, (EleArr + EleCntr - 1)->G.dA);
738 fprintf(fElem, "#DirnCosn: \n");
739 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.XUnit.X,
740 (EleArr + EleCntr - 1)->G.DC.XUnit.Y,
741 (EleArr + EleCntr - 1)->G.DC.XUnit.Z);
742 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.YUnit.X,
743 (EleArr + EleCntr - 1)->G.DC.YUnit.Y,
744 (EleArr + EleCntr - 1)->G.DC.YUnit.Z);
745 fprintf(fElem, "%lg, %lg, %lg\n", (EleArr + EleCntr - 1)->G.DC.ZUnit.X,
746 (EleArr + EleCntr - 1)->G.DC.ZUnit.Y,
747 (EleArr + EleCntr - 1)->G.DC.ZUnit.Z);
748 fprintf(fElem, "#EType\tLambda\n");
749 fprintf(fElem, "%d\t%lg\n", (EleArr + EleCntr - 1)->E.Type,
750 (EleArr + EleCntr - 1)->E.Lambda);
751 fprintf(fElem, "#NbBCs\tCPX\tCPY\tCPZ\tValue\n");
752 fprintf(fElem, "%d\t%.16lg\t%.16lg\t%.16lg\t%lg\n",
753 (EleArr + EleCntr - 1)->BC.NbOfBCs,
754 (EleArr + EleCntr - 1)->BC.CollPt.X,
755 (EleArr + EleCntr - 1)->BC.CollPt.Y,
756 (EleArr + EleCntr - 1)->BC.CollPt.Z,
757 (EleArr + EleCntr - 1)->BC.Value);
758 } // if OptElementFiles
759 //
760 // mark centroid
762 fprintf(fgpElem, "%g\t%g\t%g\n", (EleArr + EleCntr - 1)->BC.CollPt.X,
763 (EleArr + EleCntr - 1)->BC.CollPt.Y,
764 (EleArr + EleCntr - 1)->BC.CollPt.Z);
765 } // if OptElementFiles
766 // File operations end
767 } // seg loop for wire elements
768 ElementEnd[prim] = EleCntr;
769 NbElmntsOnPrim[prim] = ElementEnd[prim] - ElementBgn[prim] + 1;
770
771 if (OptPrimitiveFiles) {
772 fprintf(fPrim, "Element begin: %d, Element end: %d\n", ElementBgn[prim],
773 ElementEnd[prim]);
774 fprintf(fPrim, "Number of elements on primitive: %d\n",
775 NbElmntsOnPrim[prim]);
776 fclose(fPrim);
777 }
778
779 if (OptElementFiles) fclose(fElem);
780 if (OptGnuplot && OptGnuplotElements) fclose(fgpElem);
781
782 return (0);
783} // end of DiscretizeWire
#define MyPI
Definition: ReTriM.c:15
Vector3D UnitVector3D(Vector3D *v)
Definition: Vector.c:227

Referenced by WireElements().

◆ EffectChUp()

neBEMGLOBAL double EffectChUp ( int  fld)

Definition at line 2364 of file neBEM.c.

2364{ return (ValueChUp(elefld)); }
double ValueChUp(int elefld)
Definition: neBEM.c:2367

Referenced by RHVector().

◆ EffectKnCh()

neBEMGLOBAL double EffectKnCh ( int  fld)

Definition at line 2028 of file neBEM.c.

2028{ return (ValueKnCh(elefld)); }
double ValueKnCh(int elefld)
Definition: neBEM.c:2035

Referenced by RHVector().

◆ ElePFAtPoint()

neBEMGLOBAL int ElePFAtPoint ( Point3D globalPt,
double *  Pot,
Vector3D Flux 
)

Definition at line 697 of file ComputeProperties.c.

697 {
698 int dbgFn = 0;
699
700 const double xfld = globalP->X;
701 const double yfld = globalP->Y;
702 const double zfld = globalP->Z;
703
704 // Compute Potential and field at different locations
705 *Potential = globalF->X = globalF->Y = globalF->Z = 0.0;
706
707 // Effects due to base primitives and their repetitions are considered in the
708 // local coordinate system of the primitive (or element), while effects due to
709 // mirror elements and their repetitions are considered in the global
710 // coordinate system (GCS). This works because the direction cosines of a
711 // primitive (and its elements) and those of its repetitions are the same.
712 // As a result, we can do just one transformation from local to global at the
713 // end of calculations related to a primitive. This can save substantial
714 // computation if a discretized version of the primitive is being used since
715 // we avoid one unnecessary transformation for each element that comprises a
716 // primitive.
717 // Begin with primitive description of the device
718
719 // Scope in OpenMP: Variables in the global data space are accessible to all
720 // threads, while variables in a thread's private space is accessible to the
721 // thread only (there are several variations - copying outside region etc)
722 // Field point remains the same - kept outside private
723 // source point changes with change in primitive - private
724 // TransformationMatrix changes - kept within private (Note: matrices with
725 // fixed dimensions can be maintained, but those with dynamic allocation
726 // can not).
727 double *pPot = dvector(1, NbPrimitives);
728 // Field components in LCS for a primitive and its other incarnations.
729 double *plFx = dvector(1, NbPrimitives);
730 double *plFy = dvector(1, NbPrimitives);
731 double *plFz = dvector(1, NbPrimitives);
732
733 for (int prim = 1; prim <= NbPrimitives; ++prim) {
734 pPot[prim] = plFx[prim] = plFy[prim] = plFz[prim] = 0.0;
735 }
736
737#ifdef _OPENMP
738 int tid = 0, nthreads = 1;
739 #pragma omp parallel private(tid, nthreads)
740#endif
741 {
742
743#ifdef _OPENMP
744 if (dbgFn) {
745 tid = omp_get_thread_num();
746 if (tid == 0) {
747 nthreads = omp_get_num_threads();
748 printf("PFAtPoint computation with %d threads\n", nthreads);
749 }
750 }
751#endif
752// by default, nested parallelization is off in C
753#ifdef _OPENMP
754#pragma omp for
755#endif
756 for (int primsrc = 1; primsrc <= NbPrimitives; ++primsrc) {
757 if (dbgFn) {
758 printf("Evaluating effect of primsrc %d using on %lg, %lg, %lg\n",
759 primsrc, xfld, yfld, zfld);
760 fflush(stdout);
761 }
762
763 const double xpsrc = PrimOriginX[primsrc];
764 const double ypsrc = PrimOriginY[primsrc];
765 const double zpsrc = PrimOriginZ[primsrc];
766
767 // Field in the local frame.
768 double lFx = 0.;
769 double lFy = 0.;
770 double lFz = 0.;
771
772 // Set up transform matrix for this primitive, which is also the same
773 // for all the elements belonging to this primitive.
774 double TransformationMatrix[3][3];
775 TransformationMatrix[0][0] = PrimDC[primsrc].XUnit.X;
776 TransformationMatrix[0][1] = PrimDC[primsrc].XUnit.Y;
777 TransformationMatrix[0][2] = PrimDC[primsrc].XUnit.Z;
778 TransformationMatrix[1][0] = PrimDC[primsrc].YUnit.X;
779 TransformationMatrix[1][1] = PrimDC[primsrc].YUnit.Y;
780 TransformationMatrix[1][2] = PrimDC[primsrc].YUnit.Z;
781 TransformationMatrix[2][0] = PrimDC[primsrc].ZUnit.X;
782 TransformationMatrix[2][1] = PrimDC[primsrc].ZUnit.Y;
783 TransformationMatrix[2][2] = PrimDC[primsrc].ZUnit.Z;
784
785 // The total influence is due to primitives on the basic device and due to
786 // virtual primitives arising out of repetition, reflection etc and not
787 // residing on the basic device
788
789 // basic primitive
790
791 // Evaluate possibility whether primitive influence is accurate enough.
792 // This could be based on localPP and the subtended solid angle.
793 // If 1, then only primitive influence will be considered.
794 int PrimOK = 0;
795 if (PrimOK) {
796 // Only primitive influence will be considered
797 // Potential and flux (local system) due to base primitive
798 double tmpPot;
799 Vector3D tmpF;
800 // Rotate point from global to local system
801 double InitialVector[3] = {xfld - xpsrc, yfld - ypsrc, zfld - zpsrc};
802 double FinalVector[3] = {0., 0., 0.};
803 for (int i = 0; i < 3; ++i) {
804 for (int j = 0; j < 3; ++j) {
805 FinalVector[i] += TransformationMatrix[i][j] * InitialVector[j];
806 }
807 }
808 Point3D localPP;
809 localPP.X = FinalVector[0];
810 localPP.Y = FinalVector[1];
811 localPP.Z = FinalVector[2];
812 GetPrimPF(primsrc, &localPP, &tmpPot, &tmpF);
813 const double qpr = AvChDen[primsrc] + AvAsgndChDen[primsrc];
814 pPot[primsrc] += qpr * tmpPot;
815 lFx += qpr * tmpF.X;
816 lFy += qpr * tmpF.Y;
817 lFz += qpr * tmpF.Z;
818 // if(DebugLevel == 301)
819 if (dbgFn) {
820 printf("PFAtPoint base primitive =>\n");
821 printf("primsrc: %d, xlocal: %lg, ylocal: %lg, zlocal %lg\n",
822 primsrc, localPP.X, localPP.Y, localPP.Z);
823 printf("primsrc: %d, Pot: %lg, Fx: %lg, Fx: %lg, Fz: %lg\n",
824 primsrc, tmpPot, tmpF.X, tmpF.Y, tmpF.Z);
825 printf("primsrc: %d, pPot: %lg, lFx: %lg, lFy: %lg, lFz: %lg\n",
826 primsrc, pPot[primsrc], lFx, lFy, lFz);
827 fflush(stdout);
828 // exit(-1);
829 }
830 } else {
831 // Need to consider element influence.
832 double tPot;
833 Vector3D tF;
834 double ePot = 0.;
835 Vector3D eF;
836 eF.X = 0.0;
837 eF.Y = 0.0;
838 eF.Z = 0.0;
839 const int eleMin = ElementBgn[primsrc];
840 const int eleMax = ElementEnd[primsrc];
841 for (int ele = eleMin; ele <= eleMax; ++ele) {
842 const double xsrc = (EleArr + ele - 1)->G.Origin.X;
843 const double ysrc = (EleArr + ele - 1)->G.Origin.Y;
844 const double zsrc = (EleArr + ele - 1)->G.Origin.Z;
845 // Rotate from global to local system; matrix as for primitive
846 double vG[3] = {xfld - xsrc, yfld - ysrc, zfld - zsrc};
847 double vL[3] = {0., 0., 0.};
848 for (int i = 0; i < 3; ++i) {
849 for (int j = 0; j < 3; ++j) {
850 vL[i] += TransformationMatrix[i][j] * vG[j];
851 }
852 }
853 // Potential and flux (local system) due to base primitive
854 const int type = (EleArr + ele - 1)->G.Type;
855 const double a = (EleArr + ele - 1)->G.LX;
856 const double b = (EleArr + ele - 1)->G.LZ;
857 GetPF(type, a, b, vL[0], vL[1], vL[2], &tPot, &tF);
858 const double qel = (EleArr + ele - 1)->Solution + (EleArr + ele - 1)->Assigned;
859 ePot += qel * tPot;
860 eF.X += qel * tF.X;
861 eF.Y += qel * tF.Y;
862 eF.Z += qel * tF.Z;
863 // if(DebugLevel == 301)
864 if (dbgFn) {
865 printf("PFAtPoint base primitive:%d\n", primsrc);
866 printf("ele: %d, xlocal: %lg, ylocal: %lg, zlocal %lg\n", ele,
867 vL[0], vL[1], vL[2]);
868 printf(
869 "ele: %d, tPot: %lg, tFx: %lg, tFy: %lg, tFz: %lg, Solution: "
870 "%g\n",
871 ele, tPot, tF.X, tF.Y, tF.Z, qel);
872 printf("ele: %d, ePot: %lg, eFx: %lg, eFy: %lg, eFz: %lg\n", ele,
873 ePot, eF.X, eF.Y, eF.Z);
874 fflush(stdout);
875 }
876 } // for all the elements on this primsrc primitive
877
878 pPot[primsrc] += ePot;
879 lFx += eF.X;
880 lFy += eF.Y;
881 lFz += eF.Z;
882 if (dbgFn) {
883 printf(
884 "prim%d, ePot: %lg, eFx: %lg, eFy: %lg, eFz: %lg\n",
885 primsrc, ePot, eF.X, eF.Y, eF.Z);
886 printf("prim%d, pPot: %lg, lFx: %lg, lFy: %lg, lFz: %lg\n", primsrc,
887 pPot[primsrc], lFx, lFy, lFz);
888 fflush(stdout);
889 }
890 } // else elements influence
891
892 // if(DebugLevel == 301)
893 if (dbgFn) {
894 printf("basic primitive\n");
895 printf("primsrc: %d, pPot: %lg, lFx: %lg, lFy: %lg, lFz: %lg\n",
896 primsrc, pPot[primsrc], lFx, lFy, lFz);
897 fflush(stdout);
898 }
899
900 if (MirrorTypeX[primsrc] || MirrorTypeY[primsrc] ||
901 MirrorTypeZ[primsrc]) { // Mirror effect of base primitives
902 printf("Mirror may not be correctly implemented ...\n");
903 exit(0);
904 } // Mirror effect ends
905
906 // Flux due to repeated primitives
907 if ((PeriodicTypeX[primsrc] == 1) || (PeriodicTypeY[primsrc] == 1) ||
908 (PeriodicTypeZ[primsrc] == 1)) {
909 const int perx = PeriodicInX[primsrc];
910 const int pery = PeriodicInY[primsrc];
911 const int perz = PeriodicInZ[primsrc];
912 if (perx || pery || perz) {
913 for (int xrpt = -perx; xrpt <= perx; ++xrpt) {
914 const double xShift = XPeriod[primsrc] * (double)xrpt;
915 const double XPOfRpt = xpsrc + xShift;
916 for (int yrpt = -pery; yrpt <= pery; ++yrpt) {
917 const double yShift = YPeriod[primsrc] * (double)yrpt;
918 const double YPOfRpt = ypsrc + yShift;
919 for (int zrpt = -perz; zrpt <= perz; ++zrpt) {
920 const double zShift = ZPeriod[primsrc] * (double)zrpt;
921 const double ZPOfRpt = zpsrc + zShift;
922 // Skip the basic primitive.
923 if ((xrpt == 0) && (yrpt == 0) && (zrpt == 0)) continue;
924
925 // Basic primitive repeated
926 int repPrimOK = 0;
927 // consider primitive representation accurate enough if it is
928 // repeated and beyond PrimAfter repetitions.
929 if (PrimAfter == 0) {
930 // If PrimAfter is zero, PrimOK is always zero
931 repPrimOK = 0;
932 } else if ((abs(xrpt) > PrimAfter) && (abs(yrpt) > PrimAfter)) {
933 repPrimOK = 1;
934 }
935 if (repPrimOK) {
936 // Use primitive representation
937 // Rotate point from global to local system
938 double InitialVector[3] = {xfld - XPOfRpt, yfld - YPOfRpt, zfld - ZPOfRpt};
939 double FinalVector[3] = {0., 0., 0.};
940 for (int i = 0; i < 3; ++i) {
941 for (int j = 0; j < 3; ++j) {
942 FinalVector[i] +=
943 TransformationMatrix[i][j] * InitialVector[j];
944 }
945 }
946 Point3D localPPR;
947 localPPR.X = FinalVector[0];
948 localPPR.Y = FinalVector[1];
949 localPPR.Z = FinalVector[2];
950 // Potential and flux (local system) due to repeated
951 // primitive
952 double tmpPot;
953 Vector3D tmpF;
954 GetPrimPF(primsrc, &localPPR, &tmpPot, &tmpF);
955 const double qpr = AvChDen[primsrc] + AvAsgndChDen[primsrc];
956 pPot[primsrc] += qpr * tmpPot;
957 lFx += qpr * tmpF.X;
958 lFy += qpr * tmpF.Y;
959 lFz += qpr * tmpF.Z;
960 // if(DebugLevel == 301)
961 if (dbgFn) {
962 printf(
963 "primsrc: %d, xlocal: %lg, ylocal: %lg, zlocal: "
964 "%lg\n",
965 primsrc, localPPR.X, localPPR.Y, localPPR.Z);
966 printf(
967 "primsrc: %d, Pot: %lg, Fx: %lg, Fy: %lg, Fz: %lg\n",
968 primsrc, tmpPot * qpr, tmpF.X * qpr, tmpF.Y * qpr,
969 tmpF.Z * qpr);
970 printf(
971 "primsrc: %d, pPot: %lg, lFx: %lg, lFy: %lg, lFz: "
972 "%lg\n",
973 primsrc, pPot[primsrc], lFx, lFy, lFz);
974 fflush(stdout);
975 }
976 } else {
977 // Use discretized representation of a repeated primitive
978 double tPot;
979 Vector3D tF;
980 double erPot = 0.0;
981 Vector3D erF;
982 erF.X = 0.0;
983 erF.Y = 0.0;
984 erF.Z = 0.0;
985 const int eleMin = ElementBgn[primsrc];
986 const int eleMax = ElementEnd[primsrc];
987 for (int ele = eleMin; ele <= eleMax; ++ele) {
988 const double xrsrc = (EleArr + ele - 1)->G.Origin.X;
989 const double yrsrc = (EleArr + ele - 1)->G.Origin.Y;
990 const double zrsrc = (EleArr + ele - 1)->G.Origin.Z;
991
992 const double XEOfRpt = xrsrc + xShift;
993 const double YEOfRpt = yrsrc + yShift;
994 const double ZEOfRpt = zrsrc + zShift;
995 // Rotate from global to local system
996 double vG[3] = {xfld - XEOfRpt, yfld - YEOfRpt, zfld - ZEOfRpt};
997 double vL[3] = {0., 0., 0.};
998 for (int i = 0; i < 3; ++i) {
999 for (int j = 0; j < 3; ++j) {
1000 vL[i] += TransformationMatrix[i][j] * vG[j];
1001 }
1002 }
1003 // Allowed, because all the local coordinates have the
1004 // same orientations. Only the origins are mutually
1005 // displaced along a line.
1006 const int type = (EleArr + ele - 1)->G.Type;
1007 const double a = (EleArr + ele - 1)->G.LX;
1008 const double b = (EleArr + ele - 1)->G.LZ;
1009 GetPF(type, a, b, vL[0], vL[1], vL[2], &tPot, &tF);
1010 const double qel = (EleArr + ele - 1)->Solution + (EleArr + ele - 1)->Assigned;
1011 erPot += qel * tPot;
1012 erF.X += qel * tF.X;
1013 erF.Y += qel * tF.Y;
1014 erF.Z += qel * tF.Z;
1015 // if(DebugLevel == 301)
1016 if (dbgFn) {
1017 printf("PFAtPoint base primitive:%d\n", primsrc);
1018 printf("ele: %d, xlocal: %lg, ylocal: %lg, zlocal %lg\n",
1019 ele, vL[0], vL[1], vL[2]);
1020 printf(
1021 "ele: %d, tPot: %lg, tFx: %lg, tFy: %lg, tFz: %lg, "
1022 "Solution: %g\n",
1023 ele, tPot, tF.X, tF.Y, tF.Z, qel);
1024 printf(
1025 "ele: %d, ePot: %lg, eFx: %lg, eFy: %lg, eFz: %lg\n",
1026 ele, erPot, erF.X, erF.Y, erF.Z);
1027 fflush(stdout);
1028 }
1029 } // for all the elements on this primsrc repeated
1030 // primitive
1031
1032 pPot[primsrc] += erPot;
1033 lFx += erF.X;
1034 lFy += erF.Y;
1035 lFz += erF.Z;
1036 } // else discretized representation of this primitive
1037
1038 // if(DebugLevel == 301)
1039 if (dbgFn) {
1040 printf("basic repeated xrpt: %d. yrpt: %d, zrpt: %d\n",
1041 xrpt, yrpt, zrpt);
1042 printf(
1043 "primsrc: %d, pPot: %lg, lFx: %lg, lFy: %lg, lFz: %lg\n",
1044 primsrc, pPot[primsrc], lFx, lFy, lFz);
1045 fflush(stdout);
1046 }
1047
1048 if (MirrorTypeX[primsrc] || MirrorTypeY[primsrc] ||
1049 MirrorTypeZ[primsrc]) { // Mirror effect of repeated
1050 // primitives - not parallelized
1051 printf(
1052 "Mirror not correctly implemented in this version of "
1053 "neBEM ...\n");
1054 exit(0);
1055
1056 double tmpPot;
1057 Vector3D tmpF;
1058 Point3D srcptp;
1059 Point3D localPPRM; // point primitive repeated mirrored
1060 DirnCosn3D DirCos;
1061
1062 srcptp.X = XPOfRpt;
1063 srcptp.Y = YPOfRpt;
1064 srcptp.Z = ZPOfRpt;
1065
1066 Point3D fldpt;
1067 fldpt.X = xfld;
1068 fldpt.Y = yfld;
1069 fldpt.Z = zfld;
1070 if (MirrorTypeX[primsrc]) {
1071 MirrorTypeY[primsrc] = 0;
1072 MirrorTypeZ[primsrc] = 0;
1073 }
1074 if (MirrorTypeY[primsrc]) MirrorTypeZ[primsrc] = 0;
1075
1076 if (MirrorTypeX[primsrc]) {
1077 localPPRM = ReflectPrimitiveOnMirror(
1078 'X', primsrc, srcptp, fldpt,
1079 MirrorDistXFromOrigin[primsrc], &DirCos);
1080
1081 // check whether primitive description is good enough
1082 int mirrPrimOK = 0;
1083 if (mirrPrimOK) {
1084 GetPrimPFGCS(primsrc, &localPPRM, &tmpPot, &tmpF,
1085 &DirCos);
1086 const double qpr = AvChDen[primsrc] + AvAsgndChDen[primsrc];
1087 if (MirrorTypeX[primsrc] == 1) {
1088 // opposite charge density
1089 pPot[primsrc] -= qpr * tmpPot;
1090 lFx -= qpr * tmpF.X;
1091 lFy -= qpr * tmpF.Y;
1092 lFz -= qpr * tmpF.Z;
1093 } else if (MirrorTypeX[primsrc] == 2) {
1094 // same charge density
1095 pPot[primsrc] += qpr * tmpPot;
1096 lFx += qpr * tmpF.X;
1097 lFy += qpr * tmpF.Y;
1098 lFz += qpr * tmpF.Z;
1099 }
1100 } else { // consider element representation
1101 Point3D localPERM; // point element repeated mirrored
1102 Point3D srcpte;
1103
1104 const int eleMin = ElementBgn[primsrc];
1105 const int eleMax = ElementEnd[primsrc];
1106 for (int ele = eleMin; ele <= eleMax; ++ele) {
1107 const double xsrc = (EleArr + ele - 1)->G.Origin.X;
1108 const double ysrc = (EleArr + ele - 1)->G.Origin.Y;
1109 const double zsrc = (EleArr + ele - 1)->G.Origin.Z;
1110
1111 const double XEOfRpt = xsrc + xShift;
1112 const double YEOfRpt = ysrc + yShift;
1113 const double ZEOfRpt = zsrc + zShift;
1114
1115 srcpte.X = XEOfRpt;
1116 srcpte.Y = YEOfRpt;
1117 srcpte.Z = ZEOfRpt;
1118
1119 localPERM = ReflectOnMirror(
1120 'X', ele, srcpte, fldpt,
1121 MirrorDistXFromOrigin[primsrc], &DirCos);
1122 const int type = (EleArr + ele - 1)->G.Type;
1123 const double a = (EleArr + ele - 1)->G.LX;
1124 const double b = (EleArr + ele - 1)->G.LZ;
1125 GetPFGCS(type, a, b, &localPERM, &tmpPot, &tmpF, &DirCos); // force?
1126 const double qel = (EleArr + ele - 1)->Solution + (EleArr + ele - 1)->Assigned;
1127 if (MirrorTypeX[primsrc] == 1) {
1128 // opposite charge density
1129 pPot[primsrc] -= qel * tmpPot;
1130 lFx -= qel * tmpF.X;
1131 lFy -= qel * tmpF.Y;
1132 lFz -= qel * tmpF.Z;
1133 } else if (MirrorTypeX[primsrc] == 2) {
1134 // same charge density
1135 pPot[primsrc] += qel * tmpPot;
1136 lFx += qel * tmpF.X;
1137 lFy += qel * tmpF.Y;
1138 lFz += qel * tmpF.Z;
1139 }
1140 } // loop for all elements on the primsrc primitive
1141 } // else element representation
1142 } // MirrorTypeX
1143
1144 if (MirrorTypeY[primsrc]) {
1145 localPPRM = ReflectOnMirror('Y', primsrc, srcptp, fldpt,
1146 MirrorDistYFromOrigin[primsrc],
1147 &DirCos);
1148
1149 // check whether primitive description is good enough
1150 int mirrPrimOK = 0;
1151 if (mirrPrimOK) {
1152 GetPrimPFGCS(primsrc, &localPPRM, &tmpPot, &tmpF,
1153 &DirCos);
1154 const double qpr = AvChDen[primsrc] + AvAsgndChDen[primsrc];
1155 if (MirrorTypeY[primsrc] == 1) {
1156 // opposite charge density
1157 pPot[primsrc] -= qpr * tmpPot;
1158 lFx -= qpr * tmpF.X;
1159 lFy -= qpr * tmpF.Y;
1160 lFz -= qpr * tmpF.Z;
1161 } else if (MirrorTypeY[primsrc] == 2) {
1162 // same charge density
1163 pPot[primsrc] += qpr * tmpPot;
1164 lFx += qpr * tmpF.X;
1165 lFy += qpr * tmpF.Y;
1166 lFz += qpr * tmpF.Z;
1167 }
1168 } else { // consider element representation
1169 Point3D localPERM;
1170 Point3D srcpte;
1171
1172 const int eleMin = ElementBgn[primsrc];
1173 const int eleMax = ElementEnd[primsrc];
1174 for (int ele = eleMin; ele <= eleMax; ++ele) {
1175 const double xsrc = (EleArr + ele - 1)->G.Origin.X;
1176 const double ysrc = (EleArr + ele - 1)->G.Origin.Y;
1177 const double zsrc = (EleArr + ele - 1)->G.Origin.Z;
1178
1179 const double XEOfRpt = xsrc + xShift;
1180 const double YEOfRpt = ysrc + yShift;
1181 const double ZEOfRpt = zsrc + zShift;
1182
1183 srcpte.X = XEOfRpt;
1184 srcpte.Y = YEOfRpt;
1185 srcpte.Z = ZEOfRpt;
1186
1187 localPERM = ReflectOnMirror(
1188 'Y', ele, srcpte, fldpt,
1189 MirrorDistYFromOrigin[primsrc], &DirCos);
1190 const int type = (EleArr + ele - 1)->G.Type;
1191 const double a = (EleArr + ele - 1)->G.LX;
1192 const double b = (EleArr + ele - 1)->G.LZ;
1193 GetPFGCS(type, a, b, &localPERM, &tmpPot, &tmpF, &DirCos);
1194 const double qel = (EleArr + ele - 1)->Solution + (EleArr + ele - 1)->Assigned;
1195 if (MirrorTypeY[primsrc] == 1) {
1196 // opposite charge density
1197 pPot[primsrc] -= qel * tmpPot;
1198 lFx -= qel * tmpF.X;
1199 lFy -= qel * tmpF.Y;
1200 lFz -= qel * tmpF.Z;
1201 } else if (MirrorTypeY[primsrc] == 2) {
1202 // same charge density
1203 pPot[primsrc] += qel * tmpPot;
1204 lFx += qel * tmpF.X;
1205 lFy += qel * tmpF.Y;
1206 lFz += qel * tmpF.Z;
1207 }
1208 } // loop for all elements on the primsrc primitive
1209 } // else element representations
1210 } // MirrorTypeY
1211
1212 if (MirrorTypeZ[primsrc]) {
1213 localPPRM = ReflectOnMirror('Z', primsrc, srcptp, fldpt,
1214 MirrorDistZFromOrigin[primsrc],
1215 &DirCos);
1216
1217 // check whether primitive description is good enough
1218 int mirrPrimOK = 0;
1219 if (mirrPrimOK) {
1220 GetPrimPFGCS(primsrc, &localPPRM, &tmpPot, &tmpF,
1221 &DirCos);
1222 const double qpr = AvChDen[primsrc] + AvAsgndChDen[primsrc];
1223 if (MirrorTypeZ[primsrc] == 1) {
1224 // opposite charge density
1225 pPot[primsrc] -= qpr * tmpPot;
1226 lFx -= qpr * tmpF.X;
1227 lFy -= qpr * tmpF.Y;
1228 lFz -= qpr * tmpF.Z;
1229 } else if (MirrorTypeZ[primsrc] == 2) {
1230 // same charge density
1231 pPot[primsrc] += qpr * tmpPot;
1232 lFx += qpr * tmpF.X;
1233 lFy += qpr * tmpF.Y;
1234 lFz += qpr * tmpF.Z;
1235 }
1236 } else {
1237 // elements to be considered
1238 Point3D localPERM;
1239 Point3D srcpte;
1240
1241 const int eleMin = ElementBgn[primsrc];
1242 const int eleMax = ElementEnd[primsrc];
1243 for (int ele = eleMin; ele <= eleMax; ++ele) {
1244 const double xsrc = (EleArr + ele - 1)->G.Origin.X;
1245 const double ysrc = (EleArr + ele - 1)->G.Origin.Y;
1246 const double zsrc = (EleArr + ele - 1)->G.Origin.Z;
1247
1248 const double XEOfRpt = xsrc + xShift;
1249 const double YEOfRpt = ysrc + yShift;
1250 const double ZEOfRpt = zsrc + zShift;
1251
1252 srcpte.X = XEOfRpt;
1253 srcpte.Y = YEOfRpt;
1254 srcpte.Z = ZEOfRpt;
1255
1256 localPERM = ReflectOnMirror(
1257 'Z', ele, srcpte, fldpt,
1258 MirrorDistZFromOrigin[primsrc], &DirCos);
1259 const int type = (EleArr + ele - 1)->G.Type;
1260 const double a = (EleArr + ele - 1)->G.LX;
1261 const double b = (EleArr + ele - 1)->G.LZ;
1262 GetPFGCS(type, a, b, &localPERM, &tmpPot, &tmpF, &DirCos);
1263 const double qel = (EleArr + ele - 1)->Solution + (EleArr + ele - 1)->Assigned;
1264 if (MirrorTypeZ[primsrc] == 1) {
1265 // opposite charge density
1266 pPot[primsrc] -= qel * tmpPot;
1267 lFx -= qel * tmpF.X;
1268 lFy -= qel * tmpF.Y;
1269 lFz -= qel * tmpF.Z;
1270 } else if (MirrorTypeZ[primsrc] == 2) {
1271 // same charge density
1272 pPot[primsrc] += qel * tmpPot;
1273 lFx += qel * tmpF.X;
1274 lFy += qel * tmpF.Y;
1275 lFz += qel * tmpF.Z;
1276 }
1277 } // loop for all elements on the primsrc primitive
1278 } // else consider element representation
1279 } // MirrorTypeZ
1280 } // Mirror effect for repeated primitives ends
1281
1282 } // for zrpt
1283 } // for yrpt
1284 } // for xrpt
1285 } // PeriodicInX || PeriodicInY || PeriodicInZ
1286 } // PeriodicType == 1
1287 Vector3D localF;
1288 localF.X = lFx;
1289 localF.Y = lFy;
1290 localF.Z = lFz;
1291 Vector3D tmpF = RotateVector3D(&localF, &PrimDC[primsrc], local2global);
1292 plFx[primsrc] = tmpF.X;
1293 plFy[primsrc] = tmpF.Y;
1294 plFz[primsrc] = tmpF.Z;
1295 } // for all primitives: basic device, mirror reflections and repetitions
1296 } // pragma omp parallel
1297
1298 double totPot = 0.0;
1299 Vector3D totF;
1300 totF.X = totF.Y = totF.Z = 0.0;
1301 for (int prim = 1; prim <= NbPrimitives; ++prim) {
1302 totPot += pPot[prim];
1303 totF.X += plFx[prim];
1304 totF.Y += plFy[prim];
1305 totF.Z += plFz[prim];
1306 }
1307
1308 // This is done at the end of the function - before freeing memory
1309#ifdef __cplusplus
1310 *Potential = totPot * InvFourPiEps0;
1311 globalF->X = totF.X * InvFourPiEps0;
1312 globalF->Y = totF.Y * InvFourPiEps0;
1313 globalF->Z = totF.Z * InvFourPiEps0;
1314#else
1315 *Potential = totPot / MyFACTOR;
1316 globalF->X = totF.X / MyFACTOR;
1317 globalF->Y = totF.Y / MyFACTOR;
1318 globalF->Z = totF.Z / MyFACTOR;
1319#endif
1320 (*Potential) += VSystemChargeZero; // respect total system charge constraint
1321
1322 if (dbgFn) {
1323 printf("Final values due to all primitives: ");
1324 // printf("xfld\tyfld\tzfld\tPot\tFx\tFy\tFz\n"); // refer, do not
1325 // uncomment
1326 printf("%lg\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n\n", xfld, yfld, zfld,
1327 (*Potential), globalF->X, globalF->Y, globalF->Z);
1328 fflush(stdout);
1329 }
1330
1331 free_dvector(pPot, 1, NbPrimitives);
1332 free_dvector(plFx, 1, NbPrimitives);
1333 free_dvector(plFy, 1, NbPrimitives);
1334 free_dvector(plFz, 1, NbPrimitives);
1335
1336 return (0);
1337} // end of ElePFAtPoint
void GetPrimPFGCS(int prim, Point3D *localP, double *Potential, Vector3D *globalF, DirnCosn3D *DirCos)
void GetPFGCS(int type, double a, double b, Point3D *localP, double *Potential, Vector3D *globalF, DirnCosn3D *DirCos)
void GetPrimPF(int prim, Point3D *localP, double *Potential, Vector3D *localF)
void GetPF(int type, double a, double b, double x, double y, double z, double *Potential, Vector3D *localF)
Point3D ReflectPrimitiveOnMirror(char Axis, int primsrc, Point3D srcpt, Point3D fldpt, double distance, DirnCosn3D *MirroredDC)
Definition: neBEM.c:3742
Point3D ReflectOnMirror(char Axis, int elesrc, Point3D srcpt, Point3D fldpt, double distance, DirnCosn3D *MirroredDC)
Definition: neBEM.c:3831
neBEMGLOBAL int * PeriodicInY
Definition: neBEM.h:79
neBEMGLOBAL int * MirrorTypeZ
Definition: neBEM.h:81
neBEMGLOBAL double * MirrorDistYFromOrigin
Definition: neBEM.h:82
neBEMGLOBAL double * ZPeriod
Definition: neBEM.h:80
neBEMGLOBAL double VSystemChargeZero
Definition: neBEM.h:122
neBEMGLOBAL int NbPrimitives
Definition: neBEM.h:57
neBEMGLOBAL int * PeriodicTypeX
Definition: neBEM.h:78
neBEMGLOBAL int * PeriodicTypeY
Definition: neBEM.h:78
neBEMGLOBAL double * MirrorDistZFromOrigin
Definition: neBEM.h:83
neBEMGLOBAL int PrimAfter
Definition: neBEM.h:351
neBEMGLOBAL double * XPeriod
Definition: neBEM.h:80
neBEMGLOBAL double * AvAsgndChDen
Definition: neBEM.h:90
neBEMGLOBAL int * MirrorTypeY
Definition: neBEM.h:81
neBEMGLOBAL double * AvChDen
Definition: neBEM.h:90
neBEMGLOBAL int * MirrorTypeX
Definition: neBEM.h:81
neBEMGLOBAL int * PeriodicInZ
Definition: neBEM.h:79
neBEMGLOBAL int * PeriodicInX
Definition: neBEM.h:79
neBEMGLOBAL int * PeriodicTypeZ
Definition: neBEM.h:78
neBEMGLOBAL double * YPeriod
Definition: neBEM.h:80
neBEMGLOBAL double * MirrorDistXFromOrigin
Definition: neBEM.h:82
void free_dvector(double *v, long nl, long)
Definition: nrutil.c:470
double * dvector(long nl, long nh)
Definition: nrutil.c:63

Referenced by PFAtPoint(), and WtFldFastPFAtPoint().

◆ FastElePFAtPoint()

neBEMGLOBAL int FastElePFAtPoint ( Point3D globalPt,
double *  Pot,
Vector3D Flux 
)

Definition at line 3318 of file ComputeProperties.c.

3319 {
3320 return 0;
3321} // FastElePFAtPoint ends

◆ FastKnChPFAtPoint()

neBEMGLOBAL int FastKnChPFAtPoint ( Point3D globalPt,
double *  Pot,
Vector3D Flux 
)

Definition at line 3326 of file ComputeProperties.c.

3326 {
3327 int dbgFn = 0;
3328 double Xpt = globalP->X;
3329 double Ypt = globalP->Y;
3330 double Zpt = globalP->Z;
3331 double RptVolLX = FastVol.LX;
3332 double RptVolLY = FastVol.LY;
3333 double RptVolLZ = FastVol.LZ;
3334 double CornerX = FastVol.CrnrX;
3335 double CornerY = FastVol.CrnrY;
3336 double CornerZ = FastVol.CrnrZ;
3337 double TriLin(double xd, double yd, double zd, double c000, double c100,
3338 double c010, double c001, double c110, double c101, double c011,
3339 double c111);
3340
3341 // First of all, check how the point in question should be treated ...
3342
3343 // Check whether the point falls within a volume that is not regarded as
3344 // FastVol
3345 for (int ignore = 1; ignore <= FastVol.NbIgnoreVols; ++ignore) {
3346 if ((Xpt >= (IgnoreVolCrnrX[ignore])) &&
3347 (Xpt <= (IgnoreVolCrnrX[ignore] + IgnoreVolLX[ignore])) &&
3348 (Ypt >= (IgnoreVolCrnrY[ignore])) &&
3349 (Ypt <= (IgnoreVolCrnrY[ignore] + IgnoreVolLY[ignore])) &&
3350 (Zpt >= (IgnoreVolCrnrZ[ignore])) &&
3351 (Zpt <= (IgnoreVolCrnrZ[ignore] + IgnoreVolLZ[ignore]))) {
3352 if (dbgFn)
3353 neBEMMessage("In FastKnChPFAtPoint: point in an ignored volume!\n");
3354
3355 int fstatus = KnChPFAtPoint(globalP, Potential, globalF);
3356 if (fstatus != 0) {
3357 neBEMMessage("wrong KnChPFAtPoint return value in FastVolKnChPF.\n");
3358 return -1;
3359 } else
3360 return 0;
3361 }
3362 } // loop over ignored volumes
3363
3364 // If not ignored, the point qualifies for FastVol evaluation ...
3365
3366 // for a staggered fast volume, the volume repeated in X is larger
3367 if (OptStaggerFastVol) {
3368 RptVolLX += FastVol.LX;
3369 }
3370 if (dbgFn) {
3371 printf("\nin FastKnChPFAtPoint\n");
3372 printf("x, y, z: %g, %g, %g\n", Xpt, Ypt, Zpt);
3373 printf("RptVolLX, RptVolLY, RptVolLZ: %g, %g, %g\n", RptVolLX, RptVolLY,
3374 RptVolLZ);
3375 printf("CornerX, CornerY, CornerZ: %g, %g, %g\n", CornerX, CornerY,
3376 CornerZ);
3377 printf("Nb of blocks: %d\n", FastVol.NbBlocks);
3378 for (int block = 1; block <= FastVol.NbBlocks; ++block) {
3379 printf("NbOfXCells: %d\n", BlkNbXCells[block]);
3380 printf("NbOfYCells: %d\n", BlkNbYCells[block]);
3381 printf("NbOfZCells: %d\n", BlkNbZCells[block]);
3382 printf("LZ: %le\n", BlkLZ[block]);
3383 printf("CornerZ: %le\n", BlkCrnrZ[block]);
3384 }
3385 }
3386
3387 // Find equivalent position inside the basic / staggered volume.
3388 // real distance from volume corner
3389 double dx = Xpt - CornerX;
3390 double dy = Ypt - CornerY;
3391 double dz = Zpt - CornerZ;
3392 if (dbgFn)
3393 printf("real dx, dy, dz from volume corner: %g, %g, %g\n", dx, dy, dz);
3394
3395 int NbFastVolX = (int)(dx / RptVolLX);
3396 if (dx < 0.0) --NbFastVolX;
3397 int NbFastVolY = (int)(dy / RptVolLY);
3398 if (dy < 0.0) --NbFastVolY;
3399 int NbFastVolZ = (int)(dz / RptVolLZ);
3400 if (dz < 0.0) --NbFastVolZ;
3401 if (dbgFn)
3402 printf("Volumes in x, y, z: %d, %d, %d\n", NbFastVolX, NbFastVolY,
3403 NbFastVolZ);
3404
3405 // equivalent distances from fast volume corner
3406 dx -= NbFastVolX * RptVolLX;
3407 dy -= NbFastVolY * RptVolLY;
3408 dz -= NbFastVolZ * RptVolLZ;
3409 // The following conditions should never happen - generate an error message
3410 if (dx < 0.0) {
3411 dx = 0.0;
3412 neBEMMessage("equiv dx < 0.0 - not correct!\n");
3413 }
3414 if (dy < 0.0) {
3415 dy = 0.0;
3416 neBEMMessage("equiv dy < 0.0 - not correct!\n");
3417 }
3418 if (dz < 0.0) {
3419 dz = 0.0;
3420 neBEMMessage("equiv dz < 0.0 - not correct!\n");
3421 }
3422 if (dx > RptVolLX) {
3423 dx = RptVolLX;
3424 neBEMMessage("equiv dx > RptVolLX - not correct!\n");
3425 }
3426 if (dy > RptVolLY) {
3427 dy = RptVolLY;
3428 neBEMMessage("equiv dy > RptVolLY - not correct!\n");
3429 }
3430 if (dz > RptVolLZ) {
3431 dz = RptVolLZ;
3432 neBEMMessage("equiv dz > RptVolLZ - not correct!\n");
3433 }
3434 if (dbgFn)
3435 printf("equivalent dist from corner - dx, dy, dz: %g, %g, %g\n", dx, dy,
3436 dz);
3437
3438 // Take care of possible trouble-makers
3439 if (dx < MINDIST) dx = MINDIST; // -ve dx has already been made equal to 0
3440 if (dy < MINDIST) dy = MINDIST;
3441 if (dz < MINDIST) dz = MINDIST;
3442 if ((RptVolLX - dx) < MINDIST)
3443 dx = RptVolLX - MINDIST; // dx > RptVolLX taken care of
3444 if ((RptVolLY - dy) < MINDIST) dy = RptVolLY - MINDIST;
3445 if ((RptVolLZ - dz) < MINDIST) dz = RptVolLZ - MINDIST;
3446 // For staggered volumes, there is another plane where difficulties may occur
3447 if ((dx <= FastVol.LX) && (FastVol.LX - dx) < MINDIST)
3448 dx = FastVol.LX - MINDIST;
3449 // else if((dx > FastVol.LX) && (fabs(FastVol.LX-dx) < MINDIST))
3450 else if ((dx > FastVol.LX) && (dx - FastVol.LX) < MINDIST) // more inttuitive
3451 dx = FastVol.LX + MINDIST;
3452 if (dbgFn)
3453 printf("equivalent dist adjusted - dx, dy, dz: %g, %g, %g\n", dx, dy, dz);
3454
3455 // If volume is staggered, we have a few more things to do before finalizing
3456 // the values of equivalent distance
3457 // sector identification
3458 // _................__________________
3459 // | . . | Sector 3 |
3460 // | . . | |
3461 // | . | . |
3462 // | | . . |
3463 // | Sector 2 | . . |
3464 // |----------------| . . |
3465 // | | . |
3466 // | . | |
3467 // | . . | |
3468 // | . . |----------------|
3469 // | . . | Sector 4 |
3470 // | . | . |
3471 // | | . . |
3472 // | Sector 1 | . . |
3473 // |----------------|................|
3474
3475 int sector = 1; // kept outside `if' since this is necessary further below
3476 if (OptStaggerFastVol) {
3477 if ((dx >= 0.0) && (dx <= FastVol.LX) && (dy >= 0.0) &&
3478 (dy <= FastVol.LY)) {
3479 // point lies in sector 1, everything remains unchanged
3480 sector = 1;
3481 } else if ((dx >= 0.0) && (dx <= FastVol.LX) && (dy > FastVol.LY) &&
3482 (dy <= FastVol.LY + FastVol.YStagger)) {
3483 // point lies in sector 2, move basic volume one step up
3484 sector = 2;
3485 ++NbFastVolY;
3486 CornerY += FastVol.LY; // repeat length in Y is LY
3487 dy -= FastVol.LY;
3488 } else if ((dx > FastVol.LX) && (dx <= 2.0 * FastVol.LX) &&
3489 (dy >= FastVol.YStagger) &&
3490 (dy <= FastVol.LY + FastVol.YStagger)) {
3491 // point lies in sector 3, pt in staggered vol, change corner coords
3492 sector = 3;
3493 CornerX += FastVol.LX;
3494 CornerY += FastVol.YStagger;
3495 dx -= FastVol.LX;
3496 dy -= FastVol.YStagger;
3497 } else if ((dx > FastVol.LX) && (dx <= 2.0 * FastVol.LX) && (dy >= 0.0) &&
3498 (dy < FastVol.YStagger)) {
3499 // point lies in sector 4, move basic volume one step down and consider
3500 // staggered fast volume
3501 sector = 4;
3502 --NbFastVolY;
3503 CornerX += FastVol.LX; // in the staggered part of the repeated volume
3504 CornerY -= (FastVol.LY - FastVol.YStagger);
3505 dx -= FastVol.LX;
3506 dy += (FastVol.LY - FastVol.YStagger);
3507 } else {
3508 neBEMMessage("FastKnChPFAtPoint: point in none of the sectors!\n");
3509 }
3510 if (dbgFn) printf("stagger modified dx, dy, dz: %g, %g, %g\n", dx, dy, dz);
3511 }
3512
3513 // Take care of possible trouble-makers - once more
3514 if (dx < MINDIST) dx = MINDIST; // -ve dx has already been made equal to 0
3515 if (dy < MINDIST) dy = MINDIST;
3516 if (dz < MINDIST) dz = MINDIST;
3517 if ((RptVolLX - dx) < MINDIST)
3518 dx = RptVolLX - MINDIST; // dx > RptVolLX taken care of
3519 if ((RptVolLY - dy) < MINDIST) dy = RptVolLY - MINDIST;
3520 if ((RptVolLZ - dz) < MINDIST) dz = RptVolLZ - MINDIST;
3521 // For staggered volumes, there is another plane where difficulties may occur
3522 if ((dx <= FastVol.LX) && (FastVol.LX - dx) < MINDIST)
3523 dx = FastVol.LX - MINDIST;
3524 // else if((dx > FastVol.LX) && (fabs(FastVol.LX-dx) < MINDIST))
3525 else if ((dx > FastVol.LX) && (dx - FastVol.LX) < MINDIST) // more intuitive
3526 dx = FastVol.LX + MINDIST;
3527 if (dbgFn)
3528 printf("equivalent dist adjusted for staggered: %g, %g, %g\n", dx, dy, dz);
3529
3530 /*
3531 // Check whether the point falls within a volume that is omitted
3532 for(int omit = 1; omit <= FastVol.NbOmitVols; ++omit)
3533 {
3534 if((dx >= (OmitVolCrnrX[omit]-FastVol.CrnrX))
3535 && (dx <=
3536 (OmitVolCrnrX[omit]+OmitVolLX[omit]-FastVol.CrnrX))
3537 && (dy >= (OmitVolCrnrY[omit]-FastVol.CrnrY))
3538 && (dy <=
3539 (OmitVolCrnrY[omit]+OmitVolLY[omit]-FastVol.CrnrY))
3540 && (dz >= (OmitVolCrnrZ[omit]-FastVol.CrnrZ))
3541 && (dz <=
3542 (OmitVolCrnrZ[omit]+OmitVolLZ[omit]-FastVol.CrnrZ)))
3543 {
3544 neBEMMessage("In FastKnChPFAtPoint: point in an omitted
3545 volume!\n"); *Potential = 0.0; globalF->X = 0.0; globalF->Y = 0.0; globalF->Z
3546 = 0.0;
3547 }
3548 } // loop over omitted volumes
3549
3550 // Find the block in which the point lies
3551 int thisBlock = 1;
3552 if(FastVol.NbBlocks > 1)
3553 {
3554 for(int block = 1; block <= FastVol.NbBlocks; ++block)
3555 {
3556 if(dbgFn)
3557 {
3558 printf("dz,(BlkCrnrZ-CornerZ),(BlkCrnrZ+BlkLZ-CornerZ):
3559 %lg, %lg, %lg\n", dz, (BlkCrnrZ[block]-CornerZ),
3560 (BlkCrnrZ[block]+BlkLZ[block]-CornerZ));
3561 }
3562 if((dz >= (BlkCrnrZ[block]-CornerZ))
3563 && (dz <=
3564 (BlkCrnrZ[block]+BlkLZ[block]-CornerZ)))
3565 {
3566 thisBlock = block;
3567 break;
3568 }
3569 }
3570 } // if NbBlocks > 1
3571 */
3572
3573 int thisBlock = 0;
3574 for (int block = 1; block <= FastVol.NbBlocks; ++block) {
3575 double blkBtmZ = BlkCrnrZ[block] - CornerZ; // since CornerZ has been
3576 double blkTopZ = blkBtmZ + BlkLZ[block]; // subtracted from dz already
3577 if (dbgFn) {
3578 printf("block, dz, blkBtmZ, blkTopZ: %d, %lg, %lg, %lg\n", block, dz,
3579 blkBtmZ, blkTopZ);
3580 }
3581
3582 // take care of difficult situations
3583 if ((dz <= blkBtmZ) && ((blkBtmZ - dz) < MINDIST)) dz = blkBtmZ - MINDIST;
3584 if ((dz >= blkBtmZ) && ((dz - blkBtmZ) < MINDIST)) dz = blkBtmZ + MINDIST;
3585 if ((dz <= blkTopZ) && ((blkTopZ - dz) < MINDIST)) dz = blkTopZ - MINDIST;
3586 if ((dz >= blkTopZ) && ((dz - blkTopZ) < MINDIST)) dz = blkTopZ + MINDIST;
3587
3588 if ((dz >= blkBtmZ) && (dz <= blkTopZ)) {
3589 thisBlock = block;
3590 break;
3591 }
3592 }
3593 if (!thisBlock) {
3594 neBEMMessage("FastKnChPFAtPoint: point in none of the blocks!\n");
3595 }
3596
3597 int nbXCells = BlkNbXCells[thisBlock];
3598 int nbYCells = BlkNbYCells[thisBlock];
3599 int nbZCells = BlkNbZCells[thisBlock];
3600 double delX = FastVol.LX / nbXCells;
3601 double delY = FastVol.LY / nbYCells;
3602 double delZ = BlkLZ[thisBlock] / nbZCells;
3603 dz -= (BlkCrnrZ[thisBlock] - CornerZ); // distance from the block corner
3604
3605 if (dbgFn) {
3606 printf("thisBlock: %d\n", thisBlock);
3607 printf("nbXCells, nbYCells, nbZCells: %d, %d, %d\n", nbXCells, nbYCells,
3608 nbZCells);
3609 printf("BlkCrnrZ: %lg\n", BlkCrnrZ[thisBlock]);
3610 printf("delX, delY, delZ: %le, %le, %le\n", delX, delY, delZ);
3611 printf("dz: %lg\n", dz);
3612 fflush(stdout);
3613 }
3614
3615 // Find cell in block of basic / staggered volume within which the point lies
3616 int celli = (int)(dx / delX) + 1; // Find cell in which the point lies
3617 if (celli < 1) {
3618 celli = 1;
3619 dx = 0.5 * delX;
3620 neBEMMessage("FastKnChPFAtPoint - celli < 1\n");
3621 }
3622 if (celli > nbXCells) {
3623 celli = nbXCells;
3624 dx = FastVol.LX - 0.5 * delX;
3625 neBEMMessage("FastKnChPFAtPoint - celli > nbXCells\n");
3626 }
3627 int cellj = (int)(dy / delY) + 1;
3628 if (cellj < 1) {
3629 cellj = 1;
3630 dy = 0.5 * delY;
3631 neBEMMessage("FastKnChPFAtPoint - cellj < 1\n");
3632 }
3633 if (cellj > nbYCells) {
3634 cellj = nbYCells;
3635 dy = FastVol.LY - 0.5 * delY;
3636 neBEMMessage("FastKnChPFAtPoint - cellj > nbYCells\n");
3637 }
3638 int cellk = (int)(dz / delZ) + 1;
3639 if (cellk < 1) {
3640 cellk = 1;
3641 dz = 0.5 * delX;
3642 neBEMMessage("FastKnChPFAtPoint - cellk < 1\n");
3643 }
3644 if (cellk > nbZCells) {
3645 cellk = nbZCells;
3646 dz = FastVol.LZ - 0.5 * delZ;
3647 neBEMMessage("FastKnChPFAtPoint - cellk > nbZCells\n");
3648 }
3649 if (dbgFn) printf("Cells in x, y, z: %d, %d, %d\n", celli, cellj, cellk);
3650
3651 // Interpolate potential and field at the point using the corner values of
3652 // of the cell and, if necessary, of the neighbouring cells
3653 // These gradients can also be calculated while computing the potential and
3654 // field at the cells and stored in memory, provided enough memory is
3655 // available
3656
3657 // distances from cell corner
3658 double dxcellcrnr = dx - (double)(celli - 1) * delX;
3659 double dycellcrnr = dy - (double)(cellj - 1) * delY;
3660 double dzcellcrnr = dz - (double)(cellk - 1) * delZ;
3661 if (dbgFn)
3662 printf("cell crnr dx, dy, dz: %g, %g, %g\n", dxcellcrnr, dycellcrnr,
3663 dzcellcrnr);
3664
3665 // normalized distances
3666 double xd = dxcellcrnr / delX; // xd = (x-x0)/(x1-x0)
3667 double yd = dycellcrnr / delY; // etc
3668 double zd = dzcellcrnr / delZ;
3669 if (xd <= 0.0) xd = 0.0;
3670 if (yd <= 0.0) yd = 0.0;
3671 if (zd <= 0.0) zd = 0.0;
3672 if (xd >= 1.0) xd = 1.0;
3673 if (yd >= 1.0) yd = 1.0;
3674 if (zd >= 1.0) zd = 1.0;
3675
3676 // corner values of potential and field
3677 double P000 = FastPotKnCh[thisBlock][celli][cellj][cellk]; // lowest corner
3678 double FX000 = FastFXKnCh[thisBlock][celli][cellj][cellk];
3679 double FY000 = FastFYKnCh[thisBlock][celli][cellj][cellk];
3680 double FZ000 = FastFZKnCh[thisBlock][celli][cellj][cellk];
3681 double P100 = FastPotKnCh[thisBlock][celli + 1][cellj][cellk];
3682 double FX100 = FastFXKnCh[thisBlock][celli + 1][cellj][cellk];
3683 double FY100 = FastFYKnCh[thisBlock][celli + 1][cellj][cellk];
3684 double FZ100 = FastFZKnCh[thisBlock][celli + 1][cellj][cellk];
3685 double P010 = FastPotKnCh[thisBlock][celli][cellj + 1][cellk];
3686 double FX010 = FastFXKnCh[thisBlock][celli][cellj + 1][cellk];
3687 double FY010 = FastFYKnCh[thisBlock][celli][cellj + 1][cellk];
3688 double FZ010 = FastFZKnCh[thisBlock][celli][cellj + 1][cellk];
3689 double P001 = FastPotKnCh[thisBlock][celli][cellj][cellk + 1];
3690 double FX001 = FastFXKnCh[thisBlock][celli][cellj][cellk + 1];
3691 double FY001 = FastFYKnCh[thisBlock][celli][cellj][cellk + 1];
3692 double FZ001 = FastFZKnCh[thisBlock][celli][cellj][cellk + 1];
3693 double P110 = FastPotKnCh[thisBlock][celli + 1][cellj + 1][cellk];
3694 double FX110 = FastFXKnCh[thisBlock][celli + 1][cellj + 1][cellk];
3695 double FY110 = FastFYKnCh[thisBlock][celli + 1][cellj + 1][cellk];
3696 double FZ110 = FastFZKnCh[thisBlock][celli + 1][cellj + 1][cellk];
3697 double P101 = FastPotKnCh[thisBlock][celli + 1][cellj][cellk + 1];
3698 double FX101 = FastFXKnCh[thisBlock][celli + 1][cellj][cellk + 1];
3699 double FY101 = FastFYKnCh[thisBlock][celli + 1][cellj][cellk + 1];
3700 double FZ101 = FastFZKnCh[thisBlock][celli + 1][cellj][cellk + 1];
3701 double P011 = FastPotKnCh[thisBlock][celli][cellj + 1][cellk + 1];
3702 double FX011 = FastFXKnCh[thisBlock][celli][cellj + 1][cellk + 1];
3703 double FY011 = FastFYKnCh[thisBlock][celli][cellj + 1][cellk + 1];
3704 double FZ011 = FastFZKnCh[thisBlock][celli][cellj + 1][cellk + 1];
3705 double P111 = FastPotKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
3706 double FX111 = FastFXKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
3707 double FY111 = FastFYKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
3708 double FZ111 = FastFZKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
3709 if (OptStaggerFastVol) {
3710 if (sector == 1) { // nothing to be done
3711 }
3712 if (sector == 2) { // volume shifted up but point not in the staggered part
3713 }
3714 if (sector == 3) { // staggered volume
3715 P000 = FastStgPotKnCh[thisBlock][celli][cellj][cellk];
3716 FX000 = FastStgFXKnCh[thisBlock][celli][cellj][cellk];
3717 FY000 = FastStgFYKnCh[thisBlock][celli][cellj][cellk];
3718 FZ000 = FastStgFZKnCh[thisBlock][celli][cellj][cellk];
3719 P100 = FastStgPotKnCh[thisBlock][celli + 1][cellj][cellk];
3720 FX100 = FastStgFXKnCh[thisBlock][celli + 1][cellj][cellk];
3721 FY100 = FastStgFYKnCh[thisBlock][celli + 1][cellj][cellk];
3722 FZ100 = FastStgFZKnCh[thisBlock][celli + 1][cellj][cellk];
3723 P010 = FastStgPotKnCh[thisBlock][celli][cellj + 1][cellk];
3724 FX010 = FastStgFXKnCh[thisBlock][celli][cellj + 1][cellk];
3725 FY010 = FastStgFYKnCh[thisBlock][celli][cellj + 1][cellk];
3726 FZ010 = FastStgFZKnCh[thisBlock][celli][cellj + 1][cellk];
3727 P001 = FastStgPotKnCh[thisBlock][celli][cellj][cellk + 1];
3728 FX001 = FastStgFXKnCh[thisBlock][celli][cellj][cellk + 1];
3729 FY001 = FastStgFYKnCh[thisBlock][celli][cellj][cellk + 1];
3730 FZ001 = FastStgFZKnCh[thisBlock][celli][cellj][cellk + 1];
3731 P110 = FastStgPotKnCh[thisBlock][celli + 1][cellj + 1][cellk];
3732 FX110 = FastStgFXKnCh[thisBlock][celli + 1][cellj + 1][cellk];
3733 FY110 = FastStgFYKnCh[thisBlock][celli + 1][cellj + 1][cellk];
3734 FZ110 = FastStgFZKnCh[thisBlock][celli + 1][cellj + 1][cellk];
3735 P101 = FastStgPotKnCh[thisBlock][celli + 1][cellj][cellk + 1];
3736 FX101 = FastStgFXKnCh[thisBlock][celli + 1][cellj][cellk + 1];
3737 FY101 = FastStgFYKnCh[thisBlock][celli + 1][cellj][cellk + 1];
3738 FZ101 = FastStgFZKnCh[thisBlock][celli + 1][cellj][cellk + 1];
3739 P011 = FastStgPotKnCh[thisBlock][celli][cellj + 1][cellk + 1];
3740 FX011 = FastStgFXKnCh[thisBlock][celli][cellj + 1][cellk + 1];
3741 FY011 = FastStgFYKnCh[thisBlock][celli][cellj + 1][cellk + 1];
3742 FZ011 = FastStgFZKnCh[thisBlock][celli][cellj + 1][cellk + 1];
3743 P111 = FastStgPotKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
3744 FX111 = FastStgFXKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
3745 FY111 = FastStgFYKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
3746 FZ111 = FastStgFZKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
3747 }
3748 if (sector == 4) { // volume shifted down and point in the staggered part
3749 P000 = FastStgPotKnCh[thisBlock][celli][cellj][cellk];
3750 FX000 = FastStgFXKnCh[thisBlock][celli][cellj][cellk];
3751 FY000 = FastStgFYKnCh[thisBlock][celli][cellj][cellk];
3752 FZ000 = FastStgFZKnCh[thisBlock][celli][cellj][cellk];
3753 P100 = FastStgPotKnCh[thisBlock][celli + 1][cellj][cellk];
3754 FX100 = FastStgFXKnCh[thisBlock][celli + 1][cellj][cellk];
3755 FY100 = FastStgFYKnCh[thisBlock][celli + 1][cellj][cellk];
3756 FZ100 = FastStgFZKnCh[thisBlock][celli + 1][cellj][cellk];
3757 P010 = FastStgPotKnCh[thisBlock][celli][cellj + 1][cellk];
3758 FX010 = FastStgFXKnCh[thisBlock][celli][cellj + 1][cellk];
3759 FY010 = FastStgFYKnCh[thisBlock][celli][cellj + 1][cellk];
3760 FZ010 = FastStgFZKnCh[thisBlock][celli][cellj + 1][cellk];
3761 P001 = FastStgPotKnCh[thisBlock][celli][cellj][cellk + 1];
3762 FX001 = FastStgFXKnCh[thisBlock][celli][cellj][cellk + 1];
3763 FY001 = FastStgFYKnCh[thisBlock][celli][cellj][cellk + 1];
3764 FZ001 = FastStgFZKnCh[thisBlock][celli][cellj][cellk + 1];
3765 P110 = FastStgPotKnCh[thisBlock][celli + 1][cellj + 1][cellk];
3766 FX110 = FastStgFXKnCh[thisBlock][celli + 1][cellj + 1][cellk];
3767 FY110 = FastStgFYKnCh[thisBlock][celli + 1][cellj + 1][cellk];
3768 FZ110 = FastStgFZKnCh[thisBlock][celli + 1][cellj + 1][cellk];
3769 P101 = FastStgPotKnCh[thisBlock][celli + 1][cellj][cellk + 1];
3770 FX101 = FastStgFXKnCh[thisBlock][celli + 1][cellj][cellk + 1];
3771 FY101 = FastStgFYKnCh[thisBlock][celli + 1][cellj][cellk + 1];
3772 FZ101 = FastStgFZKnCh[thisBlock][celli + 1][cellj][cellk + 1];
3773 P011 = FastStgPotKnCh[thisBlock][celli][cellj + 1][cellk + 1];
3774 FX011 = FastStgFXKnCh[thisBlock][celli][cellj + 1][cellk + 1];
3775 FY011 = FastStgFYKnCh[thisBlock][celli][cellj + 1][cellk + 1];
3776 FZ011 = FastStgFZKnCh[thisBlock][celli][cellj + 1][cellk + 1];
3777 P111 = FastStgPotKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
3778 FX111 = FastStgFXKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
3779 FY111 = FastStgFYKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
3780 FZ111 = FastStgFZKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
3781 }
3782 } // if OptStaggerFastVol
3783
3784 double intP =
3785 TriLin(xd, yd, zd, P000, P100, P010, P001, P110, P101, P011, P111);
3786 double intFX = TriLin(xd, yd, zd, FX000, FX100, FX010, FX001, FX110, FX101,
3787 FX011, FX111);
3788 double intFY = TriLin(xd, yd, zd, FY000, FY100, FY010, FY001, FY110, FY101,
3789 FY011, FY111);
3790 double intFZ = TriLin(xd, yd, zd, FZ000, FZ100, FZ010, FZ001, FZ110, FZ101,
3791 FZ011, FZ111);
3792
3793 *Potential = intP;
3794 globalF->X = intFX;
3795 globalF->Y = intFY;
3796 globalF->Z = intFZ;
3797
3798 if (dbgFn) {
3799 printf("Cell corner values:\n");
3800 printf("Potential: %g, %g, %g, %g\n", P000, P100, P010, P001);
3801 printf("Potential: %g, %g, %g, %g\n", P110, P101, P011, P111);
3802 printf("FastFX: %g, %g, %g, %g\n", FX000, FX100, FX010, FX001);
3803 printf("FastFX: %g, %g, %g, %g\n", FX110, FX101, FX011, FX111);
3804 printf("FastFY: %g, %g, %g, %g\n", FY000, FY100, FY010, FY001);
3805 printf("FastFY: %g, %g, %g, %g\n", FY110, FY101, FY011, FY111);
3806 printf("FastFZ: %g, %g, %g, %g\n", FZ000, FZ100, FZ010, FZ001);
3807 printf("FastFZ: %g, %g, %g, %g\n", FZ110, FZ101, FZ011, FZ111);
3808 printf("Pot, FX, FY, FZ: %g, %g, %g, %g\n", *Potential, globalF->X,
3809 globalF->Y, globalF->Z);
3810 }
3811
3812 if (dbgFn) {
3813 printf("out FastKnChPFAtPoint\n");
3814 fflush(stdout);
3815 }
3816
3817 return 0;
3818} // FastKnChPFAtPoint ends
int KnChPFAtPoint(Point3D *globalP, double *Potential, Vector3D *globalF)
double TriLin(double xd, double yd, double zd, double c000, double c100, double c010, double c001, double c110, double c101, double c011, double c111)
neBEMGLOBAL int OptStaggerFastVol
Definition: neBEM.h:404
neBEMGLOBAL double **** FastStgFXKnCh
Definition: neBEM.h:450
neBEMGLOBAL double **** FastFYKnCh
Definition: neBEM.h:448
neBEMGLOBAL double * BlkCrnrZ
Definition: neBEM.h:428
neBEMGLOBAL FastAlgoVol FastVol
Definition: neBEM.h:422
neBEMGLOBAL double * BlkLZ
Definition: neBEM.h:427
neBEMGLOBAL double * IgnoreVolCrnrY
Definition: neBEM.h:439
neBEMGLOBAL int * BlkNbXCells
Definition: neBEM.h:424
neBEMGLOBAL int * BlkNbZCells
Definition: neBEM.h:426
neBEMGLOBAL double * IgnoreVolLY
Definition: neBEM.h:436
neBEMGLOBAL double * IgnoreVolLX
Definition: neBEM.h:435
neBEMGLOBAL double **** FastFXKnCh
Definition: neBEM.h:448
neBEMGLOBAL double * IgnoreVolLZ
Definition: neBEM.h:437
neBEMGLOBAL double **** FastFZKnCh
Definition: neBEM.h:448
neBEMGLOBAL double **** FastStgFYKnCh
Definition: neBEM.h:450
neBEMGLOBAL double **** FastPotKnCh
Definition: neBEM.h:447
neBEMGLOBAL double * IgnoreVolCrnrX
Definition: neBEM.h:438
neBEMGLOBAL double **** FastStgPotKnCh
Definition: neBEM.h:449
neBEMGLOBAL double **** FastStgFZKnCh
Definition: neBEM.h:450
neBEMGLOBAL double * IgnoreVolCrnrZ
Definition: neBEM.h:440
neBEMGLOBAL int * BlkNbYCells
Definition: neBEM.h:425
double CrnrX
Definition: neBEM.h:414
int NbBlocks
Definition: neBEM.h:418
double CrnrZ
Definition: neBEM.h:416
double CrnrY
Definition: neBEM.h:415
double LZ
Definition: neBEM.h:413
int NbIgnoreVols
Definition: neBEM.h:420
double YStagger
Definition: neBEM.h:417
double LY
Definition: neBEM.h:412
double LX
Definition: neBEM.h:411

◆ FastPFAtPoint()

neBEMGLOBAL int FastPFAtPoint ( Point3D globalPt,
double *  Pot,
Vector3D Flux 
)

Definition at line 2821 of file ComputeProperties.c.

2821 {
2822 int dbgFn = 0;
2823 double Xpt = globalP->X;
2824 double Ypt = globalP->Y;
2825 double Zpt = globalP->Z;
2826 double RptVolLX = FastVol.LX;
2827 double RptVolLY = FastVol.LY;
2828 double RptVolLZ = FastVol.LZ;
2829 double CornerX = FastVol.CrnrX;
2830 double CornerY = FastVol.CrnrY;
2831 double CornerZ = FastVol.CrnrZ;
2832 double TriLin(double xd, double yd, double zd, double c000, double c100,
2833 double c010, double c001, double c110, double c101, double c011,
2834 double c111);
2835
2836 // First of all, check how the point in question should be treated ...
2837
2838 // Check whether the point falls within a volume that is not regarded as
2839 // FastVol
2840 for (int ignore = 1; ignore <= FastVol.NbIgnoreVols; ++ignore) {
2841 if ((Xpt >= (IgnoreVolCrnrX[ignore])) &&
2842 (Xpt <= (IgnoreVolCrnrX[ignore] + IgnoreVolLX[ignore])) &&
2843 (Ypt >= (IgnoreVolCrnrY[ignore])) &&
2844 (Ypt <= (IgnoreVolCrnrY[ignore] + IgnoreVolLY[ignore])) &&
2845 (Zpt >= (IgnoreVolCrnrZ[ignore])) &&
2846 (Zpt <= (IgnoreVolCrnrZ[ignore] + IgnoreVolLZ[ignore]))) {
2847 if (dbgFn)
2848 neBEMMessage("In FastPFAtPoint: point in an ignored volume!\n");
2849
2850 int fstatus = PFAtPoint(globalP, Potential, globalF);
2851 if (fstatus != 0) {
2852 neBEMMessage("wrong PFAtPoint return value in FastVolPF.\n");
2853 return -1;
2854 } else
2855 return 0;
2856 }
2857 } // loop over ignored volumes
2858
2859 // If not ignored, the point qualifies for FastVol evaluation ...
2860
2861 // for a staggered fast volume, the volume repeated in X is larger
2862 if (OptStaggerFastVol) {
2863 RptVolLX += FastVol.LX;
2864 }
2865 if (dbgFn) {
2866 printf("\nin FastPFAtPoint\n");
2867 printf("x, y, z: %g, %g, %g\n", Xpt, Ypt, Zpt);
2868 printf("RptVolLX, RptVolLY, RptVolLZ: %g, %g, %g\n", RptVolLX, RptVolLY,
2869 RptVolLZ);
2870 printf("CornerX, CornerY, CornerZ: %g, %g, %g\n", CornerX, CornerY,
2871 CornerZ);
2872 printf("Nb of blocks: %d\n", FastVol.NbBlocks);
2873 for (int block = 1; block <= FastVol.NbBlocks; ++block) {
2874 printf("NbOfXCells: %d\n", BlkNbXCells[block]);
2875 printf("NbOfYCells: %d\n", BlkNbYCells[block]);
2876 printf("NbOfZCells: %d\n", BlkNbZCells[block]);
2877 printf("LZ: %le\n", BlkLZ[block]);
2878 printf("CornerZ: %le\n", BlkCrnrZ[block]);
2879 }
2880 }
2881
2882 // Find equivalent position inside the basic / staggered volume.
2883 // real distance from volume corner
2884 double dx = Xpt - CornerX;
2885 double dy = Ypt - CornerY;
2886 double dz = Zpt - CornerZ;
2887 if (dbgFn)
2888 printf("real dx, dy, dz from volume corner: %g, %g, %g\n", dx, dy, dz);
2889
2890 int NbFastVolX = (int)(dx / RptVolLX);
2891 if (dx < 0.0) --NbFastVolX;
2892 int NbFastVolY = (int)(dy / RptVolLY);
2893 if (dy < 0.0) --NbFastVolY;
2894 int NbFastVolZ = (int)(dz / RptVolLZ);
2895 if (dz < 0.0) --NbFastVolZ;
2896 if (dbgFn)
2897 printf("Volumes in x, y, z: %d, %d, %d\n", NbFastVolX, NbFastVolY,
2898 NbFastVolZ);
2899
2900 // equivalent distances from fast volume corner
2901 dx -= NbFastVolX * RptVolLX;
2902 dy -= NbFastVolY * RptVolLY;
2903 dz -= NbFastVolZ * RptVolLZ;
2904 // The following conditions should never happen - generate an error message
2905 if (dx < 0.0) {
2906 dx = 0.0;
2907 neBEMMessage("equiv dx < 0.0 - not correct!\n");
2908 }
2909 if (dy < 0.0) {
2910 dy = 0.0;
2911 neBEMMessage("equiv dy < 0.0 - not correct!\n");
2912 }
2913 if (dz < 0.0) {
2914 dz = 0.0;
2915 neBEMMessage("equiv dz < 0.0 - not correct!\n");
2916 }
2917 if (dx > RptVolLX) {
2918 dx = RptVolLX;
2919 neBEMMessage("equiv dx > RptVolLX - not correct!\n");
2920 }
2921 if (dy > RptVolLY) {
2922 dy = RptVolLY;
2923 neBEMMessage("equiv dy > RptVolLY - not correct!\n");
2924 }
2925 if (dz > RptVolLZ) {
2926 dz = RptVolLZ;
2927 neBEMMessage("equiv dz > RptVolLZ - not correct!\n");
2928 }
2929 if (dbgFn)
2930 printf("equivalent dist from corner - dx, dy, dz: %g, %g, %g\n", dx, dy,
2931 dz);
2932
2933 // Take care of possible trouble-makers
2934 if (dx < MINDIST) dx = MINDIST; // -ve dx has already been made equal to 0
2935 if (dy < MINDIST) dy = MINDIST;
2936 if (dz < MINDIST) dz = MINDIST;
2937 if ((RptVolLX - dx) < MINDIST)
2938 dx = RptVolLX - MINDIST; // dx > RptVolLX taken care of
2939 if ((RptVolLY - dy) < MINDIST) dy = RptVolLY - MINDIST;
2940 if ((RptVolLZ - dz) < MINDIST) dz = RptVolLZ - MINDIST;
2941 // For staggered volumes, there is another plane where difficulties may occur
2942 if ((dx <= FastVol.LX) && (FastVol.LX - dx) < MINDIST)
2943 dx = FastVol.LX - MINDIST;
2944 // else if((dx > FastVol.LX) && (fabs(FastVol.LX-dx) < MINDIST))
2945 else if ((dx > FastVol.LX) && (dx - FastVol.LX) < MINDIST) // more inttuitive
2946 dx = FastVol.LX + MINDIST;
2947 if (dbgFn)
2948 printf("equivalent dist adjusted - dx, dy, dz: %g, %g, %g\n", dx, dy, dz);
2949
2950 // If volume is staggered, we have a few more things to do before finalizing
2951 // the values of equivalent distance
2952 // sector identification
2953 // _................__________________
2954 // | . . | Sector 3 |
2955 // | . . | |
2956 // | . | . |
2957 // | | . . |
2958 // | Sector 2 | . . |
2959 // |----------------| . . |
2960 // | | . |
2961 // | . | |
2962 // | . . | |
2963 // | . . |----------------|
2964 // | . . | Sector 4 |
2965 // | . | . |
2966 // | | . . |
2967 // | Sector 1 | . . |
2968 // |----------------|................|
2969
2970 int sector = 1; // kept outside `if' since this is necessary further below
2971 if (OptStaggerFastVol) {
2972 if ((dx >= 0.0) && (dx <= FastVol.LX) && (dy >= 0.0) &&
2973 (dy <= FastVol.LY)) {
2974 // point lies in sector 1, everything remains unchanged
2975 sector = 1;
2976 } else if ((dx >= 0.0) && (dx <= FastVol.LX) && (dy > FastVol.LY) &&
2977 (dy <= FastVol.LY + FastVol.YStagger)) {
2978 // point lies in sector 2, move basic volume one step up
2979 sector = 2;
2980 ++NbFastVolY;
2981 CornerY += FastVol.LY; // repeat length in Y is LY
2982 dy -= FastVol.LY;
2983 } else if ((dx > FastVol.LX) && (dx <= 2.0 * FastVol.LX) &&
2984 (dy >= FastVol.YStagger) &&
2985 (dy <= FastVol.LY + FastVol.YStagger)) {
2986 // point lies in sector 3, pt in staggered vol, change corner coords
2987 sector = 3;
2988 CornerX += FastVol.LX;
2989 CornerY += FastVol.YStagger;
2990 dx -= FastVol.LX;
2991 dy -= FastVol.YStagger;
2992 } else if ((dx > FastVol.LX) && (dx <= 2.0 * FastVol.LX) && (dy >= 0.0) &&
2993 (dy < FastVol.YStagger)) {
2994 // point lies in sector 4, move basic volume one step down and consider
2995 // staggered fast volume
2996 sector = 4;
2997 --NbFastVolY;
2998 CornerX += FastVol.LX; // in the staggered part of the repeated volume
2999 CornerY -= (FastVol.LY - FastVol.YStagger);
3000 dx -= FastVol.LX;
3001 dy += (FastVol.LY - FastVol.YStagger);
3002 } else {
3003 neBEMMessage("FastPFAtPoint: point in none of the sectors!\n");
3004 }
3005 if (dbgFn) printf("stagger modified dx, dy, dz: %g, %g, %g\n", dx, dy, dz);
3006 }
3007
3008 // Take care of possible trouble-makers - once more
3009 if (dx < MINDIST) dx = MINDIST; // -ve dx has already been made equal to 0
3010 if (dy < MINDIST) dy = MINDIST;
3011 if (dz < MINDIST) dz = MINDIST;
3012 if ((RptVolLX - dx) < MINDIST)
3013 dx = RptVolLX - MINDIST; // dx > RptVolLX taken care of
3014 if ((RptVolLY - dy) < MINDIST) dy = RptVolLY - MINDIST;
3015 if ((RptVolLZ - dz) < MINDIST) dz = RptVolLZ - MINDIST;
3016 // For staggered volumes, there is another plane where difficulties may occur
3017 if ((dx <= FastVol.LX) && (FastVol.LX - dx) < MINDIST)
3018 dx = FastVol.LX - MINDIST;
3019 // else if((dx > FastVol.LX) && (fabs(FastVol.LX-dx) < MINDIST))
3020 else if ((dx > FastVol.LX) && (dx - FastVol.LX) < MINDIST) // more intuitive
3021 dx = FastVol.LX + MINDIST;
3022 if (dbgFn)
3023 printf("equivalent dist adjusted for staggered: %g, %g, %g\n", dx, dy, dz);
3024
3025 /*
3026 // Check whether the point falls within a volume that is omitted
3027 for(int omit = 1; omit <= FastVol.NbOmitVols; ++omit)
3028 {
3029 if((dx >= (OmitVolCrnrX[omit]-FastVol.CrnrX))
3030 && (dx <=
3031 (OmitVolCrnrX[omit]+OmitVolLX[omit]-FastVol.CrnrX))
3032 && (dy >= (OmitVolCrnrY[omit]-FastVol.CrnrY))
3033 && (dy <=
3034 (OmitVolCrnrY[omit]+OmitVolLY[omit]-FastVol.CrnrY))
3035 && (dz >= (OmitVolCrnrZ[omit]-FastVol.CrnrZ))
3036 && (dz <=
3037 (OmitVolCrnrZ[omit]+OmitVolLZ[omit]-FastVol.CrnrZ)))
3038 {
3039 neBEMMessage("In FastPFAtPoint: point in an omitted
3040 volume!\n"); *Potential = 0.0; globalF->X = 0.0; globalF->Y = 0.0; globalF->Z
3041 = 0.0;
3042 }
3043 } // loop over omitted volumes
3044 */
3045
3046 // Find the block in which the point lies
3047 /*
3048 int thisBlock = 1;
3049 if(FastVol.NbBlocks > 1)
3050 {
3051 for(int block = 1; block <= FastVol.NbBlocks; ++block)
3052 {
3053 if(dbgFn)
3054 {
3055 printf("dz,(BlkCrnrZ-CornerZ),(BlkCrnrZ+BlkLZ-CornerZ):
3056 %lg, %lg, %lg\n", dz, (BlkCrnrZ[block]-CornerZ),
3057 (BlkCrnrZ[block]+BlkLZ[block]-CornerZ));
3058 }
3059 if((dz >= (BlkCrnrZ[block]-CornerZ))
3060 && (dz <=
3061 (BlkCrnrZ[block]+BlkLZ[block]-CornerZ)))
3062 {
3063 thisBlock = block;
3064 break;
3065 }
3066 }
3067 } // if NbBlocks > 1
3068 */
3069
3070 int thisBlock = 0;
3071 for (int block = 1; block <= FastVol.NbBlocks; ++block) {
3072 double blkBtmZ = BlkCrnrZ[block] - CornerZ; // since CornerZ has been
3073 double blkTopZ = blkBtmZ + BlkLZ[block]; // subtracted from dz already
3074 if (dbgFn) {
3075 printf("block, dz, blkBtmZ, blkTopZ: %d, %lg, %lg, %lg\n", block, dz,
3076 blkBtmZ, blkTopZ);
3077 }
3078
3079 // take care of difficult situations
3080 if ((dz <= blkBtmZ) && ((blkBtmZ - dz) < MINDIST)) dz = blkBtmZ - MINDIST;
3081 if ((dz >= blkBtmZ) && ((dz - blkBtmZ) < MINDIST)) dz = blkBtmZ + MINDIST;
3082 if ((dz <= blkTopZ) && ((blkTopZ - dz) < MINDIST)) dz = blkTopZ - MINDIST;
3083 if ((dz >= blkTopZ) && ((dz - blkTopZ) < MINDIST)) dz = blkTopZ + MINDIST;
3084
3085 if ((dz >= blkBtmZ) && (dz <= blkTopZ)) {
3086 thisBlock = block;
3087 break;
3088 }
3089 }
3090 if (!thisBlock) {
3091 neBEMMessage("FastPFAtPoint: point in none of the blocks!\n");
3092 }
3093
3094 int nbXCells = BlkNbXCells[thisBlock];
3095 int nbYCells = BlkNbYCells[thisBlock];
3096 int nbZCells = BlkNbZCells[thisBlock];
3097 double delX = FastVol.LX / nbXCells;
3098 double delY = FastVol.LY / nbYCells;
3099 double delZ = BlkLZ[thisBlock] / nbZCells;
3100 dz -= (BlkCrnrZ[thisBlock] - CornerZ); // distance from the block corner
3101
3102 if (dbgFn) {
3103 printf("thisBlock: %d\n", thisBlock);
3104 printf("nbXCells, nbYCells, nbZCells: %d, %d, %d\n", nbXCells, nbYCells,
3105 nbZCells);
3106 printf("BlkCrnrZ: %lg\n", BlkCrnrZ[thisBlock]);
3107 printf("delX, delY, delZ: %le, %le, %le\n", delX, delY, delZ);
3108 printf("dz: %lg\n", dz);
3109 fflush(stdout);
3110 }
3111
3112 // Find cell in block of basic / staggered volume within which the point lies
3113 int celli = (int)(dx / delX) + 1; // Find cell in which the point lies
3114 if (celli < 1) {
3115 celli = 1;
3116 dx = 0.5 * delX;
3117 neBEMMessage("FastPFAtPoint - celli < 1\n");
3118 }
3119 if (celli > nbXCells) {
3120 celli = nbXCells;
3121 dx = FastVol.LX - 0.5 * delX;
3122 neBEMMessage("FastPFAtPoint - celli > nbXCells\n");
3123 }
3124 int cellj = (int)(dy / delY) + 1;
3125 if (cellj < 1) {
3126 cellj = 1;
3127 dy = 0.5 * delY;
3128 neBEMMessage("FastPFAtPoint - cellj < 1\n");
3129 }
3130 if (cellj > nbYCells) {
3131 cellj = nbYCells;
3132 dy = FastVol.LY - 0.5 * delY;
3133 neBEMMessage("FastPFAtPoint - cellj > nbYCells\n");
3134 }
3135 int cellk = (int)(dz / delZ) + 1;
3136 if (cellk < 1) {
3137 cellk = 1;
3138 dz = 0.5 * delX;
3139 neBEMMessage("FastPFAtPoint - cellk < 1\n");
3140 }
3141 if (cellk > nbZCells) {
3142 cellk = nbZCells;
3143 dz = FastVol.LZ - 0.5 * delZ;
3144 neBEMMessage("FastPFAtPoint - cellk > nbZCells\n");
3145 }
3146 if (dbgFn) printf("Cells in x, y, z: %d, %d, %d\n", celli, cellj, cellk);
3147
3148 // Interpolate potential and field at the point using the corner values of
3149 // of the cell and, if necessary, of the neighbouring cells
3150 // These gradients can also be calculated while computing the potential and
3151 // field at the cells and stored in memory, provided enough memory is
3152 // available
3153
3154 // distances from cell corner
3155 double dxcellcrnr = dx - (double)(celli - 1) * delX;
3156 double dycellcrnr = dy - (double)(cellj - 1) * delY;
3157 double dzcellcrnr = dz - (double)(cellk - 1) * delZ;
3158 if (dbgFn)
3159 printf("cell crnr dx, dy, dz: %g, %g, %g\n", dxcellcrnr, dycellcrnr,
3160 dzcellcrnr);
3161
3162 // normalized distances
3163 double xd = dxcellcrnr / delX; // xd = (x-x0)/(x1-x0)
3164 double yd = dycellcrnr / delY; // etc
3165 double zd = dzcellcrnr / delZ;
3166 if (xd <= 0.0) xd = 0.0;
3167 if (yd <= 0.0) yd = 0.0;
3168 if (zd <= 0.0) zd = 0.0;
3169 if (xd >= 1.0) xd = 1.0;
3170 if (yd >= 1.0) yd = 1.0;
3171 if (zd >= 1.0) zd = 1.0;
3172
3173 // corner values of potential and field
3174 double P000 = FastPot[thisBlock][celli][cellj][cellk]; // lowest corner
3175 double FX000 = FastFX[thisBlock][celli][cellj][cellk];
3176 double FY000 = FastFY[thisBlock][celli][cellj][cellk];
3177 double FZ000 = FastFZ[thisBlock][celli][cellj][cellk];
3178 double P100 = FastPot[thisBlock][celli + 1][cellj][cellk];
3179 double FX100 = FastFX[thisBlock][celli + 1][cellj][cellk];
3180 double FY100 = FastFY[thisBlock][celli + 1][cellj][cellk];
3181 double FZ100 = FastFZ[thisBlock][celli + 1][cellj][cellk];
3182 double P010 = FastPot[thisBlock][celli][cellj + 1][cellk];
3183 double FX010 = FastFX[thisBlock][celli][cellj + 1][cellk];
3184 double FY010 = FastFY[thisBlock][celli][cellj + 1][cellk];
3185 double FZ010 = FastFZ[thisBlock][celli][cellj + 1][cellk];
3186 double P001 = FastPot[thisBlock][celli][cellj][cellk + 1];
3187 double FX001 = FastFX[thisBlock][celli][cellj][cellk + 1];
3188 double FY001 = FastFY[thisBlock][celli][cellj][cellk + 1];
3189 double FZ001 = FastFZ[thisBlock][celli][cellj][cellk + 1];
3190 double P110 = FastPot[thisBlock][celli + 1][cellj + 1][cellk];
3191 double FX110 = FastFX[thisBlock][celli + 1][cellj + 1][cellk];
3192 double FY110 = FastFY[thisBlock][celli + 1][cellj + 1][cellk];
3193 double FZ110 = FastFZ[thisBlock][celli + 1][cellj + 1][cellk];
3194 double P101 = FastPot[thisBlock][celli + 1][cellj][cellk + 1];
3195 double FX101 = FastFX[thisBlock][celli + 1][cellj][cellk + 1];
3196 double FY101 = FastFY[thisBlock][celli + 1][cellj][cellk + 1];
3197 double FZ101 = FastFZ[thisBlock][celli + 1][cellj][cellk + 1];
3198 double P011 = FastPot[thisBlock][celli][cellj + 1][cellk + 1];
3199 double FX011 = FastFX[thisBlock][celli][cellj + 1][cellk + 1];
3200 double FY011 = FastFY[thisBlock][celli][cellj + 1][cellk + 1];
3201 double FZ011 = FastFZ[thisBlock][celli][cellj + 1][cellk + 1];
3202 double P111 = FastPot[thisBlock][celli + 1][cellj + 1][cellk + 1];
3203 double FX111 = FastFX[thisBlock][celli + 1][cellj + 1][cellk + 1];
3204 double FY111 = FastFY[thisBlock][celli + 1][cellj + 1][cellk + 1];
3205 double FZ111 = FastFZ[thisBlock][celli + 1][cellj + 1][cellk + 1];
3206 if (OptStaggerFastVol) {
3207 if (sector == 1) { // nothing to be done
3208 }
3209 if (sector == 2) { // volume shifted up but point not in the staggered part
3210 }
3211 if (sector == 3) { // staggered volume
3212 P000 = FastStgPot[thisBlock][celli][cellj][cellk];
3213 FX000 = FastStgFX[thisBlock][celli][cellj][cellk];
3214 FY000 = FastStgFY[thisBlock][celli][cellj][cellk];
3215 FZ000 = FastStgFZ[thisBlock][celli][cellj][cellk];
3216 P100 = FastStgPot[thisBlock][celli + 1][cellj][cellk];
3217 FX100 = FastStgFX[thisBlock][celli + 1][cellj][cellk];
3218 FY100 = FastStgFY[thisBlock][celli + 1][cellj][cellk];
3219 FZ100 = FastStgFZ[thisBlock][celli + 1][cellj][cellk];
3220 P010 = FastStgPot[thisBlock][celli][cellj + 1][cellk];
3221 FX010 = FastStgFX[thisBlock][celli][cellj + 1][cellk];
3222 FY010 = FastStgFY[thisBlock][celli][cellj + 1][cellk];
3223 FZ010 = FastStgFZ[thisBlock][celli][cellj + 1][cellk];
3224 P001 = FastStgPot[thisBlock][celli][cellj][cellk + 1];
3225 FX001 = FastStgFX[thisBlock][celli][cellj][cellk + 1];
3226 FY001 = FastStgFY[thisBlock][celli][cellj][cellk + 1];
3227 FZ001 = FastStgFZ[thisBlock][celli][cellj][cellk + 1];
3228 P110 = FastStgPot[thisBlock][celli + 1][cellj + 1][cellk];
3229 FX110 = FastStgFX[thisBlock][celli + 1][cellj + 1][cellk];
3230 FY110 = FastStgFY[thisBlock][celli + 1][cellj + 1][cellk];
3231 FZ110 = FastStgFZ[thisBlock][celli + 1][cellj + 1][cellk];
3232 P101 = FastStgPot[thisBlock][celli + 1][cellj][cellk + 1];
3233 FX101 = FastStgFX[thisBlock][celli + 1][cellj][cellk + 1];
3234 FY101 = FastStgFY[thisBlock][celli + 1][cellj][cellk + 1];
3235 FZ101 = FastStgFZ[thisBlock][celli + 1][cellj][cellk + 1];
3236 P011 = FastStgPot[thisBlock][celli][cellj + 1][cellk + 1];
3237 FX011 = FastStgFX[thisBlock][celli][cellj + 1][cellk + 1];
3238 FY011 = FastStgFY[thisBlock][celli][cellj + 1][cellk + 1];
3239 FZ011 = FastStgFZ[thisBlock][celli][cellj + 1][cellk + 1];
3240 P111 = FastStgPot[thisBlock][celli + 1][cellj + 1][cellk + 1];
3241 FX111 = FastStgFX[thisBlock][celli + 1][cellj + 1][cellk + 1];
3242 FY111 = FastStgFY[thisBlock][celli + 1][cellj + 1][cellk + 1];
3243 FZ111 = FastStgFZ[thisBlock][celli + 1][cellj + 1][cellk + 1];
3244 }
3245 if (sector == 4) { // volume shifted down and point in the staggered part
3246 P000 = FastStgPot[thisBlock][celli][cellj][cellk];
3247 FX000 = FastStgFX[thisBlock][celli][cellj][cellk];
3248 FY000 = FastStgFY[thisBlock][celli][cellj][cellk];
3249 FZ000 = FastStgFZ[thisBlock][celli][cellj][cellk];
3250 P100 = FastStgPot[thisBlock][celli + 1][cellj][cellk];
3251 FX100 = FastStgFX[thisBlock][celli + 1][cellj][cellk];
3252 FY100 = FastStgFY[thisBlock][celli + 1][cellj][cellk];
3253 FZ100 = FastStgFZ[thisBlock][celli + 1][cellj][cellk];
3254 P010 = FastStgPot[thisBlock][celli][cellj + 1][cellk];
3255 FX010 = FastStgFX[thisBlock][celli][cellj + 1][cellk];
3256 FY010 = FastStgFY[thisBlock][celli][cellj + 1][cellk];
3257 FZ010 = FastStgFZ[thisBlock][celli][cellj + 1][cellk];
3258 P001 = FastStgPot[thisBlock][celli][cellj][cellk + 1];
3259 FX001 = FastStgFX[thisBlock][celli][cellj][cellk + 1];
3260 FY001 = FastStgFY[thisBlock][celli][cellj][cellk + 1];
3261 FZ001 = FastStgFZ[thisBlock][celli][cellj][cellk + 1];
3262 P110 = FastStgPot[thisBlock][celli + 1][cellj + 1][cellk];
3263 FX110 = FastStgFX[thisBlock][celli + 1][cellj + 1][cellk];
3264 FY110 = FastStgFY[thisBlock][celli + 1][cellj + 1][cellk];
3265 FZ110 = FastStgFZ[thisBlock][celli + 1][cellj + 1][cellk];
3266 P101 = FastStgPot[thisBlock][celli + 1][cellj][cellk + 1];
3267 FX101 = FastStgFX[thisBlock][celli + 1][cellj][cellk + 1];
3268 FY101 = FastStgFY[thisBlock][celli + 1][cellj][cellk + 1];
3269 FZ101 = FastStgFZ[thisBlock][celli + 1][cellj][cellk + 1];
3270 P011 = FastStgPot[thisBlock][celli][cellj + 1][cellk + 1];
3271 FX011 = FastStgFX[thisBlock][celli][cellj + 1][cellk + 1];
3272 FY011 = FastStgFY[thisBlock][celli][cellj + 1][cellk + 1];
3273 FZ011 = FastStgFZ[thisBlock][celli][cellj + 1][cellk + 1];
3274 P111 = FastStgPot[thisBlock][celli + 1][cellj + 1][cellk + 1];
3275 FX111 = FastStgFX[thisBlock][celli + 1][cellj + 1][cellk + 1];
3276 FY111 = FastStgFY[thisBlock][celli + 1][cellj + 1][cellk + 1];
3277 FZ111 = FastStgFZ[thisBlock][celli + 1][cellj + 1][cellk + 1];
3278 }
3279 } // if OptStaggerFastVol
3280
3281 double intP =
3282 TriLin(xd, yd, zd, P000, P100, P010, P001, P110, P101, P011, P111);
3283 double intFX = TriLin(xd, yd, zd, FX000, FX100, FX010, FX001, FX110, FX101,
3284 FX011, FX111);
3285 double intFY = TriLin(xd, yd, zd, FY000, FY100, FY010, FY001, FY110, FY101,
3286 FY011, FY111);
3287 double intFZ = TriLin(xd, yd, zd, FZ000, FZ100, FZ010, FZ001, FZ110, FZ101,
3288 FZ011, FZ111);
3289
3290 *Potential = intP;
3291 globalF->X = intFX;
3292 globalF->Y = intFY;
3293 globalF->Z = intFZ;
3294
3295 if (dbgFn) {
3296 printf("Cell corner values:\n");
3297 printf("Potential: %g, %g, %g, %g\n", P000, P100, P010, P001);
3298 printf("Potential: %g, %g, %g, %g\n", P110, P101, P011, P111);
3299 printf("FastFX: %g, %g, %g, %g\n", FX000, FX100, FX010, FX001);
3300 printf("FastFX: %g, %g, %g, %g\n", FX110, FX101, FX011, FX111);
3301 printf("FastFY: %g, %g, %g, %g\n", FY000, FY100, FY010, FY001);
3302 printf("FastFY: %g, %g, %g, %g\n", FY110, FY101, FY011, FY111);
3303 printf("FastFZ: %g, %g, %g, %g\n", FZ000, FZ100, FZ010, FZ001);
3304 printf("FastFZ: %g, %g, %g, %g\n", FZ110, FZ101, FZ011, FZ111);
3305 printf("Pot, FX, FY, FZ: %g, %g, %g, %g\n", *Potential, globalF->X,
3306 globalF->Y, globalF->Z);
3307 }
3308
3309 if (dbgFn) {
3310 printf("out FastPFAtPoint\n");
3311 fflush(stdout);
3312 }
3313
3314 return 0;
3315} // FastPFAtPoint ends
int PFAtPoint(Point3D *globalP, double *Potential, Vector3D *globalF)
neBEMGLOBAL double **** FastFY
Definition: neBEM.h:444
neBEMGLOBAL double **** FastFZ
Definition: neBEM.h:444
neBEMGLOBAL double **** FastStgFZ
Definition: neBEM.h:446
neBEMGLOBAL double **** FastStgPot
Definition: neBEM.h:445
neBEMGLOBAL double **** FastStgFY
Definition: neBEM.h:446
neBEMGLOBAL double **** FastFX
Definition: neBEM.h:444
neBEMGLOBAL double **** FastStgFX
Definition: neBEM.h:446
neBEMGLOBAL double **** FastPot
Definition: neBEM.h:443

Referenced by MapFPR(), and neBEMField().

◆ FastVolElePF()

neBEMGLOBAL int FastVolElePF ( void  )

Definition at line 1964 of file ComputeProperties.c.

1964 {
1965 int dbgFn = 0;
1966 int fstatus;
1967
1968 int nbXCells;
1969 int nbYCells;
1970 int nbZCells;
1971 double startX;
1972 double startY;
1973 double startZ;
1974 double delX;
1975 double delY;
1976 double delZ;
1977
1978 printf("\nPotential and field computation within basic fast volume\n");
1979 int bskip = 0, iskip = 0, jskip = 0, kskip = 0;
1980
1981 // calculate n-skips based on NbPtSkip
1982 if (NbPtSkip) {
1983 int volptcnt = 0, endskip = 0;
1984
1985 for (int block = 1; block <= FastVol.NbBlocks; ++block) {
1986 nbXCells = BlkNbXCells[block];
1987 nbYCells = BlkNbYCells[block];
1988 nbZCells = BlkNbZCells[block];
1989 for (int i = 1; i <= nbXCells + 1; ++i) {
1990 for (int j = 1; j <= nbYCells + 1; ++j) {
1991 for (int k = 1; k <= nbZCells + 1; ++k) {
1992 ++volptcnt;
1993
1994 if (volptcnt == NbPtSkip) {
1995 bskip = block - 1;
1996 iskip = i - 1;
1997 jskip = j - 1;
1998 kskip = k;
1999 endskip = 1;
2000 }
2001
2002 if (endskip) break;
2003 }
2004 if (endskip) break;
2005 }
2006 if (endskip) break;
2007 }
2008 if (endskip) break;
2009 }
2010 if (dbgFn) {
2011 printf(
2012 "Basic fast volume => bskip, iskip, jskip, kskip: %d, %d, %d, %d\n",
2013 bskip, iskip, jskip, kskip);
2014 }
2015 } // NbPtSkip
2016
2017 char FastVolPFFile[256];
2018 FILE *fFastVolPF;
2019 strcpy(FastVolPFFile, BCOutDir);
2020 strcat(FastVolPFFile, "/FastVolPF.out");
2021 fFastVolPF = fopen(FastVolPFFile, "w");
2022 if (fFastVolPF == NULL) {
2023 neBEMMessage("FastVolPF - FastVolPFFile");
2024 return -1;
2025 }
2026 fprintf(fFastVolPF, "#block\tX\tY\tZ\tPot\tFX\tFY\tFZ\n");
2027
2028 if (dbgFn) {
2029 printf("FastVolPF.out created ...\n");
2030 fflush(stdout);
2031 }
2032
2033 for (int block = 1 + bskip; block <= FastVol.NbBlocks; ++block) {
2034 nbXCells = BlkNbXCells[block];
2035 nbYCells = BlkNbYCells[block];
2036 nbZCells = BlkNbZCells[block];
2037 startX = FastVol.CrnrX;
2038 startY = FastVol.CrnrY;
2039 startZ = BlkCrnrZ[block];
2040 delX = FastVol.LX / nbXCells;
2041 delY = FastVol.LY / nbYCells;
2042 delZ = BlkLZ[block] / nbZCells;
2043 printf(
2044 "NbBlocks: %d, block: %d, nbXCells: %d, nbYCells: %d, nbZCells: %d\n",
2045 FastVol.NbBlocks, block, nbXCells, nbYCells, nbZCells);
2046
2047 if (dbgFn) {
2048 printf("block: %d\n", block);
2049 printf("nbXCells, nbYCells, nbZCells: %d, %d, %d\n", nbXCells, nbYCells,
2050 nbZCells);
2051 printf("startX, startY, startZ: %le, %le, %le\n", startX, startY, startZ);
2052 printf("delX, delY, delZ: %le, %le, %le\n", delX, delY, delZ);
2053 printf("bskip, iskip, jskip, kskip: %d, %d, %d, %d\n", bskip, iskip,
2054 jskip, kskip);
2055 fflush(stdout);
2056 }
2057 // total number of points in a given block
2058 // int blktotpt = (nbXCells + 1) * (nbYCells + 1) * (nbZCells + 1);
2059 for (int i = 1 + iskip; i <= nbXCells + 1; ++i) {
2060 for (int j = 1 + jskip; j <= nbYCells + 1; ++j) {
2061 printf("Fast volume => block: %3d, i: %4d, j: %4d", block, i, j);
2062 fflush(stdout);
2063
2064 Point3D point;
2065#ifdef _OPENMP
2066 int nthreads = 1, tid = 0;
2067 #pragma omp parallel private(nthreads, tid)
2068#endif
2069 {
2070#ifdef _OPENMP
2071 if (dbgFn) {
2072 tid = omp_get_thread_num();
2073 if (tid == 0) {
2074 nthreads = omp_get_num_threads();
2075 printf("Starting fast volume computation with %d threads\n",
2076 nthreads);
2077 }
2078 }
2079#endif
2080 int k;
2081 int omitFlag;
2082 double potential;
2083 Vector3D field;
2084#ifdef _OPENMP
2085 #pragma omp for private(k, point, omitFlag, potential, field)
2086#endif
2087 for (k = 1 + kskip; k <= nbZCells + 1; ++k) {
2088 potential = 0.0;
2089 field.X = field.Y = field.Z = 0.0;
2090
2091 point.X = startX + (i - 1) * delX;
2092 point.Y = startY + (j - 1) * delY;
2093 point.Z = startZ + (k - 1) * delZ;
2094
2095 // Check whether the point falls within a volume that should be
2096 // ignored
2097 omitFlag = 0;
2098 for (int omit = 1; omit <= FastVol.NbOmitVols; ++omit) {
2099 if ((point.X > OmitVolCrnrX[omit]) &&
2100 (point.X < OmitVolCrnrX[omit] + OmitVolLX[omit]) &&
2101 (point.Y > OmitVolCrnrY[omit]) &&
2102 (point.Y < OmitVolCrnrY[omit] + OmitVolLY[omit]) &&
2103 (point.Z > OmitVolCrnrZ[omit]) &&
2104 (point.Z < OmitVolCrnrZ[omit] + OmitVolLZ[omit])) {
2105 omitFlag = 1;
2106 break;
2107 }
2108 } // loop over omitted volumes
2109
2110 if (dbgFn) {
2111 printf("block, i, j, k: %d, %d, %d, %d\n", block, i, j, k);
2112 printf("point X, Y, Z: %.8lg\t%.8lg\t%.8lg\n",
2113 point.X / LengthScale, point.Y / LengthScale,
2114 point.Z / LengthScale);
2115 printf("omitFlag: %d\n", omitFlag);
2116 fflush(stdout);
2117 }
2118
2119 if (omitFlag) {
2120 potential = field.X = field.Y = field.Z = 0.0;
2121 } else {
2122 // fstatus = ElePFAtPoint(&point, &potential, &field);
2123 fstatus =
2124 PFAtPoint(&point, &potential, &field); // both ele and KnCh
2125 if (fstatus != 0) {
2127 "wrong ElePFAtPoint return value in FastVolElePF.\n");
2128 // return -1;
2129 }
2130 }
2131 if (dbgFn) {
2132 printf("%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\n",
2133 point.X / LengthScale, point.Y / LengthScale,
2134 point.Z / LengthScale, potential / LengthScale, field.X,
2135 field.Y, field.Z);
2136 fflush(stdout);
2137 }
2138
2139 FastPot[block][i][j][k] = potential;
2140 FastFX[block][i][j][k] = field.X;
2141 FastFY[block][i][j][k] = field.Y;
2142 FastFZ[block][i][j][k] = field.Z;
2143 } // loop k
2144 } // pragma omp parallel
2145
2146 for (int k = 1 + kskip; k <= nbZCells + 1; ++k) // file output
2147 {
2148 point.X = startX + (i - 1) * delX;
2149 point.Y = startY + (j - 1) * delY;
2150 point.Z = startZ + (k - 1) * delZ;
2151
2152 fprintf(fFastVolPF,
2153 "%4d\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\n",
2154 block, point.X / LengthScale, point.Y / LengthScale,
2155 point.Z / LengthScale, FastPot[block][i][j][k],
2156 FastFX[block][i][j][k], FastFY[block][i][j][k],
2157 FastFZ[block][i][j][k]);
2158 }
2159 fflush(fFastVolPF); // file output over
2160
2161 printf(
2162 "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
2163 "\b\b\b\b\b\b\b\b\b\b");
2164 } // loop j
2165 } // loop i
2166 } // loop block
2167
2168 fclose(fFastVolPF);
2169
2170 if (OptStaggerFastVol) {
2171 printf("Potential and field computation within staggered fast volume\n");
2172
2173 bskip = iskip = jskip = kskip = 0;
2174
2175 // calculate n-skips based on NbStgPtSkip
2176 if (NbStgPtSkip) {
2177 int volptcnt = 0, endskip = 0;
2178
2179 for (int block = 1; block <= FastVol.NbBlocks; ++block) {
2180 nbXCells = BlkNbXCells[block];
2181 nbYCells = BlkNbYCells[block];
2182 nbZCells = BlkNbZCells[block];
2183 for (int i = 1; i <= nbXCells + 1; ++i) {
2184 for (int j = 1; j <= nbYCells + 1; ++j) {
2185 for (int k = 1; k <= nbZCells + 1; ++k) {
2186 ++volptcnt;
2187
2188 if (volptcnt == NbStgPtSkip) {
2189 bskip = block - 1;
2190 iskip = i - 1;
2191 jskip = j - 1;
2192 kskip = k;
2193 endskip = 1;
2194 }
2195
2196 if (endskip) break;
2197 }
2198 if (endskip) break;
2199 }
2200 if (endskip) break;
2201 }
2202 if (endskip) break;
2203 }
2204 if (dbgFn) {
2205 printf(
2206 "Staggered volume => bskip, iskip, jskip, kskip: %d, %d, %d, %d\n",
2207 bskip, iskip, jskip, kskip);
2208 }
2209 } // NbStgPtSkip
2210
2211 char FastStgVolPFFile[256];
2212 FILE *fFastStgVolPF;
2213 strcpy(FastStgVolPFFile, BCOutDir);
2214 strcat(FastStgVolPFFile, "/FastStgVolPF.out");
2215 fFastStgVolPF = fopen(FastStgVolPFFile, "w");
2216 if (fFastStgVolPF == NULL) {
2217 neBEMMessage("FastVolPF - FastStgVolPFFile");
2218 return -1;
2219 }
2220 fprintf(fFastStgVolPF, "#block\tX\tY\tZ\tPot\tFX\tFY\tFZ\n");
2221
2222 if (dbgFn) {
2223 printf("FastStgVolPF.out created ...\n");
2224 fflush(stdout);
2225 }
2226
2227 for (int block = 1 + bskip; block <= FastVol.NbBlocks; ++block) {
2228 nbXCells = BlkNbXCells[block];
2229 nbYCells = BlkNbYCells[block];
2230 nbZCells = BlkNbZCells[block];
2231 startX = FastVol.CrnrX + FastVol.LX;
2232 startY = FastVol.CrnrY + FastVol.YStagger;
2233 startZ = BlkCrnrZ[block];
2234 delX = FastVol.LX / nbXCells;
2235 delY = FastVol.LY / nbYCells;
2236 delZ = BlkLZ[block] / nbZCells;
2237 printf(
2238 "NbBlocks: %d, block: %d, nbXCells: %d, nbYCells: %d, nbZCells: %d\n",
2239 FastVol.NbBlocks, block, nbXCells, nbYCells, nbZCells);
2240
2241 if (dbgFn) {
2242 printf("block: %d\n", block);
2243 printf("nbXCells, nbYCells, nbZCells: %d, %d, %d\n", nbXCells, nbYCells,
2244 nbZCells);
2245 printf("startX, startY, startZ: %le, %le, %le\n", startX, startY,
2246 startZ);
2247 printf("delX, delY, delZ: %le, %le, %le\n", delX, delY, delZ);
2248 printf("bskip, iskip, jskip, kskip: %d, %d, %d, %d\n", bskip, iskip,
2249 jskip, kskip);
2250 fflush(stdout);
2251 }
2252
2253 // int blktotpt = (nbXCells + 1) * (nbYCells + 1) * (nbZCells + 1);
2254 for (int i = 1 + iskip; i <= nbXCells + 1; ++i) {
2255 for (int j = 1 + jskip; j <= nbYCells + 1; ++j) {
2256 printf("Fast volume => block: %3d, i: %4d, j: %4d", block, i, j);
2257 fflush(stdout);
2258
2259 Point3D point;
2260#ifdef _OPENMP
2261 int nthreads = 1, tid = 0;
2262 #pragma omp parallel private(nthreads, tid)
2263#endif
2264 {
2265#ifdef _OPENMP
2266 if (dbgFn) {
2267 tid = omp_get_thread_num();
2268 if (tid == 0) {
2269 nthreads = omp_get_num_threads();
2270 printf(
2271 "Starting staggered fast volume computation with %d "
2272 "threads\n",
2273 nthreads);
2274 }
2275 }
2276#endif
2277 int k;
2278 int omitFlag;
2279 double potential;
2280 Vector3D field;
2281#ifdef _OPENMP
2282 #pragma omp for private(k, point, omitFlag, potential, field)
2283#endif
2284 for (k = 1 + kskip; k <= nbZCells + 1; ++k) {
2285 potential = 0.0;
2286 field.X = field.Y = field.Z = 0.0;
2287
2288 point.X = startX + (i - 1) * delX;
2289 point.Y = startY + (j - 1) * delY;
2290 point.Z = startZ + (k - 1) * delZ;
2291
2292 // Check whether point falls within a volume that should be
2293 // ignored
2294 omitFlag = 0;
2295 for (int omit = 1; omit <= FastVol.NbOmitVols; ++omit) {
2296 if ((point.X > OmitVolCrnrX[omit] + FastVol.LX) &&
2297 (point.X <
2298 OmitVolCrnrX[omit] + OmitVolLX[omit] + FastVol.LX) &&
2299 (point.Y > OmitVolCrnrY[omit] + FastVol.YStagger) &&
2300 (point.Y <
2301 OmitVolCrnrY[omit] + OmitVolLY[omit] + FastVol.YStagger) &&
2302 (point.Z > OmitVolCrnrZ[omit]) &&
2303 (point.Z < OmitVolCrnrZ[omit] + OmitVolLZ[omit])) {
2304 omitFlag = 1;
2305 break;
2306 }
2307 } // loop over omitted volumes
2308
2309 if (dbgFn) {
2310 printf("point X, Y, Z: %.8lg\t%.8lg\t%.8lg\n",
2311 point.X / LengthScale, point.Y / LengthScale,
2312 point.Z / LengthScale);
2313 printf("omitFlag: %d\n", omitFlag);
2314 fflush(stdout);
2315 }
2316
2317 if (omitFlag) {
2318 potential = field.X = field.Y = field.Z = 0.0;
2319 } else {
2320 // fstatus = ElePFAtPoint(&point, &potential, &field);
2321 fstatus =
2322 PFAtPoint(&point, &potential, &field); // both ele & KnCh
2323 if (fstatus != 0) {
2325 "wrong PFAtPoint return value in FastVolElePF.\n");
2326 // return -1;
2327 }
2328 }
2329 if (dbgFn) {
2330 printf("%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\n",
2331 point.X / LengthScale, point.Y / LengthScale,
2332 point.Z / LengthScale, potential / LengthScale, field.X,
2333 field.Y, field.Z);
2334 fflush(stdout);
2335 }
2336
2337 FastStgPot[block][i][j][k] = potential;
2338 FastStgFX[block][i][j][k] = field.X;
2339 FastStgFY[block][i][j][k] = field.Y;
2340 FastStgFZ[block][i][j][k] = field.Z;
2341 } // loop k
2342 } // pragma omp
2343
2344 for (int k = 1 + kskip; k <= nbZCells + 1; ++k) // file output
2345 {
2346 point.X = startX + (i - 1) * delX;
2347 point.Y = startY + (j - 1) * delY;
2348 point.Z = startZ + (k - 1) * delZ;
2349
2350 fprintf(fFastStgVolPF,
2351 "%4d\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\n",
2352 block, point.X / LengthScale, point.Y / LengthScale,
2353 point.Z / LengthScale, FastPot[block][i][j][k],
2354 FastFX[block][i][j][k], FastFY[block][i][j][k],
2355 FastFZ[block][i][j][k]);
2356 }
2357 fflush(fFastStgVolPF); // file output over
2358
2359 printf(
2360 "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
2361 "\b\b\b\b\b\b\b\b\b\b\b");
2362 } // loop j
2363 } // loop i
2364 } // loop block
2365
2366 fclose(fFastStgVolPF);
2367 } // if OptStaggerFastVol
2368
2369 return 0;
2370} // FastVolElePF ends
neBEMGLOBAL double * OmitVolCrnrZ
Definition: neBEM.h:434
neBEMGLOBAL double * OmitVolLX
Definition: neBEM.h:429
neBEMGLOBAL double * OmitVolCrnrX
Definition: neBEM.h:432
neBEMGLOBAL double * OmitVolLZ
Definition: neBEM.h:431
neBEMGLOBAL int NbStgPtSkip
Definition: neBEM.h:408
neBEMGLOBAL int NbPtSkip
Definition: neBEM.h:407
neBEMGLOBAL double * OmitVolCrnrY
Definition: neBEM.h:433
neBEMGLOBAL double * OmitVolLY
Definition: neBEM.h:430
neBEMGLOBAL double LengthScale
Definition: neBEM.h:238
neBEMGLOBAL char BCOutDir[256]
Definition: neBEM.h:263
int NbOmitVols
Definition: neBEM.h:419

Referenced by FastVolPF().

◆ FastVolKnChPF()

neBEMGLOBAL int FastVolKnChPF ( void  )

◆ FastVolPF()

neBEMGLOBAL int FastVolPF ( void  )

Definition at line 1930 of file ComputeProperties.c.

1930 {
1931
1932 // The following may be necessary only during the first time step / iteration
1933 // At present, FastVolElePF() considers both element and KnCh effects
1934 // and create one combined fast volume.
1935 int fstatus = FastVolElePF();
1936 if (fstatus) {
1937 printf(
1938 "Problem in FastVolElePF being called from FastVolPF ... returning\n");
1939 return -1;
1940 }
1941
1942 /*
1943 // The following is likely to change throughout the computation and necessary
1944 // at all time steps. However, in order to achieve computational economy, it
1945 // may be prudent to carry out the following only after several time steps.
1946 if (OptKnCh) {
1947 fstatus = FastVolKnChPF();
1948 if (fstatus) {
1949 printf("Problem in FastVolKnChPF being called from FastVolPF... returning\n");
1950 return -1;
1951 }
1952 }
1953 */
1954
1955 return 0;
1956} // FastVolPF ends
int FastVolElePF(void)

Referenced by neBEMSolve().

◆ GetFlux()

neBEMGLOBAL void GetFlux ( int  src,
Point3D localPt,
Vector3D Flux 
)

Definition at line 208 of file ComputeProperties.c.

208 {
209 switch ((EleArr + ele - 1)->G.Type) {
210 case 4: // rectangular element
211 RecFlux(ele, localP, localF);
212 break;
213 case 3: // triangular element
214 TriFlux(ele, localP, localF);
215 break;
216 case 2: // linear (wire) element
217 WireFlux(ele, localP, localF);
218 break;
219 default:
220 printf("Geometrical type out of range! ... exiting ...\n");
221 exit(-1);
222 break; // never comes here
223 } // switch over gtsrc ends
224} // end of GetFlux

◆ GetFluxGCS()

neBEMGLOBAL void GetFluxGCS ( int  src,
Point3D localPt,
Vector3D Flux 
)

Definition at line 184 of file ComputeProperties.c.

184 {
185 Vector3D localF;
186
187 switch ((EleArr + ele - 1)->G.Type) {
188 case 4: // rectangular element
189 RecFlux(ele, localP, &localF);
190 break;
191 case 3: // triangular element
192 TriFlux(ele, localP, &localF);
193 break;
194 case 2: // linear (wire) element
195 WireFlux(ele, localP, &localF);
196 break;
197 default:
198 printf("Geometrical type out of range! ... exiting ...\n");
199 exit(-1);
200 break; // never comes here
201 } // switch over gtsrc ends
202
203 (*globalF) = RotateVector3D(&localF, &(EleArr + ele - 1)->G.DC, local2global);
204} // end of GetFluxGCS

◆ GetPF()

neBEMGLOBAL void GetPF ( int  type,
double  a,
double  b,
double  x,
double  y,
double  z,
double *  Pot,
Vector3D Flux 
)

Definition at line 4355 of file ComputeProperties.c.

4356 {
4357 switch (type) {
4358 case 4: // rectangular element
4359 RecPF(a, b, x, y, z, Potential, localF);
4360 break;
4361 case 3: // triangular element
4362 TriPF(a, b, x, y, z, Potential, localF);
4363 break;
4364 case 2: // linear (wire) element
4365 WirePF(a, b, x, y, z, Potential, localF);
4366 break;
4367 default:
4368 printf("Geometrical type out of range! ... exiting ...\n");
4369 exit(-1);
4370 break; // never comes here
4371 } // switch over gtsrc ends
4372} // end of GetPF
void RecPF(double a, double b, double x, double y, double z, double *Potential, Vector3D *localF)
void TriPF(double a, double b, double x, double y, double z, double *Potential, Vector3D *localF)
void WirePF(double rW, double lW, double x, double y, double z, double *Potential, Vector3D *localF)

Referenced by ElePFAtPoint(), and WtPFAtPoint().

◆ GetPFGCS()

neBEMGLOBAL void GetPFGCS ( int  type,
double  a,
double  b,
Point3D localPt,
double *  Pot,
Vector3D Flux,
DirnCosn3D DirCos 
)

Definition at line 4328 of file ComputeProperties.c.

4329 {
4330 Vector3D localF;
4331 const double x = localP->X;
4332 const double y = localP->Y;
4333 const double z = localP->Z;
4334 switch (type) {
4335 case 4: // rectangular element
4336 RecPF(a, b, x, y, z, Potential, &localF);
4337 break;
4338 case 3: // triangular element
4339 TriPF(a, b, x, y, z, Potential, &localF);
4340 break;
4341 case 2: // linear (wire) element
4342 WirePF(a, b, x, y, z, Potential, &localF);
4343 break;
4344 default:
4345 printf("Geometrical type out of range! ... exiting ...\n");
4346 exit(-1);
4347 break; // never comes here
4348 } // switch over gtsrc ends
4349
4350 (*globalF) = RotateVector3D(&localF, DirCos, local2global);
4351} // end of GetPFGCS

Referenced by ElePFAtPoint().

◆ GetPotential()

neBEMGLOBAL double GetPotential ( int  src,
Point3D localPt 
)

Definition at line 33 of file ComputeProperties.c.

33 {
34 double value;
35
36 switch ((EleArr + ele - 1)->G.Type) {
37 case 4: // rectangular element
38 value = RecPot(ele, localP);
39 break;
40 case 3: // triangular element
41 value = TriPot(ele, localP);
42 break;
43 case 2: // linear (wire) element
44 value = WirePot(ele, localP);
45 break;
46 default:
47 printf("Geometrical type out of range! ... exiting ...\n");
48 exit(-1);
49 break; // never comes here
50 } // switch over gtsrc ends
51
52 return (value);
53} // end of GetPotential
double TriPot(int ele, Point3D *localP)
double WirePot(int ele, Point3D *localP)
double RecPot(int ele, Point3D *localP)

Referenced by Garfield::ComponentCST::WeightingPotential().

◆ GetPrimPF()

neBEMGLOBAL void GetPrimPF ( int  src,
Point3D localPt,
double *  Pot,
Vector3D Flux 
)

Definition at line 4480 of file ComputeProperties.c.

4480 {
4481 switch (PrimType[prim]) {
4482 case 4: // rectangular primitive
4483 RecPrimPF(prim, localP, Potential, localF);
4484 break;
4485 case 3: // triangular primitive
4486 TriPrimPF(prim, localP, Potential, localF);
4487 break;
4488 case 2: // linear (wire) primitive
4489 WirePrimPF(prim, localP, Potential, localF);
4490 break;
4491 default:
4492 printf("Geometrical type out of range! ... exiting ...\n");
4493 exit(-1);
4494 break; // never comes here
4495 } // switch over gtsrc ends
4496} // end of GetPrimPF
void WirePrimPF(int prim, Point3D *localP, double *Potential, Vector3D *localF)
void RecPrimPF(int prim, Point3D *localP, double *Potential, Vector3D *localF)
void TriPrimPF(int prim, Point3D *localP, double *Potential, Vector3D *localF)

Referenced by ElePFAtPoint(), and WtPFAtPoint().

◆ GetPrimPFGCS()

neBEMGLOBAL void GetPrimPFGCS ( int  src,
Point3D localPt,
double *  Pot,
Vector3D Flux,
DirnCosn3D DirCos 
)

Definition at line 4455 of file ComputeProperties.c.

4456 {
4457 Vector3D localF;
4458
4459 switch (PrimType[prim]) {
4460 case 4: // rectangular primitive
4461 RecPrimPF(prim, localP, Potential, &localF);
4462 break;
4463 case 3: // triangular primitive
4464 TriPrimPF(prim, localP, Potential, &localF);
4465 break;
4466 case 2: // linear (wire) primitive
4467 WirePrimPF(prim, localP, Potential, &localF);
4468 break;
4469 default:
4470 printf("Geometrical type out of range! ... exiting ...\n");
4471 exit(-1);
4472 break; // never comes here
4473 } // switch over gtsrc ends
4474
4475 (*globalF) = RotateVector3D(&localF, DirCos, local2global);
4476} // end of GetPrimPFGCS

Referenced by ElePFAtPoint().

◆ KnChPFAtPoint()

neBEMGLOBAL int KnChPFAtPoint ( Point3D globalPt,
double *  Pot,
Vector3D Flux 
)

Definition at line 1344 of file ComputeProperties.c.

1344 {
1345 int dbgFn = 0;
1346 double tmpPot;
1347 Point3D tmpPt;
1348 tmpPt.X = globalP->X;
1349 tmpPt.Y = globalP->Y;
1350 tmpPt.Z = globalP->Z;
1351 Vector3D tmpF;
1352
1353 for (int point = 1; point <= NbPointsKnCh; ++point) {
1354 tmpPot = PointKnChPF((PointKnChArr + point - 1)->P, tmpPt, &tmpF);
1355 (*Potential) += (PointKnChArr + point - 1)->Assigned * tmpPot / MyFACTOR;
1356 globalF->X += (PointKnChArr + point - 1)->Assigned * tmpF.X / MyFACTOR;
1357 globalF->Y += (PointKnChArr + point - 1)->Assigned * tmpF.Y / MyFACTOR;
1358 globalF->Z += (PointKnChArr + point - 1)->Assigned * tmpF.Z / MyFACTOR;
1359 }
1360
1361 for (int line = 1; line <= NbLinesKnCh; ++line) {
1362 tmpPot = LineKnChPF((LineKnChArr + line - 1)->Start,
1363 (LineKnChArr + line - 1)->Stop,
1364 (LineKnChArr + line - 1)->Radius, tmpPt, &tmpF);
1365 (*Potential) += (LineKnChArr + line - 1)->Assigned * tmpPot / MyFACTOR;
1366 globalF->X += (LineKnChArr + line - 1)->Assigned * tmpF.X / MyFACTOR;
1367 globalF->Y += (LineKnChArr + line - 1)->Assigned * tmpF.Y / MyFACTOR;
1368 globalF->Z += (LineKnChArr + line - 1)->Assigned * tmpF.Z / MyFACTOR;
1369 }
1370
1371 for (int area = 1; area <= NbAreasKnCh; ++area) {
1372 tmpPot = AreaKnChPF((AreaKnChArr + area - 1)->NbVertices,
1373 ((AreaKnChArr + area - 1)->Vertex), tmpPt, &tmpF);
1374 (*Potential) += (AreaKnChArr + area - 1)->Assigned * tmpPot / MyFACTOR;
1375 globalF->X += (AreaKnChArr + area - 1)->Assigned * tmpF.X / MyFACTOR;
1376 globalF->Y += (AreaKnChArr + area - 1)->Assigned * tmpF.Y / MyFACTOR;
1377 globalF->Z += (AreaKnChArr + area - 1)->Assigned * tmpF.Z / MyFACTOR;
1378 }
1379
1380 for (int vol = 1; vol <= NbVolumesKnCh; ++vol) {
1381 tmpPot = VolumeKnChPF((VolumeKnChArr + vol - 1)->NbVertices,
1382 ((VolumeKnChArr + vol - 1)->Vertex), tmpPt, &tmpF);
1383 (*Potential) += (VolumeKnChArr + vol - 1)->Assigned * tmpPot / MyFACTOR;
1384 globalF->X += (VolumeKnChArr + vol - 1)->Assigned * tmpF.X / MyFACTOR;
1385 globalF->Y += (VolumeKnChArr + vol - 1)->Assigned * tmpF.Y / MyFACTOR;
1386 globalF->Z += (VolumeKnChArr + vol - 1)->Assigned * tmpF.Z / MyFACTOR;
1387 }
1388
1389 if (dbgFn) {
1390 printf("Final values due to all known charges: ");
1391 // printf("xfld\tyfld\tzfld\tPot\tFx\tFy\tFz\n"); // refer, do not
1392 // uncomment
1393 printf("%lg\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n\n", tmpPt.X, tmpPt.Y, tmpPt.Z,
1394 (*Potential), globalF->X, globalF->Y, globalF->Z);
1395 fflush(stdout);
1396 }
1397
1398 return 0;
1399} // KnChPFAtPoint ends
double LineKnChPF(Point3D LineStart, Point3D LineStop, double radius, Point3D FieldPt, Vector3D *globalF)
Definition: Isles.c:2199
double AreaKnChPF(int NbVertices, Point3D *Vertex, Point3D FieldPt, Vector3D *globalF)
Definition: Isles.c:2350
double PointKnChPF(Point3D SourcePt, Point3D FieldPt, Vector3D *globalF)
Definition: Isles.c:2177
double VolumeKnChPF(int, Point3D *, Point3D, Vector3D *globalF)
Definition: Isles.c:2491
neBEMGLOBAL double * Radius
Definition: neBEM.h:72

Referenced by FastKnChPFAtPoint(), and PFAtPoint().

◆ MapFPR()

neBEMGLOBAL int MapFPR ( void  )

Definition at line 1575 of file ComputeProperties.c.

1575 {
1576 int dbgFn = 0;
1577
1578 printf("\nPotential and field computation for 3dMap data export\n");
1579
1580 char MapInfoFile[256];
1581 strcpy(MapInfoFile, BCOutDir);
1582 strcat(MapInfoFile, "/MapInfo.out");
1583 FILE *fMapInfo = fopen(MapInfoFile, "w");
1584 if (fMapInfo == NULL) {
1585 neBEMMessage("MapFPR - MapInfoFile");
1586 return -1;
1587 }
1588 if (dbgFn) {
1589 printf("MapInfoFile.out created ...\n");
1590 fflush(stdout);
1591 }
1592
1593 // In certain versions, we may have only the version number in the header and
1594 // nothing more. In that case, it is unsafe to assume that OptMap or
1595 // OptStaggerMap will be at all present in the output file. This decision
1596 // may need to be taken immediately after reading the MapVersion value.
1597 fprintf(fMapInfo, "%s\n", MapVersion);
1598 fprintf(fMapInfo, "%d\n", OptMap);
1599 fprintf(fMapInfo, "%d\n", OptStaggerMap);
1600 fprintf(fMapInfo, "%d\n", Map.NbXCells + 1);
1601 fprintf(fMapInfo, "%d\n", Map.NbYCells + 1);
1602 fprintf(fMapInfo, "%d\n", Map.NbZCells + 1);
1603 fprintf(fMapInfo, "%le %le\n", Map.Xmin * 100.0, Map.Xmax * 100.0);
1604 fprintf(fMapInfo, "%le %le\n", Map.Ymin * 100.0, Map.Ymax * 100.0);
1605 fprintf(fMapInfo, "%le %le\n", Map.Zmin * 100.0, Map.Zmax * 100.0);
1606 fprintf(fMapInfo, "%le\n", Map.XStagger * 100.0);
1607 fprintf(fMapInfo, "%le\n", Map.YStagger * 100.0);
1608 fprintf(fMapInfo, "%le\n", Map.ZStagger * 100.0);
1609 fprintf(fMapInfo, "MapFPR.out\n");
1610 // if (OptStaggerMap) fprintf(fMapInfo, "StgrMapFPR.out\n"); /// not being read
1611 fclose(fMapInfo);
1612
1613 char MapFile[256];
1614 strcpy(MapFile, BCOutDir);
1615 strcat(MapFile, "/MapFPR.out");
1616 FILE *fMap = fopen(MapFile, "w");
1617 if (fMap == NULL) {
1618 neBEMMessage("MapFPR - MapFile");
1619 return -1;
1620 }
1621 if (dbgFn) {
1622 printf("MapFPR.out created ...\n");
1623 fflush(stdout);
1624 }
1625
1626 fprintf(
1627 fMap,
1628 "# X(cm)\tY(cm)\tZ(cm)\tFX(V/cm)\tFY(V/cm)\tFZ(V/cm)\tPot(V)\tRegion\n");
1629
1630 int nbXCells = Map.NbXCells;
1631 int nbYCells = Map.NbYCells;
1632 int nbZCells = Map.NbZCells;
1633 double startX = Map.Xmin;
1634 double startY = Map.Ymin;
1635 double startZ = Map.Zmin;
1636 double delX = (Map.Xmax - Map.Xmin) / nbXCells;
1637 double delY = (Map.Ymax - Map.Ymin) / nbYCells;
1638 double delZ = (Map.Zmax - Map.Zmin) / nbZCells;
1639
1640 double *MapFX = dvector(0, nbZCells + 1);
1641 double *MapFY = dvector(0, nbZCells + 1);
1642 double *MapFZ = dvector(0, nbZCells + 1);
1643 double *MapP = dvector(0, nbZCells + 1);
1644
1645 if (dbgFn) {
1646 printf("nbXCells, nbYCells, nbZCells: %d, %d, %d\n", nbXCells, nbYCells,
1647 nbZCells);
1648 printf("startX, startY, startZ: %le, %le, %le\n", startX, startY, startZ);
1649 printf("delX, delY, delZ: %le, %le, %le\n", delX, delY, delZ);
1650 fflush(stdout);
1651 }
1652
1653 for (int i = 1; i <= nbXCells + 1; ++i) {
1654 for (int j = 1; j <= nbYCells + 1; ++j) {
1655 if (dbgFn) {
1656 printf("MapFPR => i: %4d, j: %4d", i, j);
1657 fflush(stdout);
1658 }
1659
1660 Point3D point;
1661#ifdef _OPENMP
1662 int nthreads = 1, tid = 0;
1663 #pragma omp parallel private(nthreads, tid)
1664#endif
1665 {
1666#ifdef _OPENMP
1667 if (dbgFn) {
1668 tid = omp_get_thread_num();
1669 if (tid == 0) {
1670 nthreads = omp_get_num_threads();
1671 printf("Starting voxel computation with %d threads\n", nthreads);
1672 }
1673 }
1674#endif
1675 int k;
1676 Vector3D field;
1677 double potential;
1678#ifdef _OPENMP
1679 #pragma omp for private(k, point, potential, field)
1680#endif
1681 for (k = 1; k <= nbZCells + 1; ++k) {
1682 point.X = startX + (i - 1) * delX; // all 3 components need to be
1683 point.Y = startY + (j - 1) * delY; // evaluated after pragma omp
1684 point.Z = startZ + (k - 1) * delZ;
1685
1686 if (dbgFn) {
1687 printf("i, j, k: %d, %d, %d\n", i, j, k);
1688 printf("point X, Y, Z: %.8lg\t%.8lg\t%.8lg\n",
1689 point.X / LengthScale, point.Y / LengthScale,
1690 point.Z / LengthScale);
1691 fflush(stdout);
1692 }
1693
1694 if (OptReadFastPF) {
1695 int fstatus = FastPFAtPoint(&point, &potential, &field);
1696 if (fstatus != 0) {
1697 neBEMMessage("wrong FastPFAtPoint return value in MapFPR\n");
1698 // return -1;
1699 }
1700 } else {
1702 "Suggestion: Use of FastVol can expedite generation of Map.\n");
1703 int fstatus = PFAtPoint(&point, &potential, &field);
1704 if (fstatus != 0) {
1705 neBEMMessage("wrong PFAtPoint return value in MapFPR\n");
1706 // return -1;
1707 }
1708 }
1709
1710 if (dbgFn) {
1711 printf("%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\n",
1712 point.X / LengthScale, point.Y / LengthScale,
1713 point.Z / LengthScale, field.X, field.Y, field.Z,
1714 potential / LengthScale);
1715 fflush(stdout);
1716 }
1717
1718 MapFX[k] = field.X;
1719 MapFY[k] = field.Y;
1720 MapFZ[k] = field.Z;
1721 MapP[k] = potential;
1722 } // loop k
1723 } // pragma omp parallel
1724
1725 for (int k = 1; k <= nbZCells + 1; ++k) {
1726 // file output
1727 point.X = startX + (i - 1) * delX;
1728 point.Y = startY + (j - 1) * delY;
1729 point.Z = startZ + (k - 1) * delZ;
1730
1731 int ivol = neBEMVolumePoint(point.X, point.Y, point.Z);
1732 /*
1733 volMaterial[ivol]; // region linked to material
1734 neBEMVolumeDescription(ivol, &vshp, &vmat, &veps, &vpot, &vq, &vtype);
1735 if (dbgFn) {
1736 printf("volref: %d\n", ivol);
1737 printf("shape: %d, material: %d\n", volShape[ivol], volMaterial[ivol]);
1738 printf("eps: %d, pot: %d\n", volEpsilon[ivol], volPotential[ivol]);
1739 printf("q: %d, type: %d\n", volCharge[ivol], volBoundaryType[ivol]);
1740 printf("shape: %d, material: %d\n", vshp, vmat);
1741 printf("eps: %d, pot: %d\n", veps, vpot);
1742 printf("q: %d, type: %d\n", vq, vtype);
1743 }
1744 */
1745
1746 fprintf(fMap, "%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%4d\n",
1747 100.0 * point.X / LengthScale, 100.0 * point.Y / LengthScale,
1748 100.0 * point.Z / LengthScale, MapFX[k] / 100.0,
1749 MapFY[k] / 100.0, MapFZ[k] / 100.0, MapP[k] / LengthScale,
1750 ivol + 1);
1751 }
1752 fflush(fMap); // file output over
1753 } // loop j
1754 } // loop i
1755
1756 fclose(fMap);
1757
1758 free_dvector(MapFX, 0, nbZCells + 1);
1759 free_dvector(MapFY, 0, nbZCells + 1);
1760 free_dvector(MapFZ, 0, nbZCells + 1);
1761 free_dvector(MapP, 0, nbZCells + 1);
1762
1763 // If staggered map
1764 if (OptStaggerMap) {
1765 char StgrMapFile[256];
1766 strcpy(StgrMapFile, BCOutDir);
1767 strcat(StgrMapFile, "/StgrMapFPR.out");
1768 fMap = fopen(StgrMapFile, "w");
1769 if (fMap == NULL) {
1770 neBEMMessage("StgrMapFPR - Staggered MapFile");
1771 return -1;
1772 }
1773 if (dbgFn) {
1774 printf("StgrMapFPR.out created ...\n");
1775 fflush(stdout);
1776 }
1777
1778 fprintf(
1779 fMap,
1780 "# "
1781 "X(cm)\tY(cm)\tZ(cm)\tFX(V/cm)\tFY(V/cm)\tFZ(V/cm)\tPot(V)\tRegion\n");
1782 // Very static stagger where X-shift is one map long
1783 double LX = (Map.Xmax - Map.Xmin);
1784 Map.Xmin = Map.Xmax;
1785 Map.Xmax = Map.Xmin + LX;
1786 double LY = (Map.Ymax - Map.Ymin);
1788 Map.Ymax = Map.Ymin + LY;
1789 nbXCells = Map.NbXCells;
1790 nbYCells = Map.NbYCells;
1791 nbZCells = Map.NbZCells;
1792 startX = Map.Xmin;
1793 // and y-shift is of the presecribed amount
1794 startY = Map.Ymin + Map.YStagger;
1795 startZ = Map.Zmin;
1796 delX = (Map.Xmax - Map.Xmin) / nbXCells;
1797 delY = (Map.Ymax - Map.Ymin) / nbYCells;
1798 delZ = (Map.Zmax - Map.Zmin) / nbZCells;
1799
1800 MapFX = dvector(0, nbZCells + 1);
1801 MapFY = dvector(0, nbZCells + 1);
1802 MapFZ = dvector(0, nbZCells + 1);
1803 MapP = dvector(0, nbZCells + 1);
1804
1805 if (dbgFn) {
1806 printf("nbXCells, nbYCells, nbZCells: %d, %d, %d\n", nbXCells, nbYCells,
1807 nbZCells);
1808 printf("startX, startY, startZ: %le, %le, %le\n", startX, startY, startZ);
1809 printf("delX, delY, delZ: %le, %le, %le\n", delX, delY, delZ);
1810 fflush(stdout);
1811 }
1812
1813 for (int i = 1; i <= nbXCells + 1; ++i) {
1814 for (int j = 1; j <= nbYCells + 1; ++j) {
1815 if (dbgFn) {
1816 printf("StgrMapFPR => i: %4d, j: %4d", i, j);
1817 fflush(stdout);
1818 }
1819
1820 Point3D point;
1821#ifdef _OPENMP
1822 int nthreads = 1, tid = 0;
1823 #pragma omp parallel private(nthreads, tid)
1824#endif
1825 {
1826#ifdef _OPENMP
1827 if (dbgFn) {
1828 tid = omp_get_thread_num();
1829 if (tid == 0) {
1830 nthreads = omp_get_num_threads();
1831 printf("Starting voxel computation with %d threads\n", nthreads);
1832 }
1833 } // if dbgFn
1834#endif
1835 int k;
1836 Vector3D field;
1837 double potential;
1838#ifdef _OPENMP
1839 #pragma omp for private(k, point, potential, field)
1840#endif
1841 for (k = 1; k <= nbZCells + 1; ++k) {
1842 point.X = startX + (i - 1) * delX; // all 3 components need to be
1843 point.Y = startY + (j - 1) * delY; // evaluated after pragma omp
1844 point.Z = startZ + (k - 1) * delZ;
1845
1846 if (dbgFn) {
1847 printf("i, j, k: %d, %d, %d\n", i, j, k);
1848 printf("point X, Y, Z: %.8lg\t%.8lg\t%.8lg\n",
1849 point.X / LengthScale, point.Y / LengthScale,
1850 point.Z / LengthScale);
1851 fflush(stdout);
1852 }
1853
1854 if (OptReadFastPF) {
1855 int fstatus = FastPFAtPoint(&point, &potential, &field);
1856 if (fstatus != 0) {
1857 neBEMMessage("wrong FastPFAtPoint return value in MapFPR\n");
1858 // return -1;
1859 }
1860 } else {
1862 "Suggestion: Use of FastVol can expedite generation of "
1863 "Map.\n");
1864 int fstatus = PFAtPoint(&point, &potential, &field);
1865 if (fstatus != 0) {
1866 neBEMMessage("wrong PFAtPoint return value in MapFPR\n");
1867 // return -1;
1868 }
1869 }
1870
1871 if (dbgFn) {
1872 printf("%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\n",
1873 point.X / LengthScale, point.Y / LengthScale,
1874 point.Z / LengthScale, field.X, field.Y, field.Z,
1875 potential / LengthScale);
1876 fflush(stdout);
1877 }
1878
1879 MapFX[k] = field.X;
1880 MapFY[k] = field.Y;
1881 MapFZ[k] = field.Z;
1882 MapP[k] = potential;
1883 } // loop k
1884 } // pragma omp parallel
1885
1886 for (int k = 1; k <= nbZCells + 1; ++k) {
1887 // file output
1888 point.X = startX + (i - 1) * delX;
1889 point.Y = startY + (j - 1) * delY;
1890 point.Z = startZ + (k - 1) * delZ;
1891
1892 int ivol = neBEMVolumePoint(point.X, point.Y, point.Z);
1893 /*
1894 volMaterial[ivol]; // region linked to material
1895 neBEMVolumeDescription(ivol, &vshp, &vmat, &veps, &vpot, &vq, &vtype);
1896 if (dbgFn) {
1897 printf("volref: %d\n", ivol);
1898 printf("shape: %d, material: %d\n", volShape[ivol], volMaterial[ivol]);
1899 printf("eps: %d, pot: %d\n", volEpsilon[ivol], volPotential[ivol]);
1900 printf("q: %d, type: %d\n", volCharge[ivol], volBoundaryType[ivol]);
1901 printf("shape: %d, material: %d\n", vshp, vmat);
1902 printf("eps: %d, pot: %d\n", veps, vpot);
1903 printf("q: %d, type: %d\n", vq, vtype);
1904 }
1905 */
1906
1907 fprintf(
1908 fMap, "%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%4d\n",
1909 100.0 * point.X / LengthScale, 100.0 * point.Y / LengthScale,
1910 100.0 * point.Z / LengthScale, MapFX[k] / 100.0, MapFY[k] / 100.0,
1911 MapFZ[k] / 100.0, MapP[k] / LengthScale, ivol + 1);
1912 } // for k <= nbZCells
1913 fflush(fMap); // file output over
1914
1915 } // loop j
1916 } // loop i
1917
1918 fclose(fMap);
1919
1920 free_dvector(MapFX, 0, nbZCells + 1);
1921 free_dvector(MapFY, 0, nbZCells + 1);
1922 free_dvector(MapFZ, 0, nbZCells + 1);
1923 free_dvector(MapP, 0, nbZCells + 1);
1924 } // If staggered map
1925
1926 return 0;
1927} // end of MapFPR
int FastPFAtPoint(Point3D *globalP, double *Potential, Vector3D *globalF)
INTFACEGLOBAL int neBEMVolumePoint(double x, double y, double z)
neBEMGLOBAL MapVol Map
Definition: neBEM.h:396
neBEMGLOBAL int OptStaggerMap
Definition: neBEM.h:379
neBEMGLOBAL char MapVersion[10]
Definition: neBEM.h:380
neBEMGLOBAL int OptMap
Definition: neBEM.h:378
neBEMGLOBAL int OptReadFastPF
Definition: neBEM.h:406
int NbYCells
Definition: neBEM.h:393
double Ymax
Definition: neBEM.h:386
double YStagger
Definition: neBEM.h:390
double Zmax
Definition: neBEM.h:388
double ZStagger
Definition: neBEM.h:391
int NbZCells
Definition: neBEM.h:394
double Xmax
Definition: neBEM.h:384
double Xmin
Definition: neBEM.h:383
double XStagger
Definition: neBEM.h:389
double Zmin
Definition: neBEM.h:387
int NbXCells
Definition: neBEM.h:392
double Ymin
Definition: neBEM.h:385

Referenced by neBEMSolve().

◆ PFAtPoint()

neBEMGLOBAL int PFAtPoint ( Point3D globalPt,
double *  Pot,
Vector3D Flux 
)

Definition at line 661 of file ComputeProperties.c.

661 {
662 double ElePot;
663 Vector3D EleglobalF;
664 int fstatus = ElePFAtPoint(globalP, &ElePot, &EleglobalF);
665 if (fstatus) {
666 printf(
667 "Problem in ElePFAtPoint being called from PFAtPoint ... returning\n");
668 return (-1);
669 }
670 *Potential = ElePot;
671 globalF->X = EleglobalF.X;
672 globalF->Y = EleglobalF.Y;
673 globalF->Z = EleglobalF.Z;
674
675 if (OptKnCh) {
676 double KnChPot;
677 Vector3D KnChglobalF;
678 fstatus = KnChPFAtPoint(globalP, &KnChPot, &KnChglobalF);
679 if (fstatus) {
680 printf(
681 "Problem in KnChPFAtPoint being called from PFAtPoint ... "
682 "returning\n");
683 return (-1);
684 }
685 *Potential += KnChPot;
686 globalF->X += KnChglobalF.X;
687 globalF->Y += KnChglobalF.Y;
688 globalF->Z += KnChglobalF.Z;
689 }
690
691 return 0;
692} // PFAtPoint ends
int ElePFAtPoint(Point3D *globalP, double *Potential, Vector3D *globalF)
neBEMGLOBAL int OptKnCh
Definition: neBEM.h:52

Referenced by FastPFAtPoint(), FastVolElePF(), MapFPR(), neBEMField(), Solve(), and VoxelFPR().

◆ ReadSolution()

neBEMGLOBAL int ReadSolution ( void  )

Definition at line 3618 of file neBEM.c.

3618 {
3619 char SolnFile[256];
3620 strcpy(SolnFile, BCOutDir);
3621 strcat(SolnFile, "/Soln.out");
3622 FILE *fSoln = fopen(SolnFile, "r");
3623 // assert(fSoln != NULL);
3624 if (fSoln == NULL) {
3625 neBEMMessage("ReadSoln - unable to open solution file.");
3626 return -1;
3627 }
3628
3629 int itmp;
3630 double dtmp, sol;
3631 char instr[256];
3632 fgets(instr, 256, fSoln);
3633 for (int ele = 1; ele <= NbElements; ++ele) {
3634 fscanf(fSoln, "%d %lg %lg %lg %lg\n", &itmp, &dtmp, &dtmp, &dtmp, &sol);
3635 // assert(ele == itmp);
3636 if (ele != itmp) {
3637 neBEMMessage("ReadSolution - ele_itmp in ReadSolution");
3638 return -1;
3639 }
3640 (EleArr + ele - 1)->Solution = sol;
3641 }
3642 printf("\nReadSolution: Solution read in for all elements ...\n");
3643 fflush(stdout);
3644
3645 if (NbConstraints) {
3646 if (OptSystemChargeZero) {
3647 fgets(instr, 256, fSoln);
3648 fscanf(fSoln, "%d %lg\n", &NbSystemChargeZero, &VSystemChargeZero);
3649 printf(
3650 "ReadSolution: Read in voltage shift to ensure system charge "
3651 "zero.\n");
3652 }
3654 fgets(instr, 256, fSoln);
3655 fscanf(fSoln, "%d %lg\n", &NbFloatCon, &VFloatCon);
3656 printf("ReadSolution: Read in voltage on floating conductor.\n");
3657 }
3658 fflush(stdout);
3659 } // if NbConstraints
3660
3661 fclose(fSoln);
3662
3663 // Find primitive related charge densities
3664 // OMPCheck - may be parallelized
3665 for (int prim = 1; prim <= NbPrimitives; ++prim) {
3666 double area = 0.0; // need area of the primitive as well!
3667 AvChDen[prim] = 0.0;
3668 AvAsgndChDen[prim] = 0.0;
3669
3670 for (int ele = ElementBgn[prim]; ele <= ElementEnd[prim]; ++ele) {
3671 const double dA = (EleArr + ele - 1)->G.dA;
3672 area += dA;
3673 AvChDen[prim] += (EleArr + ele - 1)->Solution * dA;
3674 AvAsgndChDen[prim] += (EleArr + ele - 1)->Assigned * dA;
3675 }
3676
3677 AvChDen[prim] /= area;
3678 AvAsgndChDen[prim] /= area;
3679 }
3680
3681 neBEMState = 9;
3682
3683 return (0);
3684} // end of neBEMReadSolution
INTFACEGLOBAL int neBEMState
neBEMGLOBAL double VFloatCon
Definition: neBEM.h:128

Referenced by neBEMSolve().

◆ RecFlux()

neBEMGLOBAL void RecFlux ( int  src,
Point3D localPt,
Vector3D Flux 
)

Definition at line 227 of file ComputeProperties.c.

227 {
228 if (DebugLevel == 301) {
229 printf("In RecFlux ...\n");
230 }
231
232 double xpt = localP->X;
233 double ypt = localP->Y;
234 double zpt = localP->Z;
235
236 double a = (EleArr + ele - 1)->G.LX;
237 double b = (EleArr + ele - 1)->G.LZ;
238 double diag = sqrt(a * a + b * b); // diagonal of the element
239
240 // distance of field point from element centroid
241 double dist = sqrt(xpt * xpt + ypt * ypt + zpt * zpt);
242
243 // no re-scaling necessary for `E'
244 if (dist >= FarField * diag) {
245 const double f = a * b / (dist * dist * dist);
246 localF->X = xpt * f;
247 localF->Y = ypt * f;
248 localF->Z = zpt * f;
249 } else {
250 double Pot;
251 int fstatus =
252 ExactRecSurf(xpt / a, ypt / a, zpt / a, -0.5, -(b / a) / 2.0,
253 0.5, (b / a) / 2.0, &Pot, localF);
254 if (fstatus) { // non-zero
255 printf("problem in computing flux of rectangular element ... \n");
256 // printf("returning ...\n");
257 // return -1; void function at present
258 }
259 }
260
261#ifdef __cplusplus
262 localF->X *= InvFourPiEps0;
263 localF->Y *= InvFourPiEps0;
264 localF->Z *= InvFourPiEps0;
265#else
266 localF->X /= MyFACTOR;
267 localF->Y /= MyFACTOR;
268 localF->Z /= MyFACTOR;
269#endif
270} // end of RecFlux
int ExactRecSurf(double X, double Y, double Z, double xlo, double zlo, double xhi, double zhi, double *Potential, Vector3D *Flux)
Definition: Isles.c:40
#define FarField
Definition: Isles.h:21

Referenced by ContinuityKnCh(), GetFlux(), GetFluxGCS(), and SatisfyContinuity().

◆ RecPF()

neBEMGLOBAL void RecPF ( double  a,
double  b,
double  x,
double  y,
double  z,
double *  Pot,
Vector3D Flux 
)

Definition at line 4376 of file ComputeProperties.c.

4377 {
4378 const double d2 = x * x + y * y + z * z;
4379 if (d2 >= FarField2 * (a * a + b * b)) {
4380 (*Potential) = a * b / sqrt(d2);
4381 const double f = (*Potential) / d2;
4382 localF->X = x * f;
4383 localF->Y = y * f;
4384 localF->Z = z * f;
4385 } else {
4386 int fstatus =
4387 ExactRecSurf(x / a, y / a, z / a, -0.5, -(b / a) / 2.0,
4388 0.5, (b / a) / 2.0, Potential, localF);
4389 if (fstatus) { // non-zero
4390 printf("problem in RecPF ... \n");
4391 // printf("returning ...\n");
4392 // return -1; void function at present
4393 }
4394 (*Potential) *= a; // rescale - cannot be done outside because of the `if'
4395 }
4396
4397} // end of RecPF
#define FarField2
Definition: Isles.h:22

Referenced by GetPF(), and GetPFGCS().

◆ RecPot()

neBEMGLOBAL double RecPot ( int  src,
Point3D localPt 
)

Definition at line 56 of file ComputeProperties.c.

56 {
57 if (DebugLevel == 301) {
58 printf("In RecPot ...\n");
59 }
60
61 double Pot;
62 Vector3D Field;
63 double xpt = localP->X;
64 double ypt = localP->Y;
65 double zpt = localP->Z;
66
67 double a = (EleArr + ele - 1)->G.LX;
68 double b = (EleArr + ele - 1)->G.LZ;
69 double diag = sqrt(a * a + b * b); // diagonal of the element
70
71 // distance of field point from element centroid
72 double dist = sqrt(xpt * xpt + ypt * ypt + zpt * zpt);
73
74 if (dist >= FarField * diag) // all are distances and, hence, +ve
75 {
76 double dA = a * b;
77 Pot = dA / dist;
78 } else {
79 // normalize distances by `a' while sending - likely to improve accuracy
80 int fstatus =
81 ExactRecSurf(xpt / a, ypt / a, zpt / a, -0.5, -(b / a) / 2.0,
82 0.5, (b / a) / 2.0, &Pot, &Field);
83 if (fstatus) // non-zero
84 {
85 printf("problem in computing Potential of rectangular element ... \n");
86 printf("a: %lg, b: %lg, X: %lg, Y: %lg, Z: %lg\n", a, b, xpt, ypt, zpt);
87 // printf("returning ...\n");
88 // return -1; void function at present
89 }
90 Pot *= a; // rescale Potential - cannot be done outside because of the `if'
91 }
92
93#ifdef __cplusplus
94 return Pot * InvFourPiEps0;
95#else
96 return (Pot / MyFACTOR);
97#endif
98} // end of RecPot

Referenced by GetPotential(), and SatisfyValue().

◆ RecPrimPF()

neBEMGLOBAL void RecPrimPF ( int  src,
Point3D localPt,
double *  Pot,
Vector3D Flux 
)

Definition at line 4499 of file ComputeProperties.c.

4499 {
4500 double xpt = localP->X;
4501 double ypt = localP->Y;
4502 double zpt = localP->Z;
4503 double dist = sqrt(xpt * xpt + ypt * ypt + zpt * zpt);
4504
4505 double a = PrimLX[prim];
4506 double b = PrimLZ[prim];
4507 double diag = sqrt(a * a + b * b); // diagonal
4508
4509 if (dist >= FarField * diag) {
4510 double dA = a * b; // area
4511 (*Potential) = dA / dist;
4512 const double f = dA / (dist * dist * dist);
4513 localF->X = xpt * f;
4514 localF->Y = ypt * f;
4515 localF->Z = zpt * f;
4516 } else {
4517 int fstatus =
4518 ExactRecSurf(xpt / a, ypt / a, zpt / a, -0.5, -(b / a) / 2.0,
4519 0.5, (b / a) / 2.0, Potential, localF);
4520 if (fstatus) { // non-zero
4521 printf("problem in RecPrimPF ... \n");
4522 // printf("returning ...\n");
4523 // return -1; void function at present
4524 }
4525 (*Potential) *= a; // rescale - cannot be done outside because of the `if'
4526 }
4527
4528} // end of RecPrimPF

Referenced by GetPrimPF(), and GetPrimPFGCS().

◆ ReflectOnMirror()

neBEMGLOBAL Point3D ReflectOnMirror ( char  Axis,
int  elesrc,
Point3D  srcpt,
Point3D  fieldpt,
double  distance,
DirnCosn3D DirCos 
)

Definition at line 3831 of file neBEM.c.

3832 {
3833 Vector3D n; // define mirror by a bi-vector perpendicular to it
3834 Point3D Image; // reflected point by mirror assumed at origin
3835
3836 switch (Axis) {
3837 case 'x':
3838 case 'X':
3839 n.X = 1.0;
3840 n.Y = 0.0;
3841 n.Z = 0.0;
3842
3843 Image = ReflectPoint3DByMirrorAtOrigin(&srcpt, &n);
3844 Image.X += 2.0 * distance;
3845
3846 MirroredDC->XUnit.X = -(EleArr + elesrc - 1)->G.DC.XUnit.X;
3847 MirroredDC->XUnit.Y = (EleArr + elesrc - 1)->G.DC.XUnit.Y;
3848 MirroredDC->XUnit.Z = (EleArr + elesrc - 1)->G.DC.XUnit.Z;
3849 MirroredDC->YUnit.X = -(EleArr + elesrc - 1)->G.DC.YUnit.X;
3850 MirroredDC->YUnit.Y = (EleArr + elesrc - 1)->G.DC.YUnit.Y;
3851 MirroredDC->YUnit.Z = (EleArr + elesrc - 1)->G.DC.YUnit.Z;
3852 MirroredDC->ZUnit.X = -(EleArr + elesrc - 1)->G.DC.ZUnit.X;
3853 MirroredDC->ZUnit.Y = (EleArr + elesrc - 1)->G.DC.ZUnit.Y;
3854 MirroredDC->ZUnit.Z = (EleArr + elesrc - 1)->G.DC.ZUnit.Z;
3855 break;
3856
3857 case 'y':
3858 case 'Y':
3859 n.X = 0.0;
3860 n.Y = 1.0;
3861 n.Z = 0.0;
3862
3863 Image = ReflectPoint3DByMirrorAtOrigin(&srcpt, &n);
3864 Image.Y += 2.0 * distance;
3865
3866 MirroredDC->XUnit.X = (EleArr + elesrc - 1)->G.DC.XUnit.X;
3867 MirroredDC->XUnit.Y = -(EleArr + elesrc - 1)->G.DC.XUnit.Y;
3868 MirroredDC->XUnit.Z = (EleArr + elesrc - 1)->G.DC.XUnit.Z;
3869 MirroredDC->YUnit.X = (EleArr + elesrc - 1)->G.DC.YUnit.X;
3870 MirroredDC->YUnit.Y = -(EleArr + elesrc - 1)->G.DC.YUnit.Y;
3871 MirroredDC->YUnit.Z = (EleArr + elesrc - 1)->G.DC.YUnit.Z;
3872 MirroredDC->ZUnit.X = (EleArr + elesrc - 1)->G.DC.ZUnit.X;
3873 MirroredDC->ZUnit.Y = -(EleArr + elesrc - 1)->G.DC.ZUnit.Y;
3874 MirroredDC->ZUnit.Z = (EleArr + elesrc - 1)->G.DC.ZUnit.Z;
3875 break;
3876
3877 case 'z':
3878 case 'Z':
3879 n.X = 0.0;
3880 n.Y = 0.0;
3881 n.Z = 1.0;
3882
3883 Image = ReflectPoint3DByMirrorAtOrigin(&srcpt, &n);
3884 Image.Z += 2.0 * distance;
3885
3886 MirroredDC->XUnit.X = (EleArr + elesrc - 1)->G.DC.XUnit.X;
3887 MirroredDC->XUnit.Y = (EleArr + elesrc - 1)->G.DC.XUnit.Y;
3888 MirroredDC->XUnit.Z = -(EleArr + elesrc - 1)->G.DC.XUnit.Z;
3889 MirroredDC->YUnit.X = (EleArr + elesrc - 1)->G.DC.YUnit.X;
3890 MirroredDC->YUnit.Y = (EleArr + elesrc - 1)->G.DC.YUnit.Y;
3891 MirroredDC->YUnit.Z = -(EleArr + elesrc - 1)->G.DC.YUnit.Z;
3892 MirroredDC->ZUnit.X = (EleArr + elesrc - 1)->G.DC.ZUnit.X;
3893 MirroredDC->ZUnit.Y = (EleArr + elesrc - 1)->G.DC.ZUnit.Y;
3894 MirroredDC->ZUnit.Z = -(EleArr + elesrc - 1)->G.DC.ZUnit.Z;
3895 break;
3896
3897 default:
3898 printf("Axis not chosen properly!!! No reflection occurred!\n");
3899 Image.X = srcpt.X;
3900 Image.Y = srcpt.Y;
3901 Image.Z = srcpt.Z;
3902 } // switch on Axis ends
3903
3904 // printf("Axis: %c, distance: %lg\n", Axis, distance);
3905 // printf("srcpt: %lg, %lg, %lg\n", srcpt.X, srcpt.Y, srcpt.Z);
3906 // printf("Image: %lg, %lg, %lg\n", Image.X, Image.Y, Image.Z);
3907 // getchar();
3908
3909 // traslated to ECS origin, but axes direction as in global system
3910 Point3D globalP, localP;
3911 globalP.X = fldpt.X - Image.X;
3912 globalP.Y = fldpt.Y - Image.Y;
3913 globalP.Z = fldpt.Z - Image.Z;
3914
3915 // entirely in ECS
3916 return (localP = RotatePoint3D(&globalP, MirroredDC, global2local));
3917} // ReflectOnMirror ends
Point3D ReflectPoint3DByMirrorAtOrigin(Point3D *p1, Vector3D *n)
Definition: Vector.c:467

Referenced by ElePFAtPoint(), and LHMatrix().

◆ ReflectPrimitiveOnMirror()

neBEMGLOBAL Point3D ReflectPrimitiveOnMirror ( char  Axis,
int  prim,
Point3D  srcpt,
Point3D  fieldpt,
double  distance,
DirnCosn3D DirCos 
)

Definition at line 3742 of file neBEM.c.

3744 {
3745 Vector3D n; // define mirror by a bi-vector perpendicular to it
3746 Point3D Image; // reflected point by mirror assumed at origin
3747
3748 switch (Axis) {
3749 case 'x':
3750 case 'X':
3751 n.X = 1.0;
3752 n.Y = 0.0;
3753 n.Z = 0.0;
3754
3755 Image = ReflectPoint3DByMirrorAtOrigin(&srcpt, &n);
3756 Image.X += 2.0 * distance;
3757
3758 MirroredDC->XUnit.X = -PrimDC[primsrc].XUnit.X;
3759 MirroredDC->XUnit.Y = PrimDC[primsrc].XUnit.Y;
3760 MirroredDC->XUnit.Z = PrimDC[primsrc].XUnit.Z;
3761 MirroredDC->YUnit.X = -PrimDC[primsrc].YUnit.X;
3762 MirroredDC->YUnit.Y = PrimDC[primsrc].YUnit.Y;
3763 MirroredDC->YUnit.Z = PrimDC[primsrc].YUnit.Z;
3764 MirroredDC->ZUnit.X = -PrimDC[primsrc].ZUnit.X;
3765 MirroredDC->ZUnit.Y = PrimDC[primsrc].ZUnit.Y;
3766 MirroredDC->ZUnit.Z = PrimDC[primsrc].ZUnit.Z;
3767 break;
3768
3769 case 'y':
3770 case 'Y':
3771 n.X = 0.0;
3772 n.Y = 1.0;
3773 n.Z = 0.0;
3774
3775 Image = ReflectPoint3DByMirrorAtOrigin(&srcpt, &n);
3776 Image.Y += 2.0 * distance;
3777
3778 MirroredDC->XUnit.X = PrimDC[primsrc].XUnit.X;
3779 MirroredDC->XUnit.Y = -PrimDC[primsrc].XUnit.Y;
3780 MirroredDC->XUnit.Z = PrimDC[primsrc].XUnit.Z;
3781 MirroredDC->YUnit.X = PrimDC[primsrc].YUnit.X;
3782 MirroredDC->YUnit.Y = -PrimDC[primsrc].YUnit.Y;
3783 MirroredDC->YUnit.Z = PrimDC[primsrc].YUnit.Z;
3784 MirroredDC->ZUnit.X = PrimDC[primsrc].ZUnit.X;
3785 MirroredDC->ZUnit.Y = -PrimDC[primsrc].ZUnit.Y;
3786 MirroredDC->ZUnit.Z = PrimDC[primsrc].ZUnit.Z;
3787 break;
3788
3789 case 'z':
3790 case 'Z':
3791 n.X = 0.0;
3792 n.Y = 0.0;
3793 n.Z = 1.0;
3794
3795 Image = ReflectPoint3DByMirrorAtOrigin(&srcpt, &n);
3796 Image.Z += 2.0 * distance;
3797
3798 MirroredDC->XUnit.X = PrimDC[primsrc].XUnit.X;
3799 MirroredDC->XUnit.Y = PrimDC[primsrc].XUnit.Y;
3800 MirroredDC->XUnit.Z = -PrimDC[primsrc].XUnit.Z;
3801 MirroredDC->YUnit.X = PrimDC[primsrc].YUnit.X;
3802 MirroredDC->YUnit.Y = PrimDC[primsrc].YUnit.Y;
3803 MirroredDC->YUnit.Z = -PrimDC[primsrc].YUnit.Z;
3804 MirroredDC->ZUnit.X = PrimDC[primsrc].ZUnit.X;
3805 MirroredDC->ZUnit.Y = PrimDC[primsrc].ZUnit.Y;
3806 MirroredDC->ZUnit.Z = -PrimDC[primsrc].ZUnit.Z;
3807 break;
3808
3809 default:
3810 printf("Axis not chosen properly!!! No reflection occurred!\n");
3811 Image.X = srcpt.X;
3812 Image.Y = srcpt.Y;
3813 Image.Z = srcpt.Z;
3814 } // switch on Axis ends
3815
3816 // printf("Axis: %c, distance: %lg\n", Axis, distance);
3817 // printf("srcpt: %lg, %lg, %lg\n", srcpt.X, srcpt.Y, srcpt.Z);
3818 // printf("Image: %lg, %lg, %lg\n", Image.X, Image.Y, Image.Z);
3819 // getchar();
3820
3821 // traslated to ECS origin, but axes direction as in global system
3822 Point3D globalP, localP;
3823 globalP.X = fldpt.X - Image.X;
3824 globalP.Y = fldpt.Y - Image.Y;
3825 globalP.Z = fldpt.Z - Image.Z;
3826
3827 // entirely in ECS
3828 return (localP = RotatePoint3D(&globalP, MirroredDC, global2local));
3829} // ReflectPrimtiveOnMirror ends here

Referenced by ElePFAtPoint().

◆ SatisfyContinuity()

neBEMGLOBAL double SatisfyContinuity ( int  fld,
int  src,
Point3D localPt,
DirnCosn3D DirCos 
)

Definition at line 1724 of file neBEM.c.

1725 {
1726 if (DebugLevel == 301) {
1727 printf("In SatisfyContinuity ...\n");
1728 }
1729
1730 double value = 0.0;
1731 Vector3D localF, globalF;
1732
1733 // For self-influence, lmsrc is equal to lmfld which allows the following.
1734 // Additional conditions on distances ensure that periodic copies are not
1735 // treated as `self'.
1736 // Here, we have the additional problem of correctly treating the
1737 // self-influence of traingular elements for which the co-ordinate origin
1738 // does not coincide with the barycentre and thus elesrc and elefld
1739 // are separated from each other by lx/3 and lz/3 in X and Z,
1740 // respectively. The Y coordinates match, however, since the element
1741 // local coordinate system has the Y=0 plane coinciding with the element
1742 // on which the element is lying.
1743 // Since elefld and elesrc are the same for self-influence, etsrc can either
1744 // be 4 or 5. So, the check on the value of etsrc is superfluous, and two
1745 // separate if blocks are merged into one.
1746 // Check for other "special" cases!
1747 if ((elefld == elesrc) &&
1748 (fabs(localP->X) < (EleArr + elesrc - 1)->G.LX / 2.0) &&
1749 (fabs(localP->Y) < MINDIST) &&
1750 (fabs(localP->Z) <
1751 (EleArr + elesrc - 1)->G.LZ / 2.0)) // self-inf for DD intrfc
1752 { // consistent with eqn 18 of Bardhan's paper where lmsrc is inverse
1753 value = 1.0 / (2.0 * EPS0 * (EleArr + elesrc - 1)->E.Lambda);
1754 } // of the multiplying factor of roe(r). EPS0 arises due to electrostatics.
1755 else {
1756 value = 0.0;
1757 // Following fluxes in the influencing ECS
1758 switch ((EleArr + elesrc - 1)->G.Type) {
1759 case 4: // rectangular element
1760 RecFlux(elesrc, localP, &localF);
1761 break;
1762 case 3: // triangular element
1763 TriFlux(elesrc, localP, &localF);
1764 break;
1765 case 2: // linear (wire) element
1766 WireFlux(elesrc, localP, &localF);
1767 break;
1768 default:
1769 printf("Geometrical type out of range! ... exiting ...\n");
1770 exit(-1);
1771 break; // never comes here
1772 } // switch over gtsrc ends
1773
1774 // flux in the global co-ordinate system
1775 // globalF = RotateVector3D(&localF, &(EleArr+elesrc-1)->G.DC,
1776 // local2global);
1777 globalF = RotateVector3D(&localF, DirCos, local2global);
1778
1779 // Fluxes in the influenced ECS co-ordinate system
1780 localF =
1781 RotateVector3D(&globalF, &(EleArr + elefld - 1)->G.DC, global2local);
1782
1783 value = -localF.Y;
1784 // normal derivative of Green's function is - normal force
1785 // (changed from -Fy to +Fy on 02/11/11 - CHECK!!!);
1786 // From = to +=, further change on 04/11/11; Reverted + to - on 05/11/11
1787 } // else self-influence
1788
1789 return (value);
1790} // end of SatisfyContinuity

Referenced by ComputeInfluence().

◆ SatisfyValue()

neBEMGLOBAL double SatisfyValue ( int  src,
Point3D localPt 
)

Definition at line 1686 of file neBEM.c.

1686 {
1687 if (DebugLevel == 301) {
1688 printf("In SatisfyValue ...\n");
1689 }
1690
1691 double value;
1692
1693 switch ((EleArr + elesrc - 1)->G.Type) {
1694 case 4: // rectangular element
1695 value = RecPot(elesrc, localP);
1696 return (value);
1697 // return(value/dA);
1698 break;
1699 case 3: // triangular element
1700 value = TriPot(elesrc, localP);
1701 return (value);
1702 // return(value/dA);
1703 break;
1704 case 2: // linear (wire) element
1705 value = WirePot(elesrc, localP);
1706 return (value);
1707 // return(value/dA);
1708 break;
1709 default:
1710 printf("Geometrical type out of range! ... exiting ...\n");
1711 return (-1);
1712 break; // never comes here
1713 } // switch over gtsrc ends
1714} // end of SatisfyValue

Referenced by ComputeInfluence().

◆ SurfaceElements()

neBEMGLOBAL int SurfaceElements ( int  prim,
int  nvertex,
double  xvert[],
double  yvert[],
double  zvert[],
double  xnorm,
double  ynorm,
double  znorm,
int  volref1,
int  volref2,
int  inttype,
double  potential,
double  charge,
double  lambda,
int  NbSegX,
int  NbSegZ 
)

Definition at line 33 of file ReTriM.c.

36 {
37 // Decide the geometry of this primitive - if it is a rectangle, our job is
38 // greatly simplified. To begin with, we check the number of vertices to
39 // take the decision automatically.
40 // Note that a triangle is the next best bet. All other primitive will have to
41 // be reduced to rectangles (as many as possible) and triangles.
42 // Incidentally, a PrimType (determined in neBEMReadGeom (neBEMInterface.c))
43 // determines whether the primitive is a surface (2D) or a wire (1D),
44 // for a given surface, SurfShape determines whether it is a triangle,
45 // rectangle, or any other polygon besides these two (square is, of course, a
46 // special case of rectangle)
47 int fstatus;
48 switch (nvertex) {
49 case 3: // triangle
50 fstatus = DiscretizeTriangle(prim, nvertex, xvert, yvert, zvert, xnorm,
51 ynorm, znorm, volref1, volref2, inttype,
52 potential, charge, lambda, NbSegX, NbSegZ);
53 // assert(fstatus == 0);
54 if (fstatus != 0) {
55 neBEMMessage("SurfaceElements - DiscretizeTriangle");
56 return -1;
57 }
58 break;
59
60 case 4: // rectangle
61 fstatus = DiscretizeRectangle(prim, nvertex, xvert, yvert, zvert, xnorm,
62 ynorm, znorm, volref1, volref2, inttype,
63 potential, charge, lambda, NbSegX, NbSegZ);
64 // assert(fstatus == 0);
65 if (fstatus != 0) {
66 neBEMMessage("SurfaceElements - DiscretizeRectangle");
67 return -1;
68 }
69 break;
70
71 default:
72 printf("nvertex out of bounds in SurfaceElements ... exiting ...\n");
73 exit(-1);
74 }
75
76 return (0);
77} // end of SurfaceElements
int DiscretizeRectangle(int prim, int nvertex, double xvert[], double yvert[], double zvert[], double xnorm, double ynorm, double znorm, int volref1, int volref2, int inttype, double potential, double charge, double lambda, int NbSegX, int NbSegZ)
Definition: ReTriM.c:1590
int DiscretizeTriangle(int prim, int nvertex, double xvert[], double yvert[], double zvert[], double xnorm, double ynorm, double znorm, int volref1, int volref2, int inttype, double potential, double charge, double lambda, int NbSegX, int NbSegZ)
Definition: ReTriM.c:788

Referenced by neBEMDiscretize().

◆ TriFlux()

neBEMGLOBAL void TriFlux ( int  src,
Point3D localPt,
Vector3D Flux 
)

Definition at line 273 of file ComputeProperties.c.

273 {
274 if (DebugLevel == 301) {
275 printf("In TriFlux ...\n");
276 }
277
278 double xpt = localP->X;
279 double ypt = localP->Y;
280 double zpt = localP->Z;
281
282 double a = (EleArr + ele - 1)->G.LX;
283 double b = (EleArr + ele - 1)->G.LZ;
284 double diag = sqrt(a * a + b * b); // diagonal of the element
285
286 // printf("In TriFlux\n");
287 // printf("a: %lg, b: %lg, X: %lg, Y: %lg, Z: %lg\n", a, b, X, Y, Z);
288
289 // distance of field point from element centroid
290 const double xm = xpt - a / 3.;
291 const double zm = zpt - b / 3.;
292 double dist = sqrt(xm * xm + ypt * ypt + zm * zm);
293
294 if (dist >= FarField * diag) {
295 const double f = 0.5 * a * b / (dist * dist * dist);
296 localF->X = xpt * f;
297 localF->Y = ypt * f;
298 localF->Z = zpt * f;
299 } else {
300 double Pot;
301 int fstatus = ExactTriSurf(b / a, xpt / a, ypt / a, zpt / a, &Pot, localF);
302 // fstatus = ApproxTriSurf(b/a, X/a, Y/a, Z/a, 5000, 5000, &Pot, &Flux);
303 if (fstatus) { // non-zero
304 printf("problem in computing flux of triangular element ... \n");
305 // printf("returning ...\n");
306 // return -1; void function at present
307 }
308 }
309
310#ifdef __cplusplus
311 localF->X *= InvFourPiEps0;
312 localF->Y *= InvFourPiEps0;
313 localF->Z *= InvFourPiEps0;
314#else
315 localF->X /= MyFACTOR;
316 localF->Y /= MyFACTOR;
317 localF->Z /= MyFACTOR;
318#endif
319 // printf("Pot: %lg, Ex: %lg, Ey: %lg, Ez: %lg\n",
320 // Pot, localF.X, localF.Y, localF.Z);
321 // printf("Out of TriFlux\n");
322} // end of TriFlux
int ExactTriSurf(double zMax, double X, double Y, double Z, double *Potential, Vector3D *Flux)
Definition: Isles.c:784

Referenced by ContinuityKnCh(), GetFlux(), GetFluxGCS(), and SatisfyContinuity().

◆ TriPF()

neBEMGLOBAL void TriPF ( double  a,
double  b,
double  x,
double  y,
double  z,
double *  Pot,
Vector3D Flux 
)

Definition at line 4400 of file ComputeProperties.c.

4401 {
4402 // printf("In TriPF\n");
4403 const double xm = x - a / 3.;
4404 const double zm = z - b / 3.;
4405 const double d2 = xm * xm + y * y + zm * zm;
4406
4407 if (d2 >= FarField2 * (a * a + b * b)) {
4408 (*Potential) = 0.5 * a * b / sqrt(d2);
4409 const double f = (*Potential) / d2;
4410 localF->X = x * f;
4411 localF->Y = y * f;
4412 localF->Z = z * f;
4413 } else {
4414 int fstatus = ExactTriSurf(b / a, x / a, y / a, z / a, Potential, localF);
4415 if (fstatus) { // non-zero
4416 printf("problem in TriPF ... \n");
4417 // printf("returning ...\n");
4418 // return -1; void function at present
4419 }
4420 (*Potential) *= a; // rescale - cannot be done outside because of the `if'
4421 }
4422 // printf("Out of TriPF\n");
4423} // end of TriPF

Referenced by GetPF(), and GetPFGCS().

◆ TriPot()

neBEMGLOBAL double TriPot ( int  src,
Point3D localPt 
)

Definition at line 101 of file ComputeProperties.c.

101 {
102 if (DebugLevel == 301) {
103 printf("In TriPot ...\n");
104 }
105
106 double Pot;
107 Vector3D Field;
108 double xpt = localP->X;
109 double ypt = localP->Y;
110 double zpt = localP->Z;
111
112 // distance of field point from element centroid
113 double a = (EleArr + ele - 1)->G.LX;
114 double b = (EleArr + ele - 1)->G.LZ;
115 // largest side (hypotenuse) of the element
116 double diag = sqrt(a * a + b * b);
117
118 const double xm = xpt - a / 3.;
119 const double zm = zpt - b / 3.;
120 double dist = sqrt(xm * xm + ypt * ypt + zm * zm);
121
122 if (dist >= FarField * diag) {
123 double dA = 0.5 * a * b; // area of the triangular element
124 Pot = dA / dist;
125 } else {
126 int fstatus = ExactTriSurf(b / a, xpt / a, ypt / a, zpt / a, &Pot, &Field);
127 if (fstatus) { // non-zero
128 printf("problem in computing Potential of triangular element ... \n");
129 printf("a: %lg, b: %lg, X: %lg, Y: %lg, Z: %lg\n", a, b, xpt, ypt, zpt);
130 // printf("returning ...\n");
131 // return -1; void function at present
132 }
133 Pot *= a; // rescale Potential
134 }
135
136#ifdef __cplusplus
137 return Pot * InvFourPiEps0;
138#else
139 return (Pot / MyFACTOR);
140#endif
141} // end of TriPot

Referenced by GetPotential(), and SatisfyValue().

◆ TriPrimPF()

neBEMGLOBAL void TriPrimPF ( int  src,
Point3D localPt,
double *  Pot,
Vector3D Flux 
)

Definition at line 4532 of file ComputeProperties.c.

4532 {
4533 double xpt = localP->X;
4534 double ypt = localP->Y;
4535 double zpt = localP->Z;
4536 double a = PrimLX[prim];
4537 double b = PrimLZ[prim];
4538 // longest side (hypotenuse)
4539 double diag = sqrt(a * a + b * b);
4540 const double xm = xpt - a / 3.;
4541 const double zm = zpt - b / 3.;
4542 double dist = sqrt(xm * xm + ypt * ypt + zm * zm);
4543
4544 if (dist >= FarField * diag) {
4545 double dA = 0.5 * a * b; // area
4546 (*Potential) = dA / dist;
4547 double f = dA / (dist * dist * dist);
4548 localF->X = xpt * f;
4549 localF->Y = ypt * f;
4550 localF->Z = zpt * f;
4551 } else {
4552 int fstatus =
4553 ExactTriSurf(b / a, xpt / a, ypt / a, zpt / a, Potential, localF);
4554 if (fstatus) // non-zero
4555 {
4556 printf("problem in TriPrimPF ... \n");
4557 }
4558 (*Potential) *= a; // rescale - cannot be done outside because of the `if'
4559 }
4560
4561 // printf("Out of TriPrimPF\n");
4562} // end of TriPrimPF

Referenced by GetPrimPF(), and GetPrimPFGCS().

◆ ValueChUp()

neBEMGLOBAL double ValueChUp ( int  fld)

Definition at line 2367 of file neBEM.c.

2367 {
2368
2369 printf("In ValueChUp ...\n");
2370
2371 // prepare LHMatrix to compute EffectChUp
2372 if (!InfluenceMatrixFlag) {
2373 printf("Influence matrix NOT in memory ...\n");
2374
2376 printf("reading influence coefficient matrix from formatted file...\n");
2377
2378 char InflFile[256];
2379 strcpy(InflFile, MeshOutDir);
2380 strcat(InflFile, "/Infl.out");
2381 FILE *fInf = fopen(InflFile, "r");
2382 // assert(fInf != NULL);
2383 if (fInf == NULL) {
2384 neBEMMessage("Solve - InflFile in OptValidate.");
2385 return 1;
2386 }
2387
2388 int chkNbEqns, chkNbUnknowns;
2389 fscanf(fInf, "%d %d\n", &chkNbEqns, &chkNbUnknowns);
2390 if ((chkNbEqns != NbEqns) || (chkNbUnknowns != NbUnknowns)) {
2391 neBEMMessage("Solve - matrix dimension do not match!");
2392 return (-1);
2393 }
2394
2395 printf("Solve: Matrix dimensions: %d equations, %d unknowns\n", NbEqns,
2396 NbUnknowns);
2397
2398 Inf = dmatrix(1, NbEqns, 1, NbUnknowns);
2399
2400 for (int ifld = 1; ifld <= NbEqns; ++ifld)
2401 for (int jsrc = 1; jsrc <= NbUnknowns; ++jsrc)
2402 fscanf(fInf, "%le\n", &Inf[ifld][jsrc]);
2403 fclose(fInf);
2404 } else {
2405 printf("repeating influence coefficient matrix computation ...\n");
2406
2407 int fstatus = LHMatrix();
2408 // assert(fstatus == 0);
2409 if (fstatus != 0) {
2410 neBEMMessage("Solve - LHMatrix in OptRepeatLHMatrix");
2411 return -1;
2412 }
2413 }
2414
2416 neBEMMessage("Solve - Binary read of Infl matrix not implemented yet.\n");
2417 } // if OptStoreInflMatrix and Unformatted file
2418
2420 } // if(!InfluenceMatrixFlag)
2421
2422 // This approach works because Inf is supposed to contain information of
2423 // repetitions, mirrors and other geometrical attributes of the system
2424 double value = 0.0;
2425 for (int elesrc = 1; elesrc <= NbElements; ++elesrc) {
2426 value += Inf[elefld][elesrc] * (EleArr + elesrc - 1)->Assigned;
2427 if (0) {
2428 printf("elesrc, Inf, Assigned, value: %d, %lg, %lg, %lg\n", elesrc,
2429 Inf[elefld][elesrc], (EleArr + elesrc - 1)->Assigned, value);
2430 }
2431 }
2432
2433 printf("Exiting ValueChUp ...\n");
2434 return value;
2435} // ValueChUp ends
neBEMGLOBAL int OptFormattedFile
Definition: neBEM.h:49
neBEMGLOBAL int OptStoreInflMatrix
Definition: neBEM.h:47
neBEMGLOBAL int OptUnformattedFile
Definition: neBEM.h:50
double ** dmatrix(long nrl, long nrh, long ncl, long nch)
Definition: nrutil.c:97

Referenced by EffectChUp().

◆ ValueKnCh()

neBEMGLOBAL double ValueKnCh ( int  fld)

Definition at line 2035 of file neBEM.c.

2035 {
2036 int dbgFn = 0;
2037
2038 double value = 0.0;
2039 double xfld = (EleArr + elefld - 1)->BC.CollPt.X;
2040 double yfld = (EleArr + elefld - 1)->BC.CollPt.Y;
2041 double zfld = (EleArr + elefld - 1)->BC.CollPt.Z;
2042
2043 // Retrieve element properties at the field point
2044 // Location needed for Dirichlet (potential)
2045 Point3D localP, globalP; // globalP is useful here
2046
2047 // OMPCheck - parallelize
2048
2049 // Effect of known charges on the interface elements
2050 for (int elesrc = 1; elesrc <= NbElements; ++elesrc) {
2051 double assigned = (EleArr + elesrc - 1)->Assigned;
2052 if (fabs(assigned) <= 1.0e-16) continue;
2053
2054 // Retrieve element properties from the structure
2055 if ((EleArr + elesrc - 1)->E.Type == 0) {
2056 printf("Wrong EType for elesrc %d element %d on %dth primitive!\n",
2057 elesrc, (EleArr + elesrc - 1)->Id,
2058 (EleArr + elesrc - 1)->PrimitiveNb);
2059 exit(-1);
2060 }
2061
2062 Point3D *pOrigin = &(EleArr + elesrc - 1)->G.Origin;
2063
2064 // translated to local origin but axes direction as in GCS
2065 globalP.X = xfld - pOrigin->X; // used later
2066 globalP.Y = yfld - pOrigin->Y;
2067 globalP.Z = zfld - pOrigin->Z;
2068
2069 { // Rotate point3D from global to local system
2070 double TransformationMatrix[3][3] = {{0.0, 0.0, 0.0},
2071 {0.0, 0.0, 0.0},
2072 {0.0, 0.0, 0.0}};
2073 DirnCosn3D *DirCos = &(EleArr + elesrc - 1)->G.DC;
2074
2075 TransformationMatrix[0][0] = DirCos->XUnit.X;
2076 TransformationMatrix[0][1] = DirCos->XUnit.Y;
2077 TransformationMatrix[0][2] = DirCos->XUnit.Z;
2078 TransformationMatrix[1][0] = DirCos->YUnit.X;
2079 TransformationMatrix[1][1] = DirCos->YUnit.Y;
2080 TransformationMatrix[1][2] = DirCos->YUnit.Z;
2081 TransformationMatrix[2][0] = DirCos->ZUnit.X;
2082 TransformationMatrix[2][1] = DirCos->ZUnit.Y;
2083 TransformationMatrix[2][2] = DirCos->ZUnit.Z;
2084
2085 double InitialVector[3] = {xfld - pOrigin->X, yfld - pOrigin->Y, zfld - pOrigin->Z};
2086 double FinalVector[3] = {0., 0., 0.};
2087 for (int i = 0; i < 3; ++i) {
2088 for (int j = 0; j < 3; ++j) {
2089 FinalVector[i] += TransformationMatrix[i][j] * InitialVector[j];
2090 }
2091 }
2092
2093 localP.X = FinalVector[0];
2094 localP.Y = FinalVector[1];
2095 localP.Z = FinalVector[2];
2096 } // Point3D rotated
2097
2098 switch ((EleArr + elesrc - 1)->G.Type) {
2099 case 4: // rectangular element
2100 value += assigned * RecPot(elesrc, &localP);
2101 // return(value/dA);
2102 break;
2103 case 3: // triangular element
2104 value += assigned * TriPot(elesrc, &localP);
2105 // return(value/dA);
2106 break;
2107 case 2: // linear (wire) element
2108 value += assigned * WirePot(elesrc, &localP);
2109 // return(value/dA);
2110 break;
2111 default:
2112 printf("Geometrical type out of range! ... exiting ...\n");
2113 exit(-1);
2114 break; // never comes here
2115 } // switch over gtsrc ends
2116 } // for all source elements - elesrc
2117
2118 if (dbgFn) {
2119 printf("value after known charges on elements: %g\n", value);
2120 }
2121
2122 // Contribution due to known point charges
2123 Vector3D tmpglobalF; // flux not being used to evaluate Dirichlet value.
2124 for (int point = 1; point <= NbPointsKnCh; ++point) {
2125 value += (PointKnChArr + point - 1)->Assigned *
2126 PointKnChPF((PointKnChArr + point - 1)->P, globalP, &tmpglobalF) /
2127 MyFACTOR;
2128 } // for all points
2129 if (dbgFn) {
2130 printf("value after known charges at points: %g\n", value);
2131 }
2132
2133 // Contribution due to known line charges
2134 for (int line = 1; line <= NbLinesKnCh; ++line) {
2135 value +=
2136 (LineKnChArr + line - 1)->Assigned *
2137 LineKnChPF((LineKnChArr + line - 1)->Start,
2138 (LineKnChArr + line - 1)->Stop,
2139 (LineKnChArr + line - 1)->Radius, globalP, &tmpglobalF) /
2140 MyFACTOR;
2141 } // for lines
2142 if (dbgFn) {
2143 printf("value after known charges on lines: %g\n", value);
2144 }
2145
2146 // Contribution due to known area charges
2147 for (int area = 1; area <= NbAreasKnCh; ++area) {
2148 value +=
2149 (AreaKnChArr + area - 1)->Assigned *
2150 AreaKnChPF((AreaKnChArr + area - 1)->NbVertices,
2151 ((AreaKnChArr + area - 1)->Vertex), globalP, &tmpglobalF) /
2152 MyFACTOR;
2153 } // for areas
2154 if (dbgFn) {
2155 printf("value after known charges on areas: %g\n", value);
2156 }
2157
2158 // Contribution due to known volume charges
2159 for (int vol = 1; vol <= NbVolumesKnCh; ++vol) {
2160 value += (VolumeKnChArr + vol - 1)->Assigned *
2161 VolumeKnChPF((VolumeKnChArr + vol - 1)->NbVertices,
2162 ((VolumeKnChArr + vol - 1)->Vertex), globalP,
2163 &tmpglobalF) /
2164 MyFACTOR;
2165 } // for vols
2166 if (dbgFn) {
2167 printf("value after known charges in volumes: %g\n", value);
2168 }
2169
2170 return (value);
2171} // end of ValueKnCh

Referenced by EffectKnCh().

◆ VoxelFPR()

neBEMGLOBAL int VoxelFPR ( void  )

Definition at line 1402 of file ComputeProperties.c.

1402 {
1403 int dbgFn = 0;
1404 int fstatus;
1405
1406 int nbXCells;
1407 int nbYCells;
1408 int nbZCells;
1409 double startX;
1410 double startY;
1411 double startZ;
1412 double delX;
1413 double delY;
1414 double delZ;
1415
1416 printf("\nPotential and field computation for voxelized data export\n");
1417
1418 char VoxelFile[256];
1419 FILE *fVoxel;
1420 strcpy(VoxelFile, BCOutDir);
1421 strcat(VoxelFile, "/VoxelFPR.out");
1422 fVoxel = fopen(VoxelFile, "w");
1423 if (fVoxel == NULL) {
1424 neBEMMessage("VoxelFPR - VoxelFile");
1425 return -1;
1426 }
1427 fprintf(
1428 fVoxel,
1429 "# X(cm)\tY(cm)\tZ(cm)\tFX(V/cm)\tFY(V/cm)\tFZ(V/cm)\tPot(V)\tRegion\n");
1430
1431 if (dbgFn) {
1432 printf("VoxelFPR.out created ...\n");
1433 fflush(stdout);
1434 }
1435
1436 nbXCells = Voxel.NbXCells;
1437 nbYCells = Voxel.NbYCells;
1438 nbZCells = Voxel.NbZCells;
1439 startX = Voxel.Xmin;
1440 startY = Voxel.Ymin;
1441 startZ = Voxel.Zmin;
1442 delX = (Voxel.Xmax - Voxel.Xmin) / nbXCells;
1443 delY = (Voxel.Ymax - Voxel.Ymin) / nbYCells;
1444 delZ = (Voxel.Zmax - Voxel.Zmin) / nbZCells;
1445
1446 int ivol; // relates XYZ position to volume number
1447 double *VoxelFX, *VoxelFY, *VoxelFZ, *VoxelP;
1448 VoxelFX = dvector(0, nbZCells + 1);
1449 VoxelFY = dvector(0, nbZCells + 1);
1450 VoxelFZ = dvector(0, nbZCells + 1);
1451 VoxelP = dvector(0, nbZCells + 1);
1452
1453 if (dbgFn) {
1454 printf("nbXCells, nbYCells, nbZCells: %d, %d, %d\n", nbXCells, nbYCells,
1455 nbZCells);
1456 printf("startX, startY, startZ: %le, %le, %le\n", startX, startY, startZ);
1457 printf("delX, delY, delZ: %le, %le, %le\n", delX, delY, delZ);
1458 fflush(stdout);
1459 }
1460
1461 for (int i = 1; i <= nbXCells + 1; ++i) {
1462 for (int j = 1; j <= nbYCells + 1; ++j) {
1463 if (dbgFn) {
1464 printf("VoxelFPR => i: %4d, j: %4d", i, j);
1465 fflush(stdout);
1466 }
1467
1468 Point3D point;
1469#ifdef _OPENMP
1470 int nthreads = 1, tid = 0;
1471 #pragma omp parallel private(nthreads, tid)
1472#endif
1473 {
1474#ifdef _OPENMP
1475 if (dbgFn) {
1476 tid = omp_get_thread_num();
1477 if (tid == 0) {
1478 nthreads = omp_get_num_threads();
1479 printf("Starting voxel computation with %d threads\n", nthreads);
1480 }
1481 }
1482#endif
1483 int k;
1484 Vector3D field;
1485 double potential;
1486#ifdef _OPENMP
1487 #pragma omp for private(k, point, potential, field)
1488#endif
1489 for (k = 1; k <= nbZCells + 1; ++k) {
1490 potential = 0.0;
1491 field.X = field.Y = field.Z = 0.0;
1492
1493 point.X = startX + (i - 1) * delX; // all 3 components need to be
1494 point.Y = startY + (j - 1) * delY; // evaluated after pragma omp
1495 point.Z = startZ + (k - 1) * delZ;
1496
1497 if (dbgFn) {
1498 printf("i, j, k: %d, %d, %d\n", i, j, k);
1499 printf("point X, Y, Z: %.8lg\t%.8lg\t%.8lg\n",
1500 point.X / LengthScale, point.Y / LengthScale,
1501 point.Z / LengthScale);
1502 fflush(stdout);
1503 }
1504
1505 fstatus = PFAtPoint(&point, &potential, &field);
1506 if (fstatus != 0) {
1507 neBEMMessage("wrong PFAtPoint return value in VoxelFPR\n");
1508 // return -1;
1509 }
1510
1511 if (dbgFn) {
1512 printf("%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\n",
1513 point.X / LengthScale, point.Y / LengthScale,
1514 point.Z / LengthScale, field.X, field.Y, field.Z,
1515 potential / LengthScale);
1516 fflush(stdout);
1517 }
1518
1519 VoxelFX[k] = field.X;
1520 VoxelFY[k] = field.Y;
1521 VoxelFZ[k] = field.Z;
1522 VoxelP[k] = potential;
1523 } // loop k
1524 } // pragma omp parallel
1525
1526 for (int k = 1; k <= nbZCells + 1; ++k) // file output
1527 {
1528 point.X = startX + (i - 1) * delX;
1529 point.Y = startY + (j - 1) * delY;
1530 point.Z = startZ + (k - 1) * delZ;
1531
1532 ivol = neBEMVolumePoint(point.X, point.Y, point.Z);
1533 /*
1534 volMaterial[ivol]; // region linked to material
1535 neBEMVolumeDescription(ivol, &vshp, &vmat, &veps, &vpot, &vq, &vtype);
1536if(dbgFn)
1537{
1538printf("volref: %d\n", ivol);
1539printf("shape: %d, material: %d\n", volShape[ivol], volMaterial[ivol]);
1540printf("eps: %d, pot: %d\n", volEpsilon[ivol], volPotential[ivol]);
1541printf("q: %d, type: %d\n", volCharge[ivol], volBoundaryType[ivol]);
1542printf("shape: %d, material: %d\n", vshp, vmat);
1543printf("eps: %d, pot: %d\n", veps, vpot);
1544printf("q: %d, type: %d\n", vq, vtype);
1545}
1546 */
1547
1548 fprintf(fVoxel,
1549 "%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%4d\n",
1550 100.0 * point.X / LengthScale, 100.0 * point.Y / LengthScale,
1551 100.0 * point.Z / LengthScale, VoxelFX[k] / 100.0,
1552 VoxelFY[k] / 100.0, VoxelFZ[k] / 100.0, VoxelP[k] / LengthScale,
1553 ivol + 1);
1554 }
1555 fflush(fVoxel); // file output over
1556
1557 // printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
1558 } // loop j
1559 } // loop i
1560
1561 fclose(fVoxel);
1562
1563 free_dvector(VoxelFX, 0, nbZCells + 1);
1564 free_dvector(VoxelFY, 0, nbZCells + 1);
1565 free_dvector(VoxelFZ, 0, nbZCells + 1);
1566 free_dvector(VoxelP, 0, nbZCells + 1);
1567
1568 return 0;
1569} // end of VoxelFPR
neBEMGLOBAL VoxelVol Voxel
Definition: neBEM.h:371
double Zmax
Definition: neBEM.h:363
double Xmax
Definition: neBEM.h:359
int NbXCells
Definition: neBEM.h:367
double Ymax
Definition: neBEM.h:361
double Zmin
Definition: neBEM.h:362
int NbZCells
Definition: neBEM.h:369
int NbYCells
Definition: neBEM.h:368
double Xmin
Definition: neBEM.h:358
double Ymin
Definition: neBEM.h:360

Referenced by neBEMSolve().

◆ WeightingFieldSolution()

neBEMGLOBAL int WeightingFieldSolution ( int  NbPrimsWtField,
int  PrimListWtField[],
double  WtFieldChDen[] 
)

Definition at line 3688 of file neBEM.c.

3689 {
3690 // Check for the inverted matrix
3691 if (!InvMat) {
3692 printf(
3693 "WeightingFieldSolution: Capacitance matrix not in memory, can not "
3694 "calculate weighting charges.\n");
3695 return (-1);
3696 }
3697
3698 for (int i = 1; i <= NbUnknowns; i++) solnarray[i] = 0.0;
3699
3700 for (int ele = 1, InList; ele <= NbElements; ++ele) {
3701 int prim = (EleArr + ele - 1)->PrimitiveNb;
3702
3703 InList = 0; // assume that this prim is not in the list
3704 for (int primwtfl = 0; primwtfl < NbPrimsWtField; ++primwtfl) {
3705 if (prim == PrimListWtField[primwtfl]) {
3706 InList = 1;
3707 break; // get out of the for loop
3708 }
3709 } // for primwtfl
3710
3711 if (InList) {
3712 for (int i = 1; i <= NbUnknowns; ++i) {
3713 solnarray[i] += InvMat[i][ele];
3714 }
3715 }
3716 } // for ele
3717
3718 return (0);
3719} // WtFieldSolution ends
neBEMGLOBAL double ** InvMat
Definition: neBEM.h:237

Referenced by neBEMPrepareWeightingField().

◆ WireElements()

neBEMGLOBAL int WireElements ( int  prim,
int  nvertex,
double  xvert[],
double  yvert[],
double  zvert[],
double  radius,
int  volref1,
int  volref2,
int  inttype,
double  potential,
double  charge,
double  lambda,
int  NbWireSeg 
)

Definition at line 82 of file ReTriM.c.

85 {
86 int fstatus;
87
88 switch (nvertex) {
89 case 2: // wire
90 fstatus =
91 DiscretizeWire(prim, nvertex, xvert, yvert, zvert, radius, volref1,
92 volref2, inttype, potential, charge, lambda, NbSegs);
93 // assert(fstatus == 0);
94 if (fstatus != 0) {
95 neBEMMessage("WireElements - DiscretizeWire");
96 return -1;
97 }
98 break;
99
100 default:
101 printf("nvertex out of bounds in WireElements ... exiting ...\n");
102 exit(-1);
103 }
104
105 return (0);
106} // end of WireElement
int DiscretizeWire(int prim, int nvertex, double xvert[], double yvert[], double zvert[], double radius, int volref1, int volref2, int inttype, double potential, double charge, double lambda, int NbSegs)
Definition: ReTriM.c:409

Referenced by neBEMDiscretize().

◆ WireFlux()

neBEMGLOBAL void WireFlux ( int  src,
Point3D localPt,
Vector3D Flux 
)

Definition at line 325 of file ComputeProperties.c.

325 {
326 if (DebugLevel == 301) {
327 printf("In WireFlux ...\n");
328 }
329
330 double xpt = localP->X;
331 double ypt = localP->Y;
332 double zpt = localP->Z;
333 double rW = (EleArr + ele - 1)->G.LX;
334 double lW = (EleArr + ele - 1)->G.LZ;
335
336 // field point from element centroid
337 double dist = sqrt(xpt * xpt + ypt * ypt + zpt * zpt);
338
339 if (dist >= FarField * lW) {
340 const double f = 2.0 * ST_PI * rW * lW / (dist * dist * dist);
341 localF->X = xpt * f;
342 localF->Y = ypt * f;
343 localF->Z = zpt * f;
344 } else {
345 if ((fabs(xpt) < MINDIST) && (fabs(ypt) < MINDIST)) {
346 localF->X = localF->Y = 0.0;
347 } else {
348 localF->X = ExactThinFX_W(rW, lW, xpt, ypt, zpt);
349
350 localF->Y = ExactThinFY_W(rW, lW, xpt, ypt, zpt);
351 }
352
353 // Ez
354 localF->Z = ExactThinFZ_W(rW, lW, xpt, ypt, zpt);
355 }
356
357#ifdef __cplusplus
358 localF->X *= InvFourPiEps0;
359 localF->Y *= InvFourPiEps0;
360 localF->Z *= InvFourPiEps0;
361#else
362 localF->X /= MyFACTOR;
363 localF->Y /= MyFACTOR;
364 localF->Z /= MyFACTOR;
365#endif
366} // end of WireFlux
double ExactThinFX_W(double rW, double lW, double X, double Y, double Z)
Definition: Isles.c:2103
double ExactThinFY_W(double rW, double lW, double X, double Y, double Z)
Definition: Isles.c:2121
double ExactThinFZ_W(double rW, double lW, double X, double Y, double Z)
Definition: Isles.c:2139
#define ST_PI
Definition: Isles.h:24

Referenced by ContinuityKnCh(), GetFlux(), GetFluxGCS(), and SatisfyContinuity().

◆ WirePF()

neBEMGLOBAL void WirePF ( double  rW,
double  lW,
double  x,
double  y,
double  z,
double *  Pot,
Vector3D Flux 
)

Definition at line 4426 of file ComputeProperties.c.

4427 {
4428 const double d2 = x * x + y * y + z * z;
4429 if (d2 >= FarField2 * lW * lW) {
4430 double dA = 2.0 * ST_PI * rW * lW;
4431 const double dist = sqrt(d2);
4432 (*Potential) = dA / dist;
4433 double f = dA / (dist * d2);
4434 localF->X = x * f;
4435 localF->Y = y * f;
4436 localF->Z = z * f;
4437 } else {
4438 if ((fabs(x) < MINDIST) && (fabs(y) < MINDIST)) {
4439 if (fabs(z) < MINDIST)
4440 (*Potential) = ExactCentroidalP_W(rW, lW);
4441 else
4442 (*Potential) = ExactAxialP_W(rW, lW, z);
4443
4444 localF->X = localF->Y = 0.0;
4445 localF->Z = ExactThinFZ_W(rW, lW, x, y, z);
4446 } else {
4447 ExactThinWire(rW, lW, x, y, z, Potential, localF);
4448 }
4449 }
4450} // end of WirePF
double ExactCentroidalP_W(double rW, double lW)
Definition: Isles.c:1779
double ExactAxialP_W(double rW, double lW, double Z)
Definition: Isles.c:1789
int ExactThinWire(double rW, double lW, double X, double Y, double Z, double *potential, Vector3D *Flux)
Definition: Isles.c:2155

Referenced by GetPF(), and GetPFGCS().

◆ WirePot()

neBEMGLOBAL double WirePot ( int  src,
Point3D localPt 
)

Definition at line 145 of file ComputeProperties.c.

145 {
146 if (DebugLevel == 301) {
147 printf("In WirePot ...\n");
148 }
149
150 double Pot;
151 double xpt = localP->X;
152 double ypt = localP->Y;
153 double zpt = localP->Z;
154
155 double rW = (EleArr + ele - 1)->G.LX;
156 double lW = (EleArr + ele - 1)->G.LZ;
157
158 // field point from element centroid
159 double dist = sqrt(xpt * xpt + ypt * ypt + zpt * zpt);
160
161 if (dist >= FarField * lW) // all are distances and, hence, +ve
162 {
163 double dA = 2.0 * ST_PI * rW * lW;
164 // Pot = ApproxP_W(rW, lW, X, Y, Z, 1);
165 Pot = dA / dist;
166 } else if ((fabs(xpt) < MINDIST) && (fabs(ypt) < MINDIST) &&
167 (fabs(zpt) < MINDIST)) {
168 Pot = ExactCentroidalP_W(rW, lW);
169 } else if ((fabs(xpt) < MINDIST) && (fabs(ypt) < MINDIST)) {
170 Pot = ExactAxialP_W(rW, lW, localP->Z);
171 } else {
172 Pot = ExactThinP_W(rW, lW, xpt, ypt, zpt);
173 }
174
175#ifdef __cplusplus
176 return Pot * InvFourPiEps0;
177#else
178 return (Pot / MyFACTOR);
179#endif
180} // end of WirePot
double ExactThinP_W(double rW, double lW, double X, double Y, double Z)
Definition: Isles.c:2088

Referenced by GetPotential(), and SatisfyValue().

◆ WirePrimPF()

neBEMGLOBAL void WirePrimPF ( int  src,
Point3D localPt,
double *  Pot,
Vector3D Flux 
)

Definition at line 4565 of file ComputeProperties.c.

4566 {
4567 double xpt = localP->X;
4568 double ypt = localP->Y;
4569 double zpt = localP->Z;
4570 double rW = Radius[prim];
4571 double lW = PrimLZ[prim];
4572 double dist =
4573 sqrt(xpt * xpt + ypt * ypt + zpt * zpt); // fld pt from ele cntrd
4574
4575 if (dist >= FarField * lW) // all are distances and, hence, +ve
4576 {
4577 double dA = 2.0 * ST_PI * rW * lW;
4578 (*Potential) = dA / dist;
4579 double f = dA / (dist * dist * dist);
4580 localF->X = xpt * f;
4581 localF->Y = ypt * f;
4582 localF->Z = zpt * f;
4583 } else {
4584 if ((fabs(xpt) < MINDIST) && (fabs(ypt) < MINDIST)) {
4585 if (fabs(zpt) < MINDIST)
4586 (*Potential) = ExactCentroidalP_W(rW, lW);
4587 else
4588 (*Potential) = ExactAxialP_W(rW, lW, zpt);
4589
4590 localF->X = localF->Y = 0.0;
4591 localF->Z = ExactThinFZ_W(rW, lW, xpt, ypt, zpt);
4592 } else {
4593 ExactThinWire(rW, lW, xpt, ypt, zpt, Potential, localF);
4594 }
4595 }
4596} // end of WirePrimPF

Referenced by GetPrimPF(), and GetPrimPFGCS().

◆ WtFldFastPFAtPoint()

neBEMGLOBAL int WtFldFastPFAtPoint ( Point3D globalPt,
double *  Pot,
Vector3D Flux 
)

Definition at line 3826 of file ComputeProperties.c.

3826 {
3827 int dbgFn = 0;
3828 double Xpt = globalP->X;
3829 double Ypt = globalP->Y;
3830 double Zpt = globalP->Z;
3831 double RptVolLX = WtFldFastVol.LX;
3832 double RptVolLY = WtFldFastVol.LY;
3833 double RptVolLZ = WtFldFastVol.LZ;
3834 double CornerX = WtFldFastVol.CrnrX;
3835 double CornerY = WtFldFastVol.CrnrY;
3836 double CornerZ = WtFldFastVol.CrnrZ;
3837 double TriLin(double xd, double yd, double zd, double c000, double c100,
3838 double c010, double c001, double c110, double c101, double c011,
3839 double c111);
3840
3841 // First of all, check how the point in question should be treated ...
3842
3843 // Check whether the point falls within a volume that is not regarded as
3844 // FastVol
3845 for (int ignore = 1; ignore <= WtFldFastVol.NbIgnoreVols; ++ignore) {
3846 if ((Xpt >= (WtFldIgnoreVolCrnrX[ignore])) &&
3847 (Xpt <= (WtFldIgnoreVolCrnrX[ignore] + WtFldIgnoreVolLX[ignore])) &&
3848 (Ypt >= (WtFldIgnoreVolCrnrY[ignore])) &&
3849 (Ypt <= (WtFldIgnoreVolCrnrY[ignore] + WtFldIgnoreVolLY[ignore])) &&
3850 (Zpt >= (WtFldIgnoreVolCrnrZ[ignore])) &&
3851 (Zpt <= (WtFldIgnoreVolCrnrZ[ignore] + WtFldIgnoreVolLZ[ignore]))) {
3852 if (dbgFn)
3853 neBEMMessage("In WtFldFastPFAtPoint: point in an ignored volume!\n");
3854
3855 // KnCh does not have any effect
3856 int fstatus = ElePFAtPoint(globalP, Potential, globalF);
3857 if (fstatus != 0) {
3858 neBEMMessage("wrong WtFldPFAtPoint return value in FastVolPF.\n");
3859 return -1;
3860 } else
3861 return 0;
3862 }
3863 } // loop over ignored volumes
3864
3865 // If not ignored, the point qualifies for FastVol evaluation ...
3866
3867 // for a staggered fast volume, the volume repeated in X is larger
3869 RptVolLX += WtFldFastVol.LX;
3870 }
3871 if (dbgFn) {
3872 printf("\nin WtFldFastPFAtPoint\n");
3873 printf("x, y, z: %g, %g, %g\n", Xpt, Ypt, Zpt);
3874 printf("RptVolLX, RptVolLY, RptVolLZ: %g, %g, %g\n", RptVolLX, RptVolLY,
3875 RptVolLZ);
3876 printf("CornerX, CornerY, CornerZ: %g, %g, %g\n", CornerX, CornerY,
3877 CornerZ);
3878 printf("Nb of blocks: %d\n", WtFldFastVol.NbBlocks);
3879 for (int block = 1; block <= WtFldFastVol.NbBlocks; ++block) {
3880 printf("NbOfXCells: %d\n", WtFldBlkNbXCells[block]);
3881 printf("NbOfYCells: %d\n", WtFldBlkNbYCells[block]);
3882 printf("NbOfZCells: %d\n", WtFldBlkNbZCells[block]);
3883 printf("LZ: %le\n", WtFldBlkLZ[block]);
3884 printf("CornerZ: %le\n", WtFldBlkCrnrZ[block]);
3885 }
3886 }
3887
3888 // Find equivalent position inside the basic / staggered volume.
3889 // real distance from volume corner
3890 double dx = Xpt - CornerX;
3891 double dy = Ypt - CornerY;
3892 double dz = Zpt - CornerZ;
3893 if (dbgFn)
3894 printf("real dx, dy, dz from volume corner: %g, %g, %g\n", dx, dy, dz);
3895
3896 int NbFastVolX = (int)(dx / RptVolLX);
3897 if (dx < 0.0) --NbFastVolX;
3898 int NbFastVolY = (int)(dy / RptVolLY);
3899 if (dy < 0.0) --NbFastVolY;
3900 int NbFastVolZ = (int)(dz / RptVolLZ);
3901 if (dz < 0.0) --NbFastVolZ;
3902 if (dbgFn)
3903 printf("Volumes in x, y, z: %d, %d, %d\n", NbFastVolX, NbFastVolY,
3904 NbFastVolZ);
3905
3906 // equivalent distances from fast volume corner
3907 dx -= NbFastVolX * RptVolLX;
3908 dy -= NbFastVolY * RptVolLY;
3909 dz -= NbFastVolZ * RptVolLZ;
3910 // The following conditions should never happen - generate an error message
3911 if (dx < 0.0) {
3912 dx = 0.0;
3913 neBEMMessage("equiv dx < 0.0 - not correct!\n");
3914 }
3915 if (dy < 0.0) {
3916 dy = 0.0;
3917 neBEMMessage("equiv dy < 0.0 - not correct!\n");
3918 }
3919 if (dz < 0.0) {
3920 dz = 0.0;
3921 neBEMMessage("equiv dz < 0.0 - not correct!\n");
3922 }
3923 if (dx > RptVolLX) {
3924 dx = RptVolLX;
3925 neBEMMessage("equiv dx > RptVolLX - not correct!\n");
3926 }
3927 if (dy > RptVolLY) {
3928 dy = RptVolLY;
3929 neBEMMessage("equiv dy > RptVolLY - not correct!\n");
3930 }
3931 if (dz > RptVolLZ) {
3932 dz = RptVolLZ;
3933 neBEMMessage("equiv dz > RptVolLZ - not correct!\n");
3934 }
3935 if (dbgFn)
3936 printf("equivalent dist from corner - dx, dy, dz: %g, %g, %g\n", dx, dy,
3937 dz);
3938
3939 // Take care of possible trouble-makers
3940 if (dx < MINDIST) dx = MINDIST; // -ve dx has already been made equal to 0
3941 if (dy < MINDIST) dy = MINDIST;
3942 if (dz < MINDIST) dz = MINDIST;
3943 if ((RptVolLX - dx) < MINDIST)
3944 dx = RptVolLX - MINDIST; // dx > RptVolLX taken care of
3945 if ((RptVolLY - dy) < MINDIST) dy = RptVolLY - MINDIST;
3946 if ((RptVolLZ - dz) < MINDIST) dz = RptVolLZ - MINDIST;
3947 // For staggered volumes, there is another plane where difficulties may occur
3948 if ((dx <= WtFldFastVol.LX) && (WtFldFastVol.LX - dx) < MINDIST)
3949 dx = WtFldFastVol.LX - MINDIST;
3950 else if ((dx > WtFldFastVol.LX) && (fabs(WtFldFastVol.LX - dx) < MINDIST))
3951 dx = WtFldFastVol.LX + MINDIST;
3952 if (dbgFn)
3953 printf("equivalent dist adjusted - dx, dy, dz: %g, %g, %g\n", dx, dy, dz);
3954
3955 // If volume is staggered, we have a few more things to do before finalizing
3956 // the values of equivalent distance
3957 // sector identification
3958 // _................__________________
3959 // | . . | Sector 3 |
3960 // | . . | |
3961 // | . | . |
3962 // | | . . |
3963 // | Sector 2 | . . |
3964 // |----------------| . . |
3965 // | | . |
3966 // | . | |
3967 // | . . | |
3968 // | . . |----------------|
3969 // | . . | Sector 4 |
3970 // | . | . |
3971 // | | . . |
3972 // | Sector 1 | . . |
3973 // |----------------|................|
3974
3975 int sector = 1; // kept outside `if' since this is necessary further below
3977 if ((dx >= 0.0) && (dx <= WtFldFastVol.LX) && (dy >= 0.0) &&
3978 (dy <= WtFldFastVol.LY)) {
3979 // point lies in sector 1, everything remains unchanged
3980 sector = 1;
3981 } else if ((dx >= 0.0) && (dx <= WtFldFastVol.LX) &&
3982 (dy > WtFldFastVol.LY) &&
3984 // point lies in sector 2, move basic volume one step up
3985 sector = 2;
3986 ++NbFastVolY;
3987 CornerY += WtFldFastVol.LY; // repeat length in Y is LY
3988 dy -= WtFldFastVol.LY;
3989 } else if ((dx > WtFldFastVol.LX) && (dx <= 2.0 * WtFldFastVol.LX) &&
3990 (dy >= WtFldFastVol.YStagger) &&
3992 // point lies in sector 3, pt in staggered vol, change corner coords
3993 sector = 3;
3994 CornerX += WtFldFastVol.LX;
3995 CornerY += WtFldFastVol.YStagger;
3996 dx -= WtFldFastVol.LX;
3997 dy -= WtFldFastVol.YStagger;
3998 } else if ((dx > WtFldFastVol.LX) && (dx <= 2.0 * WtFldFastVol.LX) &&
3999 (dy >= 0.0) && (dy < WtFldFastVol.YStagger)) {
4000 // point lies in sector 4, move basic volume one step down and consider
4001 // staggered fast volume
4002 sector = 4;
4003 --NbFastVolY;
4004 CornerX +=
4005 WtFldFastVol.LX; // in the staggered part of the repeated volume
4006 CornerY -= (WtFldFastVol.LY - WtFldFastVol.YStagger);
4007 dx -= WtFldFastVol.LX;
4009 } else {
4010 neBEMMessage("WtFldFastPFAtPoint: point in none of the sectors!\n");
4011 }
4012 if (dbgFn) printf("stagger modified dx, dy, dz: %g, %g, %g\n", dx, dy, dz);
4013 }
4014
4015 // Take care of possible trouble-makers - once more
4016 if (dx < MINDIST) dx = MINDIST; // -ve dx has already been made equal to 0
4017 if (dy < MINDIST) dy = MINDIST;
4018 if (dz < MINDIST) dz = MINDIST;
4019 if ((RptVolLX - dx) < MINDIST)
4020 dx = RptVolLX - MINDIST; // dx > RptVolLX taken care of
4021 if ((RptVolLY - dy) < MINDIST) dy = RptVolLY - MINDIST;
4022 if ((RptVolLZ - dz) < MINDIST) dz = RptVolLZ - MINDIST;
4023 // For staggered volumes, there is another plane where difficulties may occur
4024 if ((dx <= WtFldFastVol.LX) && (WtFldFastVol.LX - dx) < MINDIST)
4025 dx = WtFldFastVol.LX - MINDIST;
4026 else if ((dx > WtFldFastVol.LX) && (fabs(WtFldFastVol.LX - dx) < MINDIST))
4027 dx = WtFldFastVol.LX + MINDIST;
4028 if (dbgFn)
4029 printf("equivalent dist adjusted for staggered: %g, %g, %g\n", dx, dy, dz);
4030
4031 /*
4032 // Check whether the point falls within a volume that is omitted
4033 for(int omit = 1; omit <= WtFldFastVol.NbOmitVols; ++omit)
4034 {
4035 if((dx >= (WtFldOmitVolCrnrX[omit]-WtFldFastVol.CrnrX))
4036 && (dx <=
4037 (WtFldOmitVolCrnrX[omit]+WtFldOmitVolLX[omit]-WtFldFastVol.CrnrX))
4038 && (dy >=
4039 (WtFldOmitVolCrnrY[omit]-WtFldFastVol.CrnrY))
4040 && (dy <=
4041 (WtFldOmitVolCrnrY[omit]+WtFldOmitVolLY[omit]-WtFldFastVol.CrnrY))
4042 && (dz >=
4043 (WtFldOmitVolCrnrZ[omit]-WtFldFastVol.CrnrZ))
4044 && (dz <=
4045 (WtFldOmitVolCrnrZ[omit]+WtFldOmitVolLZ[omit]-WtFldFastVol.CrnrZ)))
4046 {
4047 neBEMMessage("In FastPFAtPoint: point in an omitted
4048 volume!\n"); *Potential = 0.0; globalF->X = 0.0; globalF->Y = 0.0; globalF->Z
4049 = 0.0;
4050 }
4051 } // loop over omitted volumes
4052 */
4053
4054 // Find the block in which the point lies
4055 /*
4056 int thisBlock = 1;
4057 if(WtFldFastVol.NbBlocks > 1)
4058 {
4059 for(int block = 1; block <= WtFldFastVol.NbBlocks; ++block)
4060 {
4061 if(dbgFn)
4062 {
4063 printf("dz,(WtFldBlkCrnrZ-CornerZ),(WtFldBlkCrnrZ+WtFldBlkLZ-CornerZ):
4064 %lg, %lg, %lg\n", dz, (WtFldBlkCrnrZ[block]-CornerZ),
4065 (WtFldBlkCrnrZ[block]+WtFldBlkLZ[block]-CornerZ));
4066 }
4067 if((dz >= (WtFldBlkCrnrZ[block]-CornerZ))
4068 && (dz <=
4069 (WtFldBlkCrnrZ[block]+WtFldBlkLZ[block]-CornerZ)))
4070 {
4071 thisBlock = block;
4072 break;
4073 }
4074 }
4075 } // if NbBlocks > 1
4076 */
4077
4078 int thisBlock = 0;
4079 for (int block = 1; block <= WtFldFastVol.NbBlocks; ++block) {
4080 double blkBtmZ = WtFldBlkCrnrZ[block] - CornerZ; // since CornerZ has been
4081 double blkTopZ = blkBtmZ + WtFldBlkLZ[block]; // subtracted from dz already
4082 if (dbgFn) {
4083 printf("block, dz, blkBtmZ, blkTopZ: %d, %lg, %lg, %lg\n", block, dz,
4084 blkBtmZ, blkTopZ);
4085 }
4086
4087 // take care of difficult situations
4088 if ((dz <= blkBtmZ) && ((blkBtmZ - dz) < MINDIST)) dz = blkBtmZ - MINDIST;
4089 if ((dz >= blkBtmZ) && ((dz - blkBtmZ) < MINDIST)) dz = blkBtmZ + MINDIST;
4090 if ((dz <= blkTopZ) && ((blkTopZ - dz) < MINDIST)) dz = blkTopZ - MINDIST;
4091 if ((dz >= blkTopZ) && ((dz - blkTopZ) < MINDIST)) dz = blkTopZ + MINDIST;
4092
4093 if ((dz >= blkBtmZ) && (dz <= blkTopZ)) {
4094 thisBlock = block;
4095 break;
4096 }
4097 }
4098 if (!thisBlock) {
4099 neBEMMessage("WtFldFastPFAtPoint: point in none of the blocks!\n");
4100 }
4101
4102 int nbXCells = WtFldBlkNbXCells[thisBlock];
4103 int nbYCells = WtFldBlkNbYCells[thisBlock];
4104 int nbZCells = WtFldBlkNbZCells[thisBlock];
4105 double delX = WtFldFastVol.LX / nbXCells;
4106 double delY = WtFldFastVol.LY / nbYCells;
4107 double delZ = WtFldBlkLZ[thisBlock] / nbZCells;
4108 dz -= (WtFldBlkCrnrZ[thisBlock] - CornerZ); // distance from the block corner
4109
4110 if (dbgFn) {
4111 printf("thisBlock: %d\n", thisBlock);
4112 printf("nbXCells, nbYCells, nbZCells: %d, %d, %d\n", nbXCells, nbYCells,
4113 nbZCells);
4114 printf("WtFldBlkCrnrZ: %lg\n", WtFldBlkCrnrZ[thisBlock]);
4115 printf("delX, delY, delZ: %le, %le, %le\n", delX, delY, delZ);
4116 printf("dz: %lg\n", dz);
4117 fflush(stdout);
4118 }
4119
4120 // Find cell in block of basic / staggered volume within which the point lies
4121 int celli = (int)(dx / delX) + 1; // Find cell in which the point lies
4122 if (celli < 1) {
4123 celli = 1;
4124 dx = 0.5 * delX;
4125 neBEMMessage("WtFldFastPFAtPoint - celli < 1\n");
4126 }
4127 if (celli > nbXCells) {
4128 celli = nbXCells;
4129 dx = WtFldFastVol.LX - 0.5 * delX;
4130 neBEMMessage("WtFldFastPFAtPoint - celli > nbXCells\n");
4131 }
4132 int cellj = (int)(dy / delY) + 1;
4133 if (cellj < 1) {
4134 cellj = 1;
4135 dy = 0.5 * delY;
4136 neBEMMessage("WtFldFastPFAtPoint - cellj < 1\n");
4137 }
4138 if (cellj > nbYCells) {
4139 cellj = nbYCells;
4140 dy = WtFldFastVol.LY - 0.5 * delY;
4141 neBEMMessage("WtFldFastPFAtPoint - cellj > nbYCells\n");
4142 }
4143 int cellk = (int)(dz / delZ) + 1;
4144 if (cellk < 1) {
4145 cellk = 1;
4146 dz = 0.5 * delX;
4147 neBEMMessage("WtFldFastPFAtPoint - cellk < 1\n");
4148 }
4149 if (cellk > nbZCells) {
4150 cellk = nbZCells;
4151 dz = WtFldFastVol.LZ - 0.5 * delZ;
4152 neBEMMessage("WtFldFastPFAtPoint - cellk > nbZCells\n");
4153 }
4154 if (dbgFn) printf("Cells in x, y, z: %d, %d, %d\n", celli, cellj, cellk);
4155
4156 // Interpolate potential and field at the point using the corner values of
4157 // of the cell and, if necessary, of the neighbouring cells
4158 // These gradients can also be calculated while computing the potential and
4159 // field at the cells and stored in memory, provided enough memory is
4160 // available
4161
4162 // distances from cell corner
4163 double dxcellcrnr = dx - (double)(celli - 1) * delX;
4164 double dycellcrnr = dy - (double)(cellj - 1) * delY;
4165 double dzcellcrnr = dz - (double)(cellk - 1) * delZ;
4166 if (dbgFn)
4167 printf("cell crnr dx, dy, dz: %g, %g, %g\n", dxcellcrnr, dycellcrnr,
4168 dzcellcrnr);
4169
4170 // normalized distances
4171 double xd = dxcellcrnr / delX; // xd = (x-x0)/(x1-x0)
4172 double yd = dycellcrnr / delY; // etc
4173 double zd = dzcellcrnr / delZ;
4174 if (xd <= 0.0) xd = 0.0;
4175 if (yd <= 0.0) yd = 0.0;
4176 if (zd <= 0.0) zd = 0.0;
4177 if (xd >= 1.0) xd = 1.0;
4178 if (yd >= 1.0) yd = 1.0;
4179 if (zd >= 1.0) zd = 1.0;
4180
4181 // corner values of potential and field
4182 double P000 = WtFldFastPot[thisBlock][celli][cellj][cellk]; // lowest corner
4183 double FX000 = WtFldFastFX[thisBlock][celli][cellj][cellk];
4184 double FY000 = WtFldFastFY[thisBlock][celli][cellj][cellk];
4185 double FZ000 = WtFldFastFZ[thisBlock][celli][cellj][cellk];
4186 double P100 = WtFldFastPot[thisBlock][celli + 1][cellj][cellk];
4187 double FX100 = WtFldFastFX[thisBlock][celli + 1][cellj][cellk];
4188 double FY100 = WtFldFastFY[thisBlock][celli + 1][cellj][cellk];
4189 double FZ100 = WtFldFastFZ[thisBlock][celli + 1][cellj][cellk];
4190 double P010 = WtFldFastPot[thisBlock][celli][cellj + 1][cellk];
4191 double FX010 = WtFldFastFX[thisBlock][celli][cellj + 1][cellk];
4192 double FY010 = WtFldFastFY[thisBlock][celli][cellj + 1][cellk];
4193 double FZ010 = WtFldFastFZ[thisBlock][celli][cellj + 1][cellk];
4194 double P001 = WtFldFastPot[thisBlock][celli][cellj][cellk + 1];
4195 double FX001 = WtFldFastFX[thisBlock][celli][cellj][cellk + 1];
4196 double FY001 = WtFldFastFY[thisBlock][celli][cellj][cellk + 1];
4197 double FZ001 = WtFldFastFZ[thisBlock][celli][cellj][cellk + 1];
4198 double P110 = WtFldFastPot[thisBlock][celli + 1][cellj + 1][cellk];
4199 double FX110 = WtFldFastFX[thisBlock][celli + 1][cellj + 1][cellk];
4200 double FY110 = WtFldFastFY[thisBlock][celli + 1][cellj + 1][cellk];
4201 double FZ110 = WtFldFastFZ[thisBlock][celli + 1][cellj + 1][cellk];
4202 double P101 = WtFldFastPot[thisBlock][celli + 1][cellj][cellk + 1];
4203 double FX101 = WtFldFastFX[thisBlock][celli + 1][cellj][cellk + 1];
4204 double FY101 = WtFldFastFY[thisBlock][celli + 1][cellj][cellk + 1];
4205 double FZ101 = WtFldFastFZ[thisBlock][celli + 1][cellj][cellk + 1];
4206 double P011 = WtFldFastPot[thisBlock][celli][cellj + 1][cellk + 1];
4207 double FX011 = WtFldFastFX[thisBlock][celli][cellj + 1][cellk + 1];
4208 double FY011 = WtFldFastFY[thisBlock][celli][cellj + 1][cellk + 1];
4209 double FZ011 = WtFldFastFZ[thisBlock][celli][cellj + 1][cellk + 1];
4210 double P111 = WtFldFastPot[thisBlock][celli + 1][cellj + 1][cellk + 1];
4211 double FX111 = WtFldFastFX[thisBlock][celli + 1][cellj + 1][cellk + 1];
4212 double FY111 = WtFldFastFY[thisBlock][celli + 1][cellj + 1][cellk + 1];
4213 double FZ111 = WtFldFastFZ[thisBlock][celli + 1][cellj + 1][cellk + 1];
4215 if (sector == 1) { // nothing to be done
4216 }
4217 if (sector == 2) { // volume shifted up but point not in the staggered part
4218 }
4219 if (sector == 3) { // staggered volume
4220 P000 = WtFldFastStgPot[thisBlock][celli][cellj][cellk];
4221 FX000 = WtFldFastStgFX[thisBlock][celli][cellj][cellk];
4222 FY000 = WtFldFastStgFY[thisBlock][celli][cellj][cellk];
4223 FZ000 = WtFldFastStgFZ[thisBlock][celli][cellj][cellk];
4224 P100 = WtFldFastStgPot[thisBlock][celli + 1][cellj][cellk];
4225 FX100 = WtFldFastStgFX[thisBlock][celli + 1][cellj][cellk];
4226 FY100 = WtFldFastStgFY[thisBlock][celli + 1][cellj][cellk];
4227 FZ100 = WtFldFastStgFZ[thisBlock][celli + 1][cellj][cellk];
4228 P010 = WtFldFastStgPot[thisBlock][celli][cellj + 1][cellk];
4229 FX010 = WtFldFastStgFX[thisBlock][celli][cellj + 1][cellk];
4230 FY010 = WtFldFastStgFY[thisBlock][celli][cellj + 1][cellk];
4231 FZ010 = WtFldFastStgFZ[thisBlock][celli][cellj + 1][cellk];
4232 P001 = WtFldFastStgPot[thisBlock][celli][cellj][cellk + 1];
4233 FX001 = WtFldFastStgFX[thisBlock][celli][cellj][cellk + 1];
4234 FY001 = WtFldFastStgFY[thisBlock][celli][cellj][cellk + 1];
4235 FZ001 = WtFldFastStgFZ[thisBlock][celli][cellj][cellk + 1];
4236 P110 = WtFldFastStgPot[thisBlock][celli + 1][cellj + 1][cellk];
4237 FX110 = WtFldFastStgFX[thisBlock][celli + 1][cellj + 1][cellk];
4238 FY110 = WtFldFastStgFY[thisBlock][celli + 1][cellj + 1][cellk];
4239 FZ110 = WtFldFastStgFZ[thisBlock][celli + 1][cellj + 1][cellk];
4240 P101 = WtFldFastStgPot[thisBlock][celli + 1][cellj][cellk + 1];
4241 FX101 = WtFldFastStgFX[thisBlock][celli + 1][cellj][cellk + 1];
4242 FY101 = WtFldFastStgFY[thisBlock][celli + 1][cellj][cellk + 1];
4243 FZ101 = WtFldFastStgFZ[thisBlock][celli + 1][cellj][cellk + 1];
4244 P011 = WtFldFastStgPot[thisBlock][celli][cellj + 1][cellk + 1];
4245 FX011 = WtFldFastStgFX[thisBlock][celli][cellj + 1][cellk + 1];
4246 FY011 = WtFldFastStgFY[thisBlock][celli][cellj + 1][cellk + 1];
4247 FZ011 = WtFldFastStgFZ[thisBlock][celli][cellj + 1][cellk + 1];
4248 P111 = WtFldFastStgPot[thisBlock][celli + 1][cellj + 1][cellk + 1];
4249 FX111 = WtFldFastStgFX[thisBlock][celli + 1][cellj + 1][cellk + 1];
4250 FY111 = WtFldFastStgFY[thisBlock][celli + 1][cellj + 1][cellk + 1];
4251 FZ111 = WtFldFastStgFZ[thisBlock][celli + 1][cellj + 1][cellk + 1];
4252 }
4253 if (sector == 4) { // volume shifted down and point in the staggered part
4254 P000 = WtFldFastStgPot[thisBlock][celli][cellj][cellk];
4255 FX000 = WtFldFastStgFX[thisBlock][celli][cellj][cellk];
4256 FY000 = WtFldFastStgFY[thisBlock][celli][cellj][cellk];
4257 FZ000 = WtFldFastStgFZ[thisBlock][celli][cellj][cellk];
4258 P100 = WtFldFastStgPot[thisBlock][celli + 1][cellj][cellk];
4259 FX100 = WtFldFastStgFX[thisBlock][celli + 1][cellj][cellk];
4260 FY100 = WtFldFastStgFY[thisBlock][celli + 1][cellj][cellk];
4261 FZ100 = WtFldFastStgFZ[thisBlock][celli + 1][cellj][cellk];
4262 P010 = WtFldFastStgPot[thisBlock][celli][cellj + 1][cellk];
4263 FX010 = WtFldFastStgFX[thisBlock][celli][cellj + 1][cellk];
4264 FY010 = WtFldFastStgFY[thisBlock][celli][cellj + 1][cellk];
4265 FZ010 = WtFldFastStgFZ[thisBlock][celli][cellj + 1][cellk];
4266 P001 = WtFldFastStgPot[thisBlock][celli][cellj][cellk + 1];
4267 FX001 = WtFldFastStgFX[thisBlock][celli][cellj][cellk + 1];
4268 FY001 = WtFldFastStgFY[thisBlock][celli][cellj][cellk + 1];
4269 FZ001 = WtFldFastStgFZ[thisBlock][celli][cellj][cellk + 1];
4270 P110 = WtFldFastStgPot[thisBlock][celli + 1][cellj + 1][cellk];
4271 FX110 = WtFldFastStgFX[thisBlock][celli + 1][cellj + 1][cellk];
4272 FY110 = WtFldFastStgFY[thisBlock][celli + 1][cellj + 1][cellk];
4273 FZ110 = WtFldFastStgFZ[thisBlock][celli + 1][cellj + 1][cellk];
4274 P101 = WtFldFastStgPot[thisBlock][celli + 1][cellj][cellk + 1];
4275 FX101 = WtFldFastStgFX[thisBlock][celli + 1][cellj][cellk + 1];
4276 FY101 = WtFldFastStgFY[thisBlock][celli + 1][cellj][cellk + 1];
4277 FZ101 = WtFldFastStgFZ[thisBlock][celli + 1][cellj][cellk + 1];
4278 P011 = WtFldFastStgPot[thisBlock][celli][cellj + 1][cellk + 1];
4279 FX011 = WtFldFastStgFX[thisBlock][celli][cellj + 1][cellk + 1];
4280 FY011 = WtFldFastStgFY[thisBlock][celli][cellj + 1][cellk + 1];
4281 FZ011 = WtFldFastStgFZ[thisBlock][celli][cellj + 1][cellk + 1];
4282 P111 = WtFldFastStgPot[thisBlock][celli + 1][cellj + 1][cellk + 1];
4283 FX111 = WtFldFastStgFX[thisBlock][celli + 1][cellj + 1][cellk + 1];
4284 FY111 = WtFldFastStgFY[thisBlock][celli + 1][cellj + 1][cellk + 1];
4285 FZ111 = WtFldFastStgFZ[thisBlock][celli + 1][cellj + 1][cellk + 1];
4286 }
4287 }
4288
4289 double intP =
4290 TriLin(xd, yd, zd, P000, P100, P010, P001, P110, P101, P011, P111);
4291 double intFX = TriLin(xd, yd, zd, FX000, FX100, FX010, FX001, FX110, FX101,
4292 FX011, FX111);
4293 double intFY = TriLin(xd, yd, zd, FY000, FY100, FY010, FY001, FY110, FY101,
4294 FY011, FY111);
4295 double intFZ = TriLin(xd, yd, zd, FZ000, FZ100, FZ010, FZ001, FZ110, FZ101,
4296 FZ011, FZ111);
4297
4298 *Potential = intP;
4299 globalF->X = intFX;
4300 globalF->Y = intFY;
4301 globalF->Z = intFZ;
4302
4303 if (dbgFn) {
4304 printf("WtFldCell corner values:\n");
4305 printf("Potential: %g, %g, %g, %g\n", P000, P100, P010, P001);
4306 printf("Potential: %g, %g, %g, %g\n", P110, P101, P011, P111);
4307 printf("FastFX: %g, %g, %g, %g\n", FX000, FX100, FX010, FX001);
4308 printf("FastFX: %g, %g, %g, %g\n", FX110, FX101, FX011, FX111);
4309 printf("FastFY: %g, %g, %g, %g\n", FY000, FY100, FY010, FY001);
4310 printf("FastFY: %g, %g, %g, %g\n", FY110, FY101, FY011, FY111);
4311 printf("FastFZ: %g, %g, %g, %g\n", FZ000, FZ100, FZ010, FZ001);
4312 printf("FastFZ: %g, %g, %g, %g\n", FZ110, FZ101, FZ011, FZ111);
4313 printf("Pot, FX, FY, FZ: %g, %g, %g, %g\n", *Potential, globalF->X,
4314 globalF->Y, globalF->Z);
4315 }
4316
4317 if (dbgFn) {
4318 printf("out WtFldFastPFAtPoint\n");
4319 fflush(stdout);
4320 }
4321
4322 return 0;
4323} // WtFldFastPFAtPoint ends
neBEMGLOBAL double **** WtFldFastStgFZ
Definition: neBEM.h:515
neBEMGLOBAL double **** WtFldFastFZ
Definition: neBEM.h:513
neBEMGLOBAL int * WtFldBlkNbYCells
Definition: neBEM.h:494
neBEMGLOBAL double **** WtFldFastFX
Definition: neBEM.h:513
neBEMGLOBAL double **** WtFldFastPot
Definition: neBEM.h:512
neBEMGLOBAL int * WtFldBlkNbXCells
Definition: neBEM.h:493
neBEMGLOBAL double * WtFldIgnoreVolCrnrX
Definition: neBEM.h:507
neBEMGLOBAL int OptWtFldStaggerFastVol
Definition: neBEM.h:473
neBEMGLOBAL double **** WtFldFastStgPot
Definition: neBEM.h:514
neBEMGLOBAL double * WtFldIgnoreVolLZ
Definition: neBEM.h:506
neBEMGLOBAL WtFldFastAlgoVol WtFldFastVol
Definition: neBEM.h:491
neBEMGLOBAL double **** WtFldFastFY
Definition: neBEM.h:513
neBEMGLOBAL double * WtFldBlkLZ
Definition: neBEM.h:496
neBEMGLOBAL double * WtFldBlkCrnrZ
Definition: neBEM.h:497
neBEMGLOBAL double **** WtFldFastStgFY
Definition: neBEM.h:515
neBEMGLOBAL int * WtFldBlkNbZCells
Definition: neBEM.h:495
neBEMGLOBAL double * WtFldIgnoreVolCrnrY
Definition: neBEM.h:508
neBEMGLOBAL double * WtFldIgnoreVolCrnrZ
Definition: neBEM.h:509
neBEMGLOBAL double * WtFldIgnoreVolLY
Definition: neBEM.h:505
neBEMGLOBAL double **** WtFldFastStgFX
Definition: neBEM.h:515
neBEMGLOBAL double * WtFldIgnoreVolLX
Definition: neBEM.h:504
int NbIgnoreVols
Definition: neBEM.h:489
double LZ
Definition: neBEM.h:482
double YStagger
Definition: neBEM.h:486
double LY
Definition: neBEM.h:481
double LX
Definition: neBEM.h:480
double CrnrY
Definition: neBEM.h:484
double CrnrX
Definition: neBEM.h:483
double CrnrZ
Definition: neBEM.h:485

Referenced by neBEMWeightingField().

◆ WtFldFastVolPF()

neBEMGLOBAL int WtFldFastVolPF ( void  )

◆ WtPFAtPoint()

neBEMGLOBAL int WtPFAtPoint ( Point3D globalPt,
double *  Pot,
Vector3D Flux,
int  Id 
)

Definition at line 4610 of file ComputeProperties.c.

4611 {
4612 int dbgFn = 0;
4613
4614 const double xfld = globalP->X;
4615 const double yfld = globalP->Y;
4616 const double zfld = globalP->Z;
4617
4618 // Compute Potential and field at different locations
4619 *Potential = globalF->X = globalF->Y = globalF->Z = 0.0;
4620
4621 // Effects due to base primitives and their repetitions are considered in the
4622 // local coordinate system of the primitive (or element), while effects due to
4623 // mirror elements and their repetitions are considered in the global
4624 // coordinate system (GCS). This works because the direction cosines of a
4625 // primitive (and its elements) and those of its repetitions are the same.
4626 // As a result, we can do just one transformation from local to global at the
4627 // end of calculations related to a primitive. This can save substantial
4628 // computation if a discretized version of the primitive is being used since
4629 // we avoid one unnecessary transformation for each element that comprises a
4630 // primitive.
4631 // Begin with primitive description of the device
4632
4633 // Scope in OpenMP: Variables in the global data space are accessible to all
4634 // threads, while variables in a thread's private space is accessible to the
4635 // thread only (there are several variations - copying outside region etc)
4636 // Field point remains the same - kept outside private
4637 // source point changes with change in primitive - private
4638 // TransformationMatrix changes - kept within private (Note: matrices with
4639 // fixed dimensions can be maintained, but those with dynamic allocation
4640 // can not).
4641 double *pPot = dvector(1, NbPrimitives);
4642 double *plFx = dvector(1, NbPrimitives); // field components in LCS
4643 double *plFy = dvector(1, NbPrimitives); // for a primitive
4644 double *plFz = dvector(1, NbPrimitives); // and its other incarnations
4645
4646 for (int prim = 1; prim <= NbPrimitives; ++prim) {
4647 pPot[prim] = plFx[prim] = plFy[prim] = plFz[prim] = 0.0;
4648 }
4649
4650#ifdef _OPENMP
4651 int tid = 0, nthreads = 1;
4652 #pragma omp parallel private(tid, nthreads)
4653#endif
4654 {
4655
4656#ifdef _OPENMP
4657 if (dbgFn) {
4658 tid = omp_get_thread_num();
4659 if (tid == 0) {
4660 nthreads = omp_get_num_threads();
4661 printf("PFAtPoint computation with %d threads\n", nthreads);
4662 }
4663 }
4664#endif
4665// by default, nested parallelization is off in C
4666#ifdef _OPENMP
4667#pragma omp for
4668#endif
4669 for (int primsrc = 1; primsrc <= NbPrimitives; ++primsrc) {
4670 if (dbgFn) {
4671 printf("Evaluating effect of primsrc %d using on %lg, %lg, %lg\n",
4672 primsrc, xfld, yfld, zfld);
4673 fflush(stdout);
4674 }
4675
4676 const double xpsrc = PrimOriginX[primsrc];
4677 const double ypsrc = PrimOriginY[primsrc];
4678 const double zpsrc = PrimOriginZ[primsrc];
4679
4680 // Field in the local frame.
4681 double lFx = 0.;
4682 double lFy = 0.;
4683 double lFz = 0.;
4684
4685 // Set up transform matrix for this primitive, which is also the same
4686 // for all the elements belonging to this primitive.
4687 double TransformationMatrix[3][3];
4688 TransformationMatrix[0][0] = PrimDC[primsrc].XUnit.X;
4689 TransformationMatrix[0][1] = PrimDC[primsrc].XUnit.Y;
4690 TransformationMatrix[0][2] = PrimDC[primsrc].XUnit.Z;
4691 TransformationMatrix[1][0] = PrimDC[primsrc].YUnit.X;
4692 TransformationMatrix[1][1] = PrimDC[primsrc].YUnit.Y;
4693 TransformationMatrix[1][2] = PrimDC[primsrc].YUnit.Z;
4694 TransformationMatrix[2][0] = PrimDC[primsrc].ZUnit.X;
4695 TransformationMatrix[2][1] = PrimDC[primsrc].ZUnit.Y;
4696 TransformationMatrix[2][2] = PrimDC[primsrc].ZUnit.Z;
4697
4698 // The total influence is due to primitives on the basic device and due to
4699 // virtual primitives arising out of repetition, reflection etc and not
4700 // residing on the basic device
4701
4702 { // basic primitive
4703 // point translated to the ECS origin, but axes direction global
4704 Point3D localPP;
4705 { // Rotate point from global to local system
4706 double InitialVector[3] = {xfld - xpsrc, yfld - ypsrc, zfld - zpsrc};
4707 double FinalVector[3] = {0., 0., 0.};
4708 for (int i = 0; i < 3; ++i) {
4709 for (int j = 0; j < 3; ++j) {
4710 FinalVector[i] += TransformationMatrix[i][j] * InitialVector[j];
4711 }
4712 }
4713 localPP.X = FinalVector[0];
4714 localPP.Y = FinalVector[1];
4715 localPP.Z = FinalVector[2];
4716 } // Point3D rotated
4717
4718 // evaluate possibility whether primitive influence is accurate enough
4719 // This could be based on localPP and the subtended solid angle
4720 // If 1, then only primitive influence will be considered
4721 int PrimOK = 0;
4722 if (PrimOK) {
4723 // Potential and flux (local system) due to base primitive
4724 double tmpPot;
4725 Vector3D tmpF;
4726 GetPrimPF(primsrc, &localPP, &tmpPot, &tmpF);
4727 const double qpr = AvWtChDen[IdWtField][primsrc];
4728 pPot[primsrc] += qpr * tmpPot;
4729 lFx += qpr * tmpF.X;
4730 lFy += qpr * tmpF.Y;
4731 lFz += qpr * tmpF.Z;
4732 // if(DebugLevel == 301)
4733 if (dbgFn) {
4734 printf("PFAtPoint base primitive =>\n");
4735 printf("primsrc: %d, xlocal: %lg, ylocal: %lg, zlocal %lg\n",
4736 primsrc, localPP.X, localPP.Y, localPP.Z);
4737 printf("primsrc: %d, Pot: %lg, Fx: %lg, Fx: %lg, Fz: %lg\n",
4738 primsrc, tmpPot, tmpF.X, tmpF.Y, tmpF.Z);
4739 printf("primsrc: %d, pPot: %lg, lFx: %lg, lFy: %lg, lFz: %lg\n",
4740 primsrc, pPot[primsrc], lFx, lFy, lFz);
4741 fflush(stdout);
4742 // exit(-1);
4743 }
4744 } else {
4745 // element influence
4746 double tPot;
4747 Vector3D tF;
4748 double ePot = 0.;
4749 Vector3D eF;
4750 eF.X = 0.0;
4751 eF.Y = 0.0;
4752 eF.Z = 0.0;
4753
4754 const int eleMin = ElementBgn[primsrc];
4755 const int eleMax = ElementEnd[primsrc];
4756 for (int ele = eleMin; ele <= eleMax; ++ele) {
4757 const double xsrc = (EleArr + ele - 1)->G.Origin.X;
4758 const double ysrc = (EleArr + ele - 1)->G.Origin.Y;
4759 const double zsrc = (EleArr + ele - 1)->G.Origin.Z;
4760 // Rotate vector from global to local system; matrix as for
4761 // primitive
4762 double vG[3] = {xfld - xsrc, yfld - ysrc, zfld - zsrc};
4763 double vL[3] = {0., 0., 0.};
4764 for (int i = 0; i < 3; ++i) {
4765 for (int j = 0; j < 3; ++j) {
4766 vL[i] += TransformationMatrix[i][j] * vG[j];
4767 }
4768 }
4769 // Potential and flux (local system) due to base primitive
4770 const int type = (EleArr + ele - 1)->G.Type;
4771 const double a = (EleArr + ele - 1)->G.LX;
4772 const double b = (EleArr + ele - 1)->G.LZ;
4773 GetPF(type, a, b, vL[0], vL[1], vL[2], &tPot, &tF);
4774 const double qel = WtFieldChDen[IdWtField][ele];
4775 ePot += qel * tPot;
4776 eF.X += qel * tF.X;
4777 eF.Y += qel * tF.Y;
4778 eF.Z += qel * tF.Z;
4779 // if(DebugLevel == 301)
4780 if (dbgFn) {
4781 printf("PFAtPoint base primitive:%d\n", primsrc);
4782 printf("ele: %d, xlocal: %lg, ylocal: %lg, zlocal %lg\n", ele,
4783 vL[0], vL[1], vL[2]);
4784 printf(
4785 "ele: %d, tPot: %lg, tFx: %lg, tFy: %lg, tFz: %lg, Solution: "
4786 "%g\n",
4787 ele, tPot, tF.X, tF.Y, tF.Z, qel);
4788 printf("ele: %d, ePot: %lg, eFx: %lg, eFy: %lg, eFz: %lg\n", ele,
4789 ePot, eF.X, eF.Y, eF.Z);
4790 fflush(stdout);
4791 }
4792 } // for all the elements on this primsrc primitive
4793
4794 pPot[primsrc] += ePot;
4795 lFx += eF.X;
4796 lFy += eF.Y;
4797 lFz += eF.Z;
4798 if (dbgFn) {
4799 printf(
4800 "prim%d, ePot: %lg, eFx: %lg, eFy: %lg, eFz: %lg\n",
4801 primsrc, ePot, eF.X, eF.Y, eF.Z);
4802 printf("prim%d, pPot: %lg, lFx: %lg, lFy: %lg, lFz: %lg\n", primsrc,
4803 pPot[primsrc], lFx, lFy, lFz);
4804 fflush(stdout);
4805 }
4806 } // else elements influence
4807
4808 // if(DebugLevel == 301)
4809 if (dbgFn) {
4810 printf("basic primtive\n");
4811 printf("primsrc: %d, pPot: %lg, lFx: %lg, lFy: %lg, lFz: %lg\n",
4812 primsrc, pPot[primsrc], lFx, lFy, lFz);
4813 fflush(stdout);
4814 }
4815 } // basic primitive ends
4816
4817 if (MirrorTypeX[primsrc] || MirrorTypeY[primsrc] ||
4818 MirrorTypeZ[primsrc]) { // Mirror effect of base primitives
4819 printf("Mirror may not be correctly implemented ...\n");
4820 exit(0);
4821 } // Mirror effect ends
4822
4823 // Flux due to repeated primitives
4824 if ((PeriodicTypeX[primsrc] == 1) || (PeriodicTypeY[primsrc] == 1) ||
4825 (PeriodicTypeZ[primsrc] == 1)) {
4826 const int perx = PeriodicInX[primsrc];
4827 const int pery = PeriodicInY[primsrc];
4828 const int perz = PeriodicInZ[primsrc];
4829 if (perx || pery || perz) {
4830 for (int xrpt = -perx; xrpt <= perx; ++xrpt) {
4831 const double xShift = XPeriod[primsrc] * (double)xrpt;
4832 double XPOfRpt = xpsrc + xShift;
4833 for (int yrpt = -pery; yrpt <= pery; ++yrpt) {
4834 const double yShift = YPeriod[primsrc] * (double)yrpt;
4835 double YPOfRpt = ypsrc + yShift;
4836 for (int zrpt = -perz; zrpt <= perz; ++zrpt) {
4837 const double zShift = ZPeriod[primsrc] * (double)zrpt;
4838 double ZPOfRpt = zpsrc + zShift;
4839 // Skip the base device.
4840 if ((xrpt == 0) && (yrpt == 0) && (zrpt == 0)) continue;
4841 { // basic primitive repeated
4842 Point3D localPPR;
4843 { // Rotate point from global to local system
4844 double InitialVector[3] = {xfld - XPOfRpt, yfld - YPOfRpt, zfld - ZPOfRpt};
4845 double FinalVector[3] = {0., 0., 0.};
4846 for (int i = 0; i < 3; ++i) {
4847 for (int j = 0; j < 3; ++j) {
4848 FinalVector[i] +=
4849 TransformationMatrix[i][j] * InitialVector[j];
4850 }
4851 }
4852 localPPR.X = FinalVector[0];
4853 localPPR.Y = FinalVector[1];
4854 localPPR.Z = FinalVector[2];
4855 } // Point3D rotated
4856
4857 int PrimOK = 0;
4858
4859 // consider primitive representation accurate enough if it is
4860 // repeated and beyond PrimAfter repetitions.
4861 if (PrimAfter == 0) {
4862 // If PrimAfter is zero, PrimOK is always zero
4863 PrimOK = 0;
4864 } else if ((abs(xrpt) > PrimAfter) && (abs(yrpt) > PrimAfter)) {
4865 PrimOK = 1;
4866 }
4867 if (PrimOK) { // use primitive representation
4868 // Potential and flux (local system) due to repeated
4869 // primitive
4870 double tmpPot;
4871 Vector3D tmpF;
4872 GetPrimPF(primsrc, &localPPR, &tmpPot, &tmpF);
4873 const double qpr = AvWtChDen[IdWtField][primsrc];
4874 pPot[primsrc] += qpr * tmpPot;
4875 lFx += qpr * tmpF.X;
4876 lFy += qpr * tmpF.Y;
4877 lFz += qpr * tmpF.Z;
4878 // if(DebugLevel == 301)
4879 if (dbgFn) {
4880 printf(
4881 "primsrc: %d, xlocal: %lg, ylocal: %lg, zlocal: "
4882 "%lg\n",
4883 primsrc, localPPR.X, localPPR.Y, localPPR.Z);
4884 printf(
4885 "primsrc: %d, Pot: %lg, Fx: %lg, Fy: %lg, Fz: %lg\n",
4886 primsrc, tmpPot * qpr, tmpF.X * qpr, tmpF.Y * qpr,
4887 tmpF.Z * qpr);
4888 printf(
4889 "primsrc: %d, pPot: %lg, lFx: %lg, lFy: %lg, lFz: "
4890 "%lg\n",
4891 primsrc, pPot[primsrc], lFx, lFy, lFz);
4892 fflush(stdout);
4893 }
4894 } else {
4895 // use discretized representation of a repeated primitive
4896 double tPot;
4897 Vector3D tF;
4898 double erPot = 0.;
4899 Vector3D erF;
4900 erF.X = 0.0;
4901 erF.Y = 0.0;
4902 erF.Z = 0.0;
4903
4904 const int eleMin = ElementBgn[primsrc];
4905 const int eleMax = ElementEnd[primsrc];
4906 for (int ele = eleMin; ele <= eleMax; ++ele) {
4907 const double xrsrc = (EleArr + ele - 1)->G.Origin.X;
4908 const double yrsrc = (EleArr + ele - 1)->G.Origin.Y;
4909 const double zrsrc = (EleArr + ele - 1)->G.Origin.Z;
4910
4911 const double XEOfRpt = xrsrc + xShift;
4912 const double YEOfRpt = yrsrc + yShift;
4913 const double ZEOfRpt = zrsrc + zShift;
4914
4915 // Rotate point from global to local system.
4916 double vG[3] = {xfld - XEOfRpt, yfld - YEOfRpt, zfld - ZEOfRpt};
4917 double vL[3] = {0., 0., 0.};
4918 for (int i = 0; i < 3; ++i) {
4919 for (int j = 0; j < 3; ++j) {
4920 vL[i] += TransformationMatrix[i][j] * vG[j];
4921 }
4922 }
4923 // Allowed, because all the local coordinates have the
4924 // same orientations. Only the origins are mutually
4925 // displaced along a line.
4926 const int type = (EleArr + ele - 1)->G.Type;
4927 const double a = (EleArr + ele - 1)->G.LX;
4928 const double b = (EleArr + ele - 1)->G.LZ;
4929 GetPF(type, a, b, vL[0], vL[1], vL[2], &tPot, &tF);
4930 const double qel = WtFieldChDen[IdWtField][ele];
4931 erPot += qel * tPot;
4932 erF.X += qel * tF.X;
4933 erF.Y += qel * tF.Y;
4934 erF.Z += qel * tF.Z;
4935 // if(DebugLevel == 301)
4936 if (dbgFn) {
4937 printf("PFAtPoint base primitive:%d\n", primsrc);
4938 printf(
4939 "ele: %d, xlocal: %lg, ylocal: %lg, zlocal %lg\n",
4940 ele, vL[0], vL[1], vL[2]);
4941 printf(
4942 "ele: %d, tPot: %lg, tFx: %lg, tFy: %lg, tFz: %lg, "
4943 "Solution: %g\n",
4944 ele, tPot, tF.X, tF.Y, tF.Z, qel);
4945 printf(
4946 "ele: %d, ePot: %lg, eFx: %lg, eFy: %lg, eFz: "
4947 "%lg\n",
4948 ele, erPot, erF.X, erF.Y, erF.Z);
4949 fflush(stdout);
4950 }
4951 } // for all the elements on this primsrc repeated
4952 // primitive
4953
4954 pPot[primsrc] += erPot;
4955 lFx += erF.X;
4956 lFy += erF.Y;
4957 lFz += erF.Z;
4958 } // else discretized representation of this primitive
4959
4960 // if(DebugLevel == 301)
4961 if (dbgFn) {
4962 printf("basic repeated xrpt: %d. yrpt: %d, zrpt: %d\n",
4963 xrpt, yrpt, zrpt);
4964 printf(
4965 "primsrc: %d, pPot: %lg, lFx: %lg, lFy: %lg, lFz: "
4966 "%lg\n",
4967 primsrc, pPot[primsrc], lFx, lFy, lFz);
4968 fflush(stdout);
4969 }
4970 } // repetition of basic primitive
4971
4972 if (MirrorTypeX[primsrc] || MirrorTypeY[primsrc] ||
4973 MirrorTypeZ[primsrc]) {
4974 // Mirror effect of repeated primitives - not parallelized
4975 printf(
4976 "Mirror not correctly implemented in this version of "
4977 "neBEM ...\n");
4978 exit(0);
4979 } // Mirror effect for repeated primitives ends
4980
4981 } // for zrpt
4982 } // for yrpt
4983 } // for xrpt
4984 } // PeriodicInX || PeriodicInY || PeriodicInZ
4985 } // PeriodicType == 1
4986 Vector3D localF;
4987 localF.X = lFx;
4988 localF.Y = lFy;
4989 localF.Z = lFz;
4990 Vector3D tmpF = RotateVector3D(&localF, &PrimDC[primsrc], local2global);
4991 plFx[primsrc] = tmpF.X; // local fluxes lFx, lFy, lFz in GCS
4992 plFy[primsrc] = tmpF.Y;
4993 plFz[primsrc] = tmpF.Z;
4994 } // for all primitives: basic device, mirror reflections and repetitions
4995 } // pragma omp parallel
4996
4997 double totPot = 0.0;
4998 Vector3D totF;
4999 totF.X = totF.Y = totF.Z = 0.0;
5000 for (int prim = 1; prim <= NbPrimitives; ++prim) {
5001 totPot += pPot[prim];
5002 totF.X += plFx[prim];
5003 totF.Y += plFy[prim];
5004 totF.Z += plFz[prim];
5005 }
5006
5007 // This should be done at the end of the function - before freeing memory
5008#ifdef __cplusplus
5009 *Potential = totPot * InvFourPiEps0;
5010 globalF->X = totF.X * InvFourPiEps0;
5011 globalF->Y = totF.Y * InvFourPiEps0;
5012 globalF->Z = totF.Z * InvFourPiEps0;
5013#else
5014 *Potential = totPot / MyFACTOR;
5015 globalF->X = totF.X / MyFACTOR;
5016 globalF->Y = totF.Y / MyFACTOR;
5017 globalF->Z = totF.Z / MyFACTOR;
5018#endif
5019 /* for weighting field, effect of KnCh is possibly zero.
5020 double tmpPot; Vector3D tmpF;
5021 // ExactPointP and ExactPointF should also have an ExactPointPF
5022 // Similarly for area and volume element related functions
5023 // since there is no intermediate function that interfaces ExactPointP etc
5024 // division by MyFACTOR is necessary
5025 // Do parallelize before using these known charges - points or distributions
5026 for (int point = 1; point <= NbPtsKnCh; ++point) {
5027 tmpPot = ExactPointP(&(PtKnChArr+point-1)->P, globalP);
5028 (*Potential) += (PtKnChArr+point-1)->Assigned * tmpPot / MyFACTOR;
5029 ExactPointF(&(PtKnChArr+point-1)->P, globalP, &tmpF);
5030 globalF->X += (PtKnChArr+point-1)->Assigned * tmpF.X / MyFACTOR;
5031 globalF->Y += (PtKnChArr+point-1)->Assigned * tmpF.Y / MyFACTOR;
5032 globalF->Z += (PtKnChArr+point-1)->Assigned * tmpF.Z / MyFACTOR;
5033 } // for all points
5034
5035 for (int line = 1; line <= NbLinesKnCh; ++line) {
5036 (*Potential) += 0.0;
5037 globalF->X += 0.0;
5038 globalF->Y += 0.0;
5039 globalF->Z += 0.0;
5040 } // for all lines
5041
5042 for (int area = 1; area <= NbAreasKnCh; ++area) {
5043 (*Potential) += 0.0;
5044 globalF->X += 0.0;
5045 globalF->Y += 0.0;
5046 globalF->Z += 0.0;
5047 } // for all areas
5048
5049 for (int vol = 1; vol <= NbVolsKnCh; ++vol) {
5050 (*Potential) += 0.0;
5051 globalF->X += 0.0;
5052 globalF->Y += 0.0;
5053 globalF->Z += 0.0;
5054 } // for all volumes
5055
5056 // This should be the final position
5057 // *Potential = totPot;
5058 // globalF->X = totF.X;
5059 // globalF->Y = totF.Y;
5060 // globalF->Z = totF.Z;
5061 // effect of KnCh is possibly zero on weighting field
5062 */
5063
5064 // (*Potential) += VSystemChargeZero; // respect total system charge constraint
5065
5066 if (dbgFn) {
5067 printf("Final values due to all primitives and other influences: ");
5068 // printf("xfld\tyfld\tzfld\tPot\tFx\tFy\tFz\n"); // refer, do not
5069 // uncomment
5070 printf("%lg\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n\n", xfld, yfld, zfld,
5071 (*Potential), globalF->X, globalF->Y, globalF->Z);
5072 fflush(stdout);
5073 }
5074
5075 free_dvector(pPot, 1, NbPrimitives);
5076 free_dvector(plFx, 1, NbPrimitives);
5077 free_dvector(plFy, 1, NbPrimitives);
5078 free_dvector(plFz, 1, NbPrimitives);
5079
5080 return (0);
5081} // end of WtPFAtPoint
neBEMGLOBAL double ** AvWtChDen
Definition: neBEM.h:333
neBEMGLOBAL double ** WtFieldChDen
Definition: neBEM.h:333

Referenced by neBEMWeightingField().

Variable Documentation

◆ ApplCh

neBEMGLOBAL double * ApplCh

Definition at line 75 of file neBEM.h.

Referenced by neBEMDiscretize(), neBEMReadGeometry(), ReadPrimitives(), and WritePrimitives().

◆ ApplPot

neBEMGLOBAL double * ApplPot

◆ AreaKnChArr

neBEMGLOBAL AreaKnCh* AreaKnChArr

Definition at line 204 of file neBEM.h.

Referenced by KnChPFAtPoint(), neBEMKnownCharges(), ReadElements(), and WriteElements().

◆ AvAsgndChDen

neBEMGLOBAL double * AvAsgndChDen

Definition at line 90 of file neBEM.h.

Referenced by ElePFAtPoint(), neBEMReadGeometry(), ReadSolution(), and Solve().

◆ AvChDen

neBEMGLOBAL double* AvChDen

Definition at line 90 of file neBEM.h.

Referenced by ElePFAtPoint(), neBEMReadGeometry(), ReadSolution(), and Solve().

◆ AvWtChDen

◆ BCCntr

neBEMGLOBAL int BCCntr

◆ BCOutDir

neBEMGLOBAL char BCOutDir[256]

◆ BlkCrnrZ

neBEMGLOBAL double* BlkCrnrZ

Definition at line 428 of file neBEM.h.

Referenced by FastKnChPFAtPoint(), FastPFAtPoint(), FastVolElePF(), neBEMInitialize(), and neBEMSolve().

◆ BlkLZ

neBEMGLOBAL double* BlkLZ

Definition at line 427 of file neBEM.h.

Referenced by FastKnChPFAtPoint(), FastPFAtPoint(), FastVolElePF(), neBEMInitialize(), and neBEMSolve().

◆ BlkNbXCells

neBEMGLOBAL int* BlkNbXCells

Definition at line 424 of file neBEM.h.

Referenced by FastKnChPFAtPoint(), FastPFAtPoint(), FastVolElePF(), neBEMInitialize(), and neBEMSolve().

◆ BlkNbYCells

neBEMGLOBAL int* BlkNbYCells

Definition at line 425 of file neBEM.h.

Referenced by FastKnChPFAtPoint(), FastPFAtPoint(), FastVolElePF(), neBEMInitialize(), and neBEMSolve().

◆ BlkNbZCells

neBEMGLOBAL int* BlkNbZCells

Definition at line 426 of file neBEM.h.

Referenced by FastKnChPFAtPoint(), FastPFAtPoint(), FastVolElePF(), neBEMInitialize(), and neBEMSolve().

◆ BndPlaneInXMax

neBEMGLOBAL int* BndPlaneInXMax

Definition at line 85 of file neBEM.h.

Referenced by neBEMReadGeometry().

◆ BndPlaneInXMin

neBEMGLOBAL int* BndPlaneInXMin

Definition at line 84 of file neBEM.h.

Referenced by neBEMReadGeometry().

◆ BndPlaneInYMax

neBEMGLOBAL int * BndPlaneInYMax

Definition at line 85 of file neBEM.h.

Referenced by neBEMReadGeometry().

◆ BndPlaneInYMin

neBEMGLOBAL int * BndPlaneInYMin

Definition at line 84 of file neBEM.h.

Referenced by neBEMReadGeometry().

◆ BndPlaneInZMax

neBEMGLOBAL int * BndPlaneInZMax

Definition at line 85 of file neBEM.h.

Referenced by neBEMReadGeometry().

◆ BndPlaneInZMin

neBEMGLOBAL int * BndPlaneInZMin

Definition at line 84 of file neBEM.h.

Referenced by neBEMReadGeometry().

◆ DebugLevel

◆ DeviceOutDir

neBEMGLOBAL char DeviceOutDir[256]

Definition at line 262 of file neBEM.h.

Referenced by CreateDirStr(), neBEM::neBEMSetDefaults(), and neBEM::ReadInitFile().

◆ EleArr

◆ EleCntr

◆ ElementBgn

◆ ElementEnd

◆ ElementLengthRqstd

neBEMGLOBAL double ElementLengthRqstd

Definition at line 107 of file neBEM.h.

Referenced by AnalyzeSurface(), AnalyzeWire(), neBEM::neBEMSetDefaults(), and neBEM::ReadInitFile().

◆ EndOfTime

neBEMGLOBAL int EndOfTime

Definition at line 241 of file neBEM.h.

Referenced by ComputeSolution().

◆ Epsilon1

neBEMGLOBAL double* Epsilon1

Definition at line 75 of file neBEM.h.

Referenced by DiscretizeTriangle(), neBEMReadGeometry(), ReadPrimitives(), Solve(), and WritePrimitives().

◆ Epsilon2

neBEMGLOBAL double * Epsilon2

Definition at line 75 of file neBEM.h.

Referenced by DiscretizeTriangle(), neBEMReadGeometry(), ReadPrimitives(), Solve(), and WritePrimitives().

◆ FastFX

neBEMGLOBAL double**** FastFX

Definition at line 444 of file neBEM.h.

Referenced by FastPFAtPoint(), FastVolElePF(), and neBEMSolve().

◆ FastFXKnCh

neBEMGLOBAL double**** FastFXKnCh

Definition at line 448 of file neBEM.h.

Referenced by FastKnChPFAtPoint().

◆ FastFY

neBEMGLOBAL double **** FastFY

Definition at line 444 of file neBEM.h.

Referenced by FastPFAtPoint(), FastVolElePF(), and neBEMSolve().

◆ FastFYKnCh

neBEMGLOBAL double **** FastFYKnCh

Definition at line 448 of file neBEM.h.

Referenced by FastKnChPFAtPoint().

◆ FastFZ

neBEMGLOBAL double **** FastFZ

Definition at line 444 of file neBEM.h.

Referenced by FastPFAtPoint(), FastVolElePF(), and neBEMSolve().

◆ FastFZKnCh

neBEMGLOBAL double **** FastFZKnCh

Definition at line 448 of file neBEM.h.

Referenced by FastKnChPFAtPoint().

◆ FastPot

neBEMGLOBAL double**** FastPot

Definition at line 443 of file neBEM.h.

Referenced by FastPFAtPoint(), FastVolElePF(), and neBEMSolve().

◆ FastPotKnCh

neBEMGLOBAL double**** FastPotKnCh

Definition at line 447 of file neBEM.h.

Referenced by FastKnChPFAtPoint().

◆ FastStgFX

neBEMGLOBAL double**** FastStgFX

Definition at line 446 of file neBEM.h.

Referenced by FastPFAtPoint(), FastVolElePF(), and neBEMSolve().

◆ FastStgFXKnCh

neBEMGLOBAL double**** FastStgFXKnCh

Definition at line 450 of file neBEM.h.

Referenced by FastKnChPFAtPoint().

◆ FastStgFY

neBEMGLOBAL double **** FastStgFY

Definition at line 446 of file neBEM.h.

Referenced by FastPFAtPoint(), FastVolElePF(), and neBEMSolve().

◆ FastStgFYKnCh

neBEMGLOBAL double **** FastStgFYKnCh

Definition at line 450 of file neBEM.h.

Referenced by FastKnChPFAtPoint().

◆ FastStgFZ

neBEMGLOBAL double **** FastStgFZ

Definition at line 446 of file neBEM.h.

Referenced by FastPFAtPoint(), FastVolElePF(), and neBEMSolve().

◆ FastStgFZKnCh

neBEMGLOBAL double **** FastStgFZKnCh

Definition at line 450 of file neBEM.h.

Referenced by FastKnChPFAtPoint().

◆ FastStgPot

neBEMGLOBAL double**** FastStgPot

Definition at line 445 of file neBEM.h.

Referenced by FastPFAtPoint(), FastVolElePF(), and neBEMSolve().

◆ FastStgPotKnCh

neBEMGLOBAL double**** FastStgPotKnCh

Definition at line 449 of file neBEM.h.

Referenced by FastKnChPFAtPoint().

◆ FastVol

◆ FixedWtFieldX

neBEMGLOBAL double FixedWtFieldX

Definition at line 467 of file neBEM.h.

Referenced by neBEMInitialize(), and neBEMWeightingField().

◆ FixedWtFieldY

neBEMGLOBAL double FixedWtFieldY

Definition at line 468 of file neBEM.h.

Referenced by neBEMInitialize(), and neBEMWeightingField().

◆ FixedWtFieldZ

neBEMGLOBAL double FixedWtFieldZ

Definition at line 469 of file neBEM.h.

Referenced by neBEMInitialize(), and neBEMWeightingField().

◆ FixedWtPotential

neBEMGLOBAL double FixedWtPotential

Definition at line 466 of file neBEM.h.

Referenced by neBEMInitialize(), and neBEMWeightingField().

◆ fMeshLog

neBEMGLOBAL FILE* fMeshLog

Definition at line 114 of file neBEM.h.

Referenced by AnalyzeSurface(), AnalyzeWire(), and neBEMDiscretize().

◆ GnuplotScriptFile

neBEMGLOBAL char GnuplotScriptFile[256]

Definition at line 245 of file neBEM.h.

◆ GnuplotTmpDir

neBEMGLOBAL char GnuplotTmpDir[256]

Definition at line 245 of file neBEM.h.

◆ IgnoreVolCrnrX

neBEMGLOBAL double* IgnoreVolCrnrX

Definition at line 438 of file neBEM.h.

Referenced by FastKnChPFAtPoint(), FastPFAtPoint(), and neBEMInitialize().

◆ IgnoreVolCrnrY

neBEMGLOBAL double* IgnoreVolCrnrY

Definition at line 439 of file neBEM.h.

Referenced by FastKnChPFAtPoint(), FastPFAtPoint(), and neBEMInitialize().

◆ IgnoreVolCrnrZ

neBEMGLOBAL double* IgnoreVolCrnrZ

Definition at line 440 of file neBEM.h.

Referenced by FastKnChPFAtPoint(), FastPFAtPoint(), and neBEMInitialize().

◆ IgnoreVolLX

neBEMGLOBAL double* IgnoreVolLX

Definition at line 435 of file neBEM.h.

Referenced by FastKnChPFAtPoint(), FastPFAtPoint(), and neBEMInitialize().

◆ IgnoreVolLY

neBEMGLOBAL double* IgnoreVolLY

Definition at line 436 of file neBEM.h.

Referenced by FastKnChPFAtPoint(), FastPFAtPoint(), and neBEMInitialize().

◆ IgnoreVolLZ

neBEMGLOBAL double* IgnoreVolLZ

Definition at line 437 of file neBEM.h.

Referenced by FastKnChPFAtPoint(), FastPFAtPoint(), and neBEMInitialize().

◆ Inf

neBEMGLOBAL double** Inf

Definition at line 237 of file neBEM.h.

Referenced by ComputeSolution(), InvertMatrix(), LHMatrix(), Solve(), and ValueChUp().

◆ InterfaceType

◆ InvMat

neBEMGLOBAL double ** InvMat

Definition at line 237 of file neBEM.h.

Referenced by InvertMatrix(), ReadInvertedMatrix(), Solve(), and WeightingFieldSolution().

◆ Lambda

neBEMGLOBAL double * Lambda

Definition at line 75 of file neBEM.h.

Referenced by neBEMDiscretize(), neBEMReadGeometry(), ReadPrimitives(), and WritePrimitives().

◆ LengthScale

neBEMGLOBAL double LengthScale

◆ LineKnChArr

neBEMGLOBAL LineKnCh* LineKnChArr

Definition at line 192 of file neBEM.h.

Referenced by KnChPFAtPoint(), neBEMKnownCharges(), ReadElements(), and WriteElements().

◆ Map

Definition at line 396 of file neBEM.h.

Referenced by MapFPR(), and neBEMInitialize().

◆ MapVersion

neBEMGLOBAL char MapVersion[10]

Definition at line 380 of file neBEM.h.

Referenced by Garfield::ComponentNeBem3dMap::LoadMapInfo(), MapFPR(), and neBEMInitialize().

◆ MaxNbElementsOnLength

neBEMGLOBAL int MaxNbElementsOnLength

Definition at line 105 of file neBEM.h.

Referenced by AnalyzeSurface(), AnalyzeWire(), neBEM::neBEMSetDefaults(), and neBEM::ReadInitFile().

◆ MaxNbVertices

neBEMGLOBAL int MaxNbVertices

◆ MeshCntr

neBEMGLOBAL int MeshCntr

◆ MeshOutDir

◆ MinNbElementsOnLength

neBEMGLOBAL int MinNbElementsOnLength

Definition at line 103 of file neBEM.h.

Referenced by AnalyzeSurface(), AnalyzeWire(), neBEM::neBEMSetDefaults(), and neBEM::ReadInitFile().

◆ MirrorDistXFromOrigin

neBEMGLOBAL double* MirrorDistXFromOrigin

Definition at line 82 of file neBEM.h.

Referenced by ElePFAtPoint(), LHMatrix(), neBEMReadGeometry(), ReadPrimitives(), and WritePrimitives().

◆ MirrorDistYFromOrigin

neBEMGLOBAL double * MirrorDistYFromOrigin

Definition at line 82 of file neBEM.h.

Referenced by ElePFAtPoint(), LHMatrix(), neBEMReadGeometry(), ReadPrimitives(), and WritePrimitives().

◆ MirrorDistZFromOrigin

neBEMGLOBAL double * MirrorDistZFromOrigin

Definition at line 83 of file neBEM.h.

Referenced by ElePFAtPoint(), LHMatrix(), neBEMReadGeometry(), ReadPrimitives(), and WritePrimitives().

◆ MirrorTypeX

neBEMGLOBAL int* MirrorTypeX

Definition at line 81 of file neBEM.h.

Referenced by ElePFAtPoint(), LHMatrix(), neBEMReadGeometry(), and WtPFAtPoint().

◆ MirrorTypeY

neBEMGLOBAL int * MirrorTypeY

Definition at line 81 of file neBEM.h.

Referenced by ElePFAtPoint(), LHMatrix(), neBEMReadGeometry(), and WtPFAtPoint().

◆ MirrorTypeZ

neBEMGLOBAL int * MirrorTypeZ

Definition at line 81 of file neBEM.h.

Referenced by ElePFAtPoint(), LHMatrix(), neBEMReadGeometry(), and WtPFAtPoint().

◆ ModelCntr

neBEMGLOBAL int ModelCntr

◆ ModelOutDir

neBEMGLOBAL char ModelOutDir[256]

◆ NativeOutDir

neBEMGLOBAL char NativeOutDir[256]

Definition at line 262 of file neBEM.h.

Referenced by CreateDirStr(), and neBEMReadGeometry().

◆ NativePrimDir

neBEMGLOBAL char NativePrimDir[256]

Definition at line 263 of file neBEM.h.

Referenced by CreateDirStr(), and neBEMReadGeometry().

◆ NbAreasKnCh

neBEMGLOBAL int NbAreasKnCh

Definition at line 172 of file neBEM.h.

Referenced by KnChPFAtPoint(), neBEMKnownCharges(), ReadElements(), and WriteElements().

◆ NbConstraints

neBEMGLOBAL int NbConstraints

Definition at line 233 of file neBEM.h.

Referenced by ComputeSolution(), ReadSolution(), RHVector(), and Solve().

◆ NbElements

◆ NbElmntsOnPrim

neBEMGLOBAL int* NbElmntsOnPrim

Definition at line 94 of file neBEM.h.

Referenced by DiscretizeWire(), and neBEMReadGeometry().

◆ NbEqns

◆ NbFloatCon

neBEMGLOBAL int NbFloatCon

Definition at line 126 of file neBEM.h.

Referenced by ComputeSolution(), ReadSolution(), and Solve().

◆ NbFloatingConductors

neBEMGLOBAL int NbFloatingConductors

Definition at line 124 of file neBEM.h.

Referenced by ComputeSolution(), neBEMReadGeometry(), ReadSolution(), and Solve().

◆ NbLinesKnCh

neBEMGLOBAL int NbLinesKnCh

Definition at line 172 of file neBEM.h.

Referenced by KnChPFAtPoint(), neBEMKnownCharges(), ReadElements(), and WriteElements().

◆ NbPointsKnCh

neBEMGLOBAL int NbPointsKnCh

Definition at line 172 of file neBEM.h.

Referenced by KnChPFAtPoint(), neBEMKnownCharges(), ReadElements(), and WriteElements().

◆ NbPrimitives

◆ NbPtSkip

neBEMGLOBAL int NbPtSkip

Definition at line 407 of file neBEM.h.

Referenced by FastVolElePF(), neBEMInitialize(), and neBEMSolve().

◆ NbStgPtSkip

neBEMGLOBAL int NbStgPtSkip

Definition at line 408 of file neBEM.h.

Referenced by FastVolElePF(), neBEMInitialize(), and neBEMSolve().

◆ NbSurfs

◆ NbSurfSegX

neBEMGLOBAL int* NbSurfSegX

◆ NbSurfSegZ

neBEMGLOBAL int * NbSurfSegZ

◆ NbSystemChargeZero

neBEMGLOBAL int NbSystemChargeZero

Definition at line 120 of file neBEM.h.

Referenced by ComputeSolution(), ReadSolution(), RHVector(), and Solve().

◆ NbUnknowns

◆ NbVertices

◆ NbVolumes

neBEMGLOBAL int NbVolumes

Definition at line 56 of file neBEM.h.

Referenced by neBEM::neBEMSetDefaults(), ReadPrimitives(), and WritePrimitives().

◆ NbVolumesKnCh

neBEMGLOBAL int NbVolumesKnCh

Definition at line 172 of file neBEM.h.

Referenced by KnChPFAtPoint(), neBEMKnownCharges(), ReadElements(), and WriteElements().

◆ NbWires

◆ NbWireSeg

neBEMGLOBAL int* NbWireSeg

◆ neBEMVersion

neBEMGLOBAL char neBEMVersion[10]

Definition at line 34 of file neBEM.h.

Referenced by neBEMInitialize(), and neBEMTimeElapsed().

◆ NewBC

◆ NewMesh

◆ NewModel

◆ NewPP

◆ OmitVolCrnrX

neBEMGLOBAL double* OmitVolCrnrX

Definition at line 432 of file neBEM.h.

Referenced by FastVolElePF(), neBEMInitialize(), and neBEMSolve().

◆ OmitVolCrnrY

neBEMGLOBAL double* OmitVolCrnrY

Definition at line 433 of file neBEM.h.

Referenced by FastVolElePF(), neBEMInitialize(), and neBEMSolve().

◆ OmitVolCrnrZ

neBEMGLOBAL double* OmitVolCrnrZ

Definition at line 434 of file neBEM.h.

Referenced by FastVolElePF(), neBEMInitialize(), and neBEMSolve().

◆ OmitVolLX

neBEMGLOBAL double* OmitVolLX

Definition at line 429 of file neBEM.h.

Referenced by FastVolElePF(), neBEMInitialize(), and neBEMSolve().

◆ OmitVolLY

neBEMGLOBAL double* OmitVolLY

Definition at line 430 of file neBEM.h.

Referenced by FastVolElePF(), neBEMInitialize(), and neBEMSolve().

◆ OmitVolLZ

neBEMGLOBAL double* OmitVolLZ

Definition at line 431 of file neBEM.h.

Referenced by FastVolElePF(), neBEMInitialize(), and neBEMSolve().

◆ OptChargingUp

neBEMGLOBAL int OptChargingUp

Definition at line 53 of file neBEM.h.

Referenced by neBEMChargingUp(), and RHVector().

◆ OptCreateFastPF

neBEMGLOBAL int OptCreateFastPF

Definition at line 405 of file neBEM.h.

Referenced by neBEMInitialize(), and neBEMSolve().

◆ OptEstimateError

neBEMGLOBAL int OptEstimateError

Definition at line 44 of file neBEM.h.

Referenced by Solve().

◆ OptFastVol

neBEMGLOBAL int OptFastVol

Definition at line 403 of file neBEM.h.

Referenced by neBEMField(), neBEMInitialize(), and neBEMSolve().

◆ OptFixedWtField

neBEMGLOBAL int OptFixedWtField

Definition at line 465 of file neBEM.h.

Referenced by neBEMInitialize(), and neBEMWeightingField().

◆ OptForceValidation

neBEMGLOBAL int OptForceValidation

Definition at line 43 of file neBEM.h.

Referenced by neBEM::neBEMSetDefaults(), neBEM::ReadInitFile(), and Solve().

◆ OptFormattedFile

◆ OptGSL

neBEMGLOBAL int OptGSL

Definition at line 236 of file neBEM.h.

Referenced by ComputeSolution(), and InvertMatrix().

◆ OptInvMatProc

neBEMGLOBAL int OptInvMatProc

Definition at line 41 of file neBEM.h.

Referenced by ComputeSolution(), neBEM::neBEMSetDefaults(), and neBEM::ReadInitFile().

◆ OptKnCh

neBEMGLOBAL int OptKnCh

Definition at line 52 of file neBEM.h.

Referenced by neBEMKnownCharges(), PFAtPoint(), and RHVector().

◆ OptLU

neBEMGLOBAL int OptLU

Definition at line 236 of file neBEM.h.

Referenced by ComputeSolution(), and InvertMatrix().

◆ OptMap

neBEMGLOBAL int OptMap

◆ OptReadFastPF

neBEMGLOBAL int OptReadFastPF

Definition at line 406 of file neBEM.h.

Referenced by MapFPR(), neBEMInitialize(), and neBEMSolve().

◆ OptRepeatLHMatrix

neBEMGLOBAL int OptRepeatLHMatrix

Definition at line 51 of file neBEM.h.

Referenced by neBEM::neBEMSetDefaults(), neBEM::ReadInitFile(), and Solve().

◆ OptStaggerFastVol

neBEMGLOBAL int OptStaggerFastVol

Definition at line 404 of file neBEM.h.

Referenced by FastKnChPFAtPoint(), FastPFAtPoint(), FastVolElePF(), neBEMInitialize(), and neBEMSolve().

◆ OptStaggerMap

neBEMGLOBAL int OptStaggerMap

Definition at line 379 of file neBEM.h.

Referenced by Garfield::ComponentNeBem3dMap::LoadMapInfo(), MapFPR(), and neBEMInitialize().

◆ OptStaggerVoxel

neBEMGLOBAL int OptStaggerVoxel

Definition at line 355 of file neBEM.h.

Referenced by neBEMInitialize().

◆ OptStoreElements

neBEMGLOBAL int OptStoreElements

Definition at line 46 of file neBEM.h.

Referenced by neBEMDiscretize(), neBEM::neBEMSetDefaults(), and neBEM::ReadInitFile().

◆ OptStoreInflMatrix

neBEMGLOBAL int OptStoreInflMatrix

Definition at line 47 of file neBEM.h.

Referenced by neBEM::neBEMSetDefaults(), neBEM::ReadInitFile(), Solve(), and ValueChUp().

◆ OptStoreInvMatrix

neBEMGLOBAL int OptStoreInvMatrix

◆ OptStorePrimitives

neBEMGLOBAL int OptStorePrimitives

Definition at line 45 of file neBEM.h.

Referenced by neBEMReadGeometry(), neBEM::neBEMSetDefaults(), and neBEM::ReadInitFile().

◆ OptSVD

neBEMGLOBAL int OptSVD

Definition at line 236 of file neBEM.h.

Referenced by ComputeSolution(), and InvertMatrix().

◆ OptSystemChargeZero

neBEMGLOBAL int OptSystemChargeZero

◆ OptUnformattedFile

◆ OptValidateSolution

neBEMGLOBAL int OptValidateSolution

◆ OptVoxel

neBEMGLOBAL int OptVoxel

Definition at line 354 of file neBEM.h.

Referenced by neBEMInitialize(), and neBEMSolve().

◆ OptWtFldCreateFastPF

neBEMGLOBAL int OptWtFldCreateFastPF

Definition at line 474 of file neBEM.h.

Referenced by neBEMInitialize(), and neBEMSolve().

◆ OptWtFldFastVol

neBEMGLOBAL int OptWtFldFastVol

Definition at line 472 of file neBEM.h.

Referenced by neBEMInitialize(), neBEMSolve(), and neBEMWeightingField().

◆ OptWtFldReadFastPF

neBEMGLOBAL int OptWtFldReadFastPF

Definition at line 475 of file neBEM.h.

Referenced by neBEMInitialize(), and neBEMSolve().

◆ OptWtFldStaggerFastVol

neBEMGLOBAL int OptWtFldStaggerFastVol

Definition at line 473 of file neBEM.h.

Referenced by neBEMInitialize(), neBEMSolve(), and WtFldFastPFAtPoint().

◆ OrgnlNbPrimitives

neBEMGLOBAL int OrgnlNbPrimitives

Definition at line 58 of file neBEM.h.

Referenced by neBEMReadGeometry().

◆ OrgnlToEffPrim

neBEMGLOBAL int** OrgnlToEffPrim

Definition at line 69 of file neBEM.h.

Referenced by neBEMReadGeometry().

◆ PeriodicInX

◆ PeriodicInY

◆ PeriodicInZ

◆ PeriodicTypeX

neBEMGLOBAL int* PeriodicTypeX

◆ PeriodicTypeY

neBEMGLOBAL int * PeriodicTypeY

◆ PeriodicTypeZ

neBEMGLOBAL int * PeriodicTypeZ

◆ PointKnChArr

neBEMGLOBAL PointKnCh* PointKnChArr

Definition at line 181 of file neBEM.h.

Referenced by KnChPFAtPoint(), neBEMKnownCharges(), ReadElements(), and WriteElements().

◆ PPCntr

neBEMGLOBAL int PPCntr

◆ PPOutDir

neBEMGLOBAL char PPOutDir[256]

Definition at line 263 of file neBEM.h.

Referenced by CreateDirStr(), neBEMInitialize(), and neBEMSolve().

◆ PrimAfter

neBEMGLOBAL int PrimAfter

◆ PrimDC

◆ PrimLX

◆ PrimLZ

◆ PrimOriginX

◆ PrimOriginY

◆ PrimOriginZ

◆ PrimType

◆ Radius

◆ RHS

neBEMGLOBAL double * RHS

Definition at line 237 of file neBEM.h.

Referenced by RHVector(), and Solve().

◆ Solution

◆ TimeStep

neBEMGLOBAL int TimeStep

Definition at line 241 of file neBEM.h.

Referenced by ComputeSolution(), neBEM::neBEMSetDefaults(), neBEMSolve(), RHVector(), and Solve().

◆ TimeStr

neBEMGLOBAL char TimeStr[256]

Definition at line 242 of file neBEM.h.

◆ VBndPlaneInXMax

neBEMGLOBAL double* VBndPlaneInXMax

Definition at line 89 of file neBEM.h.

Referenced by neBEMReadGeometry().

◆ VBndPlaneInXMin

neBEMGLOBAL double* VBndPlaneInXMin

Definition at line 88 of file neBEM.h.

Referenced by neBEMReadGeometry().

◆ VBndPlaneInYMax

neBEMGLOBAL double * VBndPlaneInYMax

Definition at line 89 of file neBEM.h.

Referenced by neBEMReadGeometry().

◆ VBndPlaneInYMin

neBEMGLOBAL double * VBndPlaneInYMin

Definition at line 88 of file neBEM.h.

Referenced by neBEMReadGeometry().

◆ VBndPlaneInZMax

neBEMGLOBAL double * VBndPlaneInZMax

Definition at line 89 of file neBEM.h.

Referenced by neBEMReadGeometry().

◆ VBndPlaneInZMin

neBEMGLOBAL double * VBndPlaneInZMin

Definition at line 88 of file neBEM.h.

Referenced by neBEMReadGeometry().

◆ VFloatCon

neBEMGLOBAL double VFloatCon

Definition at line 128 of file neBEM.h.

Referenced by ReadSolution(), and Solve().

◆ volBoundaryType

neBEMGLOBAL int * volBoundaryType

Definition at line 63 of file neBEM.h.

Referenced by neBEMReadGeometry(), and ReadPrimitives().

◆ volCharge

neBEMGLOBAL double * volCharge

Definition at line 64 of file neBEM.h.

Referenced by neBEMReadGeometry(), and ReadPrimitives().

◆ volEpsilon

neBEMGLOBAL double* volEpsilon

Definition at line 64 of file neBEM.h.

Referenced by neBEMReadGeometry(), and ReadPrimitives().

◆ volMaterial

neBEMGLOBAL int * volMaterial

Definition at line 63 of file neBEM.h.

Referenced by neBEMReadGeometry(), and ReadPrimitives().

◆ VolMax

neBEMGLOBAL int VolMax

◆ volPotential

neBEMGLOBAL double * volPotential

Definition at line 64 of file neBEM.h.

Referenced by neBEMReadGeometry(), and ReadPrimitives().

◆ volRef

neBEMGLOBAL int* volRef

Definition at line 63 of file neBEM.h.

Referenced by neBEMReadGeometry(), and ReadPrimitives().

◆ VolRef1

◆ VolRef2

neBEMGLOBAL int * VolRef2

◆ volShape

neBEMGLOBAL int * volShape

Definition at line 63 of file neBEM.h.

Referenced by neBEMReadGeometry(), and ReadPrimitives().

◆ VolumeKnChArr

neBEMGLOBAL VolumeKnCh* VolumeKnChArr

Definition at line 216 of file neBEM.h.

Referenced by KnChPFAtPoint(), neBEMKnownCharges(), ReadElements(), and WriteElements().

◆ Voxel

Definition at line 371 of file neBEM.h.

Referenced by neBEMInitialize(), and VoxelFPR().

◆ VSystemChargeZero

neBEMGLOBAL double VSystemChargeZero

Definition at line 122 of file neBEM.h.

Referenced by ReadSolution(), and Solve().

◆ WtFieldChDen

neBEMGLOBAL double** WtFieldChDen

◆ WtFldBlkCrnrZ

neBEMGLOBAL double* WtFldBlkCrnrZ

Definition at line 497 of file neBEM.h.

Referenced by neBEMInitialize(), neBEMSolve(), and WtFldFastPFAtPoint().

◆ WtFldBlkLZ

neBEMGLOBAL double* WtFldBlkLZ

Definition at line 496 of file neBEM.h.

Referenced by neBEMInitialize(), neBEMSolve(), and WtFldFastPFAtPoint().

◆ WtFldBlkNbXCells

neBEMGLOBAL int* WtFldBlkNbXCells

Definition at line 493 of file neBEM.h.

Referenced by neBEMInitialize(), neBEMSolve(), and WtFldFastPFAtPoint().

◆ WtFldBlkNbYCells

neBEMGLOBAL int* WtFldBlkNbYCells

Definition at line 494 of file neBEM.h.

Referenced by neBEMInitialize(), neBEMSolve(), and WtFldFastPFAtPoint().

◆ WtFldBlkNbZCells

neBEMGLOBAL int* WtFldBlkNbZCells

Definition at line 495 of file neBEM.h.

Referenced by neBEMInitialize(), neBEMSolve(), and WtFldFastPFAtPoint().

◆ WtFldFastFX

neBEMGLOBAL double**** WtFldFastFX

Definition at line 513 of file neBEM.h.

Referenced by neBEMSolve(), and WtFldFastPFAtPoint().

◆ WtFldFastFY

neBEMGLOBAL double **** WtFldFastFY

Definition at line 513 of file neBEM.h.

Referenced by neBEMSolve(), and WtFldFastPFAtPoint().

◆ WtFldFastFZ

neBEMGLOBAL double **** WtFldFastFZ

Definition at line 513 of file neBEM.h.

Referenced by neBEMSolve(), and WtFldFastPFAtPoint().

◆ WtFldFastPot

neBEMGLOBAL double**** WtFldFastPot

Definition at line 512 of file neBEM.h.

Referenced by neBEMSolve(), and WtFldFastPFAtPoint().

◆ WtFldFastStgFX

neBEMGLOBAL double**** WtFldFastStgFX

Definition at line 515 of file neBEM.h.

Referenced by neBEMSolve(), and WtFldFastPFAtPoint().

◆ WtFldFastStgFY

neBEMGLOBAL double **** WtFldFastStgFY

Definition at line 515 of file neBEM.h.

Referenced by neBEMSolve(), and WtFldFastPFAtPoint().

◆ WtFldFastStgFZ

neBEMGLOBAL double **** WtFldFastStgFZ

Definition at line 515 of file neBEM.h.

Referenced by neBEMSolve(), and WtFldFastPFAtPoint().

◆ WtFldFastStgPot

neBEMGLOBAL double**** WtFldFastStgPot

Definition at line 514 of file neBEM.h.

Referenced by neBEMSolve(), and WtFldFastPFAtPoint().

◆ WtFldFastVol

Definition at line 491 of file neBEM.h.

Referenced by neBEMInitialize(), neBEMSolve(), and WtFldFastPFAtPoint().

◆ WtFldIgnoreVolCrnrX

neBEMGLOBAL double* WtFldIgnoreVolCrnrX

Definition at line 507 of file neBEM.h.

Referenced by neBEMInitialize(), and WtFldFastPFAtPoint().

◆ WtFldIgnoreVolCrnrY

neBEMGLOBAL double* WtFldIgnoreVolCrnrY

Definition at line 508 of file neBEM.h.

Referenced by neBEMInitialize(), and WtFldFastPFAtPoint().

◆ WtFldIgnoreVolCrnrZ

neBEMGLOBAL double* WtFldIgnoreVolCrnrZ

Definition at line 509 of file neBEM.h.

Referenced by neBEMInitialize(), and WtFldFastPFAtPoint().

◆ WtFldIgnoreVolLX

neBEMGLOBAL double* WtFldIgnoreVolLX

Definition at line 504 of file neBEM.h.

Referenced by neBEMInitialize(), and WtFldFastPFAtPoint().

◆ WtFldIgnoreVolLY

neBEMGLOBAL double* WtFldIgnoreVolLY

Definition at line 505 of file neBEM.h.

Referenced by neBEMInitialize(), and WtFldFastPFAtPoint().

◆ WtFldIgnoreVolLZ

neBEMGLOBAL double* WtFldIgnoreVolLZ

Definition at line 506 of file neBEM.h.

Referenced by neBEMInitialize(), and WtFldFastPFAtPoint().

◆ WtFldNbPtSkip

neBEMGLOBAL int WtFldNbPtSkip

Definition at line 476 of file neBEM.h.

Referenced by neBEMInitialize(), and neBEMSolve().

◆ WtFldNbStgPtSkip

neBEMGLOBAL int WtFldNbStgPtSkip

Definition at line 477 of file neBEM.h.

Referenced by neBEMInitialize(), and neBEMSolve().

◆ WtFldOmitVolCrnrX

neBEMGLOBAL double* WtFldOmitVolCrnrX

Definition at line 501 of file neBEM.h.

Referenced by neBEMInitialize(), and neBEMSolve().

◆ WtFldOmitVolCrnrY

neBEMGLOBAL double* WtFldOmitVolCrnrY

Definition at line 502 of file neBEM.h.

Referenced by neBEMInitialize(), and neBEMSolve().

◆ WtFldOmitVolCrnrZ

neBEMGLOBAL double* WtFldOmitVolCrnrZ

Definition at line 503 of file neBEM.h.

Referenced by neBEMInitialize(), and neBEMSolve().

◆ WtFldOmitVolLX

neBEMGLOBAL double* WtFldOmitVolLX

Definition at line 498 of file neBEM.h.

Referenced by neBEMInitialize(), and neBEMSolve().

◆ WtFldOmitVolLY

neBEMGLOBAL double* WtFldOmitVolLY

Definition at line 499 of file neBEM.h.

Referenced by neBEMInitialize(), and neBEMSolve().

◆ WtFldOmitVolLZ

neBEMGLOBAL double* WtFldOmitVolLZ

Definition at line 500 of file neBEM.h.

Referenced by neBEMInitialize(), and neBEMSolve().

◆ XBndPlaneInXMax

neBEMGLOBAL double* XBndPlaneInXMax

Definition at line 87 of file neBEM.h.

Referenced by neBEMReadGeometry().

◆ XBndPlaneInXMin

neBEMGLOBAL double* XBndPlaneInXMin

Definition at line 86 of file neBEM.h.

Referenced by neBEMReadGeometry().

◆ XNorm

neBEMGLOBAL double * XNorm

◆ XPeriod

neBEMGLOBAL double* XPeriod

◆ XVertex

◆ YBndPlaneInYMax

neBEMGLOBAL double * YBndPlaneInYMax

Definition at line 87 of file neBEM.h.

Referenced by neBEMReadGeometry().

◆ YBndPlaneInYMin

neBEMGLOBAL double * YBndPlaneInYMin

Definition at line 86 of file neBEM.h.

Referenced by neBEMReadGeometry().

◆ YNorm

neBEMGLOBAL double * YNorm

◆ YPeriod

neBEMGLOBAL double * YPeriod

◆ YVertex

◆ ZBndPlaneInZMax

neBEMGLOBAL double * ZBndPlaneInZMax

Definition at line 87 of file neBEM.h.

Referenced by neBEMReadGeometry().

◆ ZBndPlaneInZMin

neBEMGLOBAL double * ZBndPlaneInZMin

Definition at line 86 of file neBEM.h.

Referenced by neBEMReadGeometry().

◆ ZNorm

neBEMGLOBAL double * ZNorm

◆ ZPeriod

neBEMGLOBAL double * ZPeriod

◆ ZVertex