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

Go to the source code of this file.

Functions

double GetPotential (int ele, Point3D *localP)
 
double RecPot (int ele, Point3D *localP)
 
double TriPot (int ele, Point3D *localP)
 
double WirePot (int ele, Point3D *localP)
 
void GetFluxGCS (int ele, Point3D *localP, Vector3D *globalF)
 
void GetFlux (int ele, Point3D *localP, Vector3D *localF)
 
void RecFlux (int ele, Point3D *localP, Vector3D *localF)
 
void TriFlux (int ele, Point3D *localP, Vector3D *localF)
 
void WireFlux (int ele, Point3D *localP, Vector3D *localF)
 
int PFAtPoint (Point3D *globalP, double *Potential, Vector3D *globalF)
 
int ElePFAtPoint (Point3D *globalP, double *Potential, Vector3D *globalF)
 
int KnChPFAtPoint (Point3D *globalP, double *Potential, Vector3D *globalF)
 
int VoxelFPR (void)
 
int MapFPR (void)
 
int CreateFastVolPF (void)
 
int CreateFastVolElePF (void)
 
int FastPFAtPoint (Point3D *globalP, double *Potential, Vector3D *globalF)
 
int FastElePFAtPoint (Point3D *, double *, Vector3D *)
 
int FastKnChPFAtPoint (Point3D *globalP, double *Potential, Vector3D *globalF)
 
int WtFldPFAtPoint (Point3D *globalP, double *Potential, Vector3D *globalF, int IdWtField)
 
int CreateWtFldFastVolPF (int IdWtField)
 
int WtFldFastPFAtPoint (Point3D *globalP, double *Potential, Vector3D *globalF, int IdWtField)
 
void GetPFGCS (int type, double a, double b, Point3D *localP, double *Potential, Vector3D *globalF, DirnCosn3D *DirCos)
 
void GetPF (int type, double a, double b, double x, double y, double z, double *Potential, Vector3D *localF)
 
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)
 
void GetPrimPFGCS (int prim, Point3D *localP, double *Potential, Vector3D *globalF, DirnCosn3D *DirCos)
 
void GetPrimPF (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)
 
void WirePrimPF (int prim, Point3D *localP, double *Potential, Vector3D *localF)
 
double TriLin (double xd, double yd, double zd, double c000, double c100, double c010, double c001, double c110, double c101, double c011, double c111)
 

Function Documentation

◆ CreateFastVolElePF()

int CreateFastVolElePF ( void )

Definition at line 1722 of file ComputeProperties.c.

1722 {
1723 int dbgFn = 0;
1724 int fstatus;
1725
1726 int nbXCells;
1727 int nbYCells;
1728 int nbZCells;
1729 double startX;
1730 double startY;
1731 double startZ;
1732 double delX;
1733 double delY;
1734 double delZ;
1735
1736 printf(
1737 "\nPhysical potential and field computation within basic fast volume\n");
1738 int bskip = 0, iskip = 0, jskip = 0, kskip = 0;
1739
1740 // calculate n-skips based on NbPtSkip
1741 if (NbPtSkip) {
1742 int volptcnt = 0, endskip = 0;
1743
1744 for (int block = 1; block <= FastVol.NbBlocks; ++block) {
1745 nbXCells = BlkNbXCells[block];
1746 nbYCells = BlkNbYCells[block];
1747 nbZCells = BlkNbZCells[block];
1748 for (int i = 1; i <= nbXCells + 1; ++i) {
1749 for (int j = 1; j <= nbYCells + 1; ++j) {
1750 for (int k = 1; k <= nbZCells + 1; ++k) {
1751 ++volptcnt;
1752
1753 if (volptcnt == NbPtSkip) {
1754 bskip = block - 1;
1755 iskip = i - 1;
1756 jskip = j - 1;
1757 kskip = k;
1758 endskip = 1;
1759 }
1760
1761 if (endskip) break;
1762 }
1763 if (endskip) break;
1764 }
1765 if (endskip) break;
1766 }
1767 if (endskip) break;
1768 }
1769 if (dbgFn) {
1770 printf(
1771 "Basic fast volume => bskip, iskip, jskip, kskip: %d, %d, %d, %d\n",
1772 bskip, iskip, jskip, kskip);
1773 }
1774 } // NbPtSkip
1775
1776 char FastVolPFFile[256];
1777 strcpy(FastVolPFFile, BCOutDir);
1778 strcat(FastVolPFFile, "/FastVolPF.out");
1779 FILE *fFastVolPF = fopen(FastVolPFFile, "w");
1780 if (fFastVolPF == NULL) {
1781 neBEMMessage("FastVolPF - FastVolPFFile");
1782 return -1;
1783 }
1784 fprintf(fFastVolPF, "#block\tX\tY\tZ\tPot\tFX\tFY\tFZ\n");
1785
1786 if (dbgFn) {
1787 printf("FastVolPF.out created ...\n");
1788 fflush(stdout);
1789 }
1790
1791 for (int block = 1 + bskip; block <= FastVol.NbBlocks; ++block) {
1792 nbXCells = BlkNbXCells[block];
1793 nbYCells = BlkNbYCells[block];
1794 nbZCells = BlkNbZCells[block];
1795 startX = FastVol.CrnrX;
1796 startY = FastVol.CrnrY;
1797 startZ = BlkCrnrZ[block];
1798 delX = FastVol.LX / nbXCells;
1799 delY = FastVol.LY / nbYCells;
1800 delZ = BlkLZ[block] / nbZCells;
1801 printf(
1802 "NbBlocks: %d, block: %d, nbXCells: %d, nbYCells: %d, nbZCells: %d\n",
1803 FastVol.NbBlocks, block, nbXCells, nbYCells, nbZCells);
1804
1805 if (dbgFn) {
1806 printf("block: %d\n", block);
1807 printf("nbXCells, nbYCells, nbZCells: %d, %d, %d\n", nbXCells, nbYCells,
1808 nbZCells);
1809 printf("startX, startY, startZ: %le, %le, %le\n", startX, startY, startZ);
1810 printf("delX, delY, delZ: %le, %le, %le\n", delX, delY, delZ);
1811 printf("bskip, iskip, jskip, kskip: %d, %d, %d, %d\n", bskip, iskip,
1812 jskip, kskip);
1813 fflush(stdout);
1814 }
1815 // total number of points in a given block
1816 // int blktotpt = (nbXCells + 1) * (nbYCells + 1) * (nbZCells + 1);
1817 for (int i = 1 + iskip; i <= nbXCells + 1; ++i) {
1818 for (int j = 1 + jskip; j <= nbYCells + 1; ++j) {
1819 printf("Fast volume => block: %3d, i: %4d, j: %4d", block, i, j);
1820 fflush(stdout);
1821
1822 Point3D point;
1823#ifdef _OPENMP
1824 int nthreads = 1, tid = 0;
1825#pragma omp parallel private(nthreads, tid)
1826#endif
1827 {
1828#ifdef _OPENMP
1829 if (dbgFn) {
1830 tid = omp_get_thread_num();
1831 if (tid == 0) {
1832 nthreads = omp_get_num_threads();
1833 printf("Starting fast volume computation with %d threads\n",
1834 nthreads);
1835 }
1836 }
1837#endif
1838 int k;
1839 int omitFlag;
1840 double potential;
1841 Vector3D field;
1842#ifdef _OPENMP
1843#pragma omp for private(k, point, omitFlag, potential, field)
1844#endif
1845 for (k = 1 + kskip; k <= nbZCells + 1; ++k) {
1846 potential = 0.0;
1847 field.X = field.Y = field.Z = 0.0;
1848
1849 point.X = startX + (i - 1) * delX;
1850 point.Y = startY + (j - 1) * delY;
1851 point.Z = startZ + (k - 1) * delZ;
1852
1853 // Check whether the point falls within a volume that should be
1854 // ignored
1855 omitFlag = 0;
1856 for (int omit = 1; omit <= FastVol.NbOmitVols; ++omit) {
1857 if ((point.X > OmitVolCrnrX[omit]) &&
1858 (point.X < OmitVolCrnrX[omit] + OmitVolLX[omit]) &&
1859 (point.Y > OmitVolCrnrY[omit]) &&
1860 (point.Y < OmitVolCrnrY[omit] + OmitVolLY[omit]) &&
1861 (point.Z > OmitVolCrnrZ[omit]) &&
1862 (point.Z < OmitVolCrnrZ[omit] + OmitVolLZ[omit])) {
1863 omitFlag = 1;
1864 break;
1865 }
1866 } // loop over omitted volumes
1867
1868 if (dbgFn) {
1869 printf("block, i, j, k: %d, %d, %d, %d\n", block, i, j, k);
1870 printf("point X, Y, Z: %.8lg\t%.8lg\t%.8lg\n",
1871 point.X / LengthScale, point.Y / LengthScale,
1872 point.Z / LengthScale);
1873 printf("omitFlag: %d\n", omitFlag);
1874 fflush(stdout);
1875 }
1876
1877 if (omitFlag) {
1878 potential = field.X = field.Y = field.Z = 0.0;
1879 } else {
1880 // fstatus = ElePFAtPoint(&point, &potential, &field);
1881 fstatus =
1882 PFAtPoint(&point, &potential, &field); // both ele and KnCh
1883 if (fstatus != 0) {
1885 "wrong ElePFAtPoint return value in FastVolElePF.\n");
1886 // return -1;
1887 }
1888 } // else omitFlag
1889 if (dbgFn) {
1890 printf("%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\n",
1891 point.X / LengthScale, point.Y / LengthScale,
1892 point.Z / LengthScale, potential / LengthScale, field.X,
1893 field.Y, field.Z);
1894 fflush(stdout);
1895 }
1896
1897 FastPot[block][i][j][k] = potential;
1898 FastFX[block][i][j][k] = field.X;
1899 FastFY[block][i][j][k] = field.Y;
1900 FastFZ[block][i][j][k] = field.Z;
1901 } // loop k
1902 } // pragma omp parallel
1903
1904 for (int k = 1 + kskip; k <= nbZCells + 1; ++k) // file output
1905 {
1906 point.X = startX + (i - 1) * delX;
1907 point.Y = startY + (j - 1) * delY;
1908 point.Z = startZ + (k - 1) * delZ;
1909
1910 fprintf(fFastVolPF,
1911 "%4d\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\n",
1912 block, point.X / LengthScale, point.Y / LengthScale,
1913 point.Z / LengthScale, FastPot[block][i][j][k],
1914 FastFX[block][i][j][k], FastFY[block][i][j][k],
1915 FastFZ[block][i][j][k]);
1916 }
1917 fflush(fFastVolPF); // file output over
1918
1919 printf(
1920 "\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"
1921 "\b\b\b\b\b\b\b\b\b\b");
1922 } // loop j
1923 } // loop i
1924 } // loop block
1925
1926 fclose(fFastVolPF);
1927
1928 if (OptStaggerFastVol) {
1929 printf("Potential and field computation within staggered fast volume\n");
1930
1931 bskip = iskip = jskip = kskip = 0;
1932
1933 // calculate n-skips based on NbStgPtSkip
1934 if (NbStgPtSkip) {
1935 int volptcnt = 0, endskip = 0;
1936
1937 for (int block = 1; block <= FastVol.NbBlocks; ++block) {
1938 nbXCells = BlkNbXCells[block];
1939 nbYCells = BlkNbYCells[block];
1940 nbZCells = BlkNbZCells[block];
1941 for (int i = 1; i <= nbXCells + 1; ++i) {
1942 for (int j = 1; j <= nbYCells + 1; ++j) {
1943 for (int k = 1; k <= nbZCells + 1; ++k) {
1944 ++volptcnt;
1945
1946 if (volptcnt == NbStgPtSkip) {
1947 bskip = block - 1;
1948 iskip = i - 1;
1949 jskip = j - 1;
1950 kskip = k;
1951 endskip = 1;
1952 }
1953
1954 if (endskip) break;
1955 }
1956 if (endskip) break;
1957 }
1958 if (endskip) break;
1959 }
1960 if (endskip) break;
1961 }
1962 if (dbgFn) {
1963 printf(
1964 "Staggered volume => bskip, iskip, jskip, kskip: %d, %d, %d, %d\n",
1965 bskip, iskip, jskip, kskip);
1966 }
1967 } // NbStgPtSkip
1968
1969 char StgFastVolPFFile[256];
1970 FILE *fStgFastVolPF;
1971 strcpy(StgFastVolPFFile, BCOutDir);
1972 strcat(StgFastVolPFFile, "/StgFastVolPF.out");
1973 fStgFastVolPF = fopen(StgFastVolPFFile, "w");
1974 if (fStgFastVolPF == NULL) {
1975 neBEMMessage("FastVolPF - StgFastVolPFFile");
1976 return -1;
1977 }
1978 fprintf(fStgFastVolPF, "#block\tX\tY\tZ\tPot\tFX\tFY\tFZ\n");
1979
1980 if (dbgFn) {
1981 printf("StgFastVolPF.out created ...\n");
1982 fflush(stdout);
1983 }
1984
1985 for (int block = 1 + bskip; block <= FastVol.NbBlocks; ++block) {
1986 nbXCells = BlkNbXCells[block];
1987 nbYCells = BlkNbYCells[block];
1988 nbZCells = BlkNbZCells[block];
1989 startX = FastVol.CrnrX + FastVol.LX;
1990 startY = FastVol.CrnrY + FastVol.YStagger;
1991 startZ = BlkCrnrZ[block];
1992 delX = FastVol.LX / nbXCells;
1993 delY = FastVol.LY / nbYCells;
1994 delZ = BlkLZ[block] / nbZCells;
1995 printf(
1996 "NbBlocks: %d, block: %d, nbXCells: %d, nbYCells: %d, nbZCells: %d\n",
1997 FastVol.NbBlocks, block, nbXCells, nbYCells, nbZCells);
1998
1999 if (dbgFn) {
2000 printf("block: %d\n", block);
2001 printf("nbXCells, nbYCells, nbZCells: %d, %d, %d\n", nbXCells, nbYCells,
2002 nbZCells);
2003 printf("startX, startY, startZ: %le, %le, %le\n", startX, startY,
2004 startZ);
2005 printf("delX, delY, delZ: %le, %le, %le\n", delX, delY, delZ);
2006 printf("bskip, iskip, jskip, kskip: %d, %d, %d, %d\n", bskip, iskip,
2007 jskip, kskip);
2008 fflush(stdout);
2009 }
2010
2011 // int blktotpt = (nbXCells + 1) * (nbYCells + 1) * (nbZCells + 1);
2012 for (int i = 1 + iskip; i <= nbXCells + 1; ++i) {
2013 for (int j = 1 + jskip; j <= nbYCells + 1; ++j) {
2014 printf("Fast volume => block: %3d, i: %4d, j: %4d", block, i, j);
2015 fflush(stdout);
2016
2017 Point3D point;
2018#ifdef _OPENMP
2019 int nthreads = 1, tid = 0;
2020#pragma omp parallel private(nthreads, tid)
2021#endif
2022 {
2023#ifdef _OPENMP
2024 if (dbgFn) {
2025 tid = omp_get_thread_num();
2026 if (tid == 0) {
2027 nthreads = omp_get_num_threads();
2028 printf(
2029 "Starting staggered fast volume computation with %d "
2030 "threads\n",
2031 nthreads);
2032 }
2033 }
2034#endif
2035 int k;
2036 int omitFlag;
2037 double potential;
2038 Vector3D field;
2039#ifdef _OPENMP
2040#pragma omp for private(k, point, omitFlag, potential, field)
2041#endif
2042 for (k = 1 + kskip; k <= nbZCells + 1; ++k) {
2043 potential = 0.0;
2044 field.X = field.Y = field.Z = 0.0;
2045
2046 point.X = startX + (i - 1) * delX;
2047 point.Y = startY + (j - 1) * delY;
2048 point.Z = startZ + (k - 1) * delZ;
2049
2050 // Check whether point falls within a volume that should be
2051 // ignored
2052 omitFlag = 0;
2053 for (int omit = 1; omit <= FastVol.NbOmitVols; ++omit) {
2054 if ((point.X > OmitVolCrnrX[omit] + FastVol.LX) &&
2055 (point.X <
2056 OmitVolCrnrX[omit] + OmitVolLX[omit] + FastVol.LX) &&
2057 (point.Y > OmitVolCrnrY[omit] + FastVol.YStagger) &&
2058 (point.Y <
2059 OmitVolCrnrY[omit] + OmitVolLY[omit] + FastVol.YStagger) &&
2060 (point.Z > OmitVolCrnrZ[omit]) &&
2061 (point.Z < OmitVolCrnrZ[omit] + OmitVolLZ[omit])) {
2062 omitFlag = 1;
2063 break;
2064 }
2065 } // loop over omitted volumes
2066
2067 if (dbgFn) {
2068 printf("point X, Y, Z: %.8lg\t%.8lg\t%.8lg\n",
2069 point.X / LengthScale, point.Y / LengthScale,
2070 point.Z / LengthScale);
2071 printf("omitFlag: %d\n", omitFlag);
2072 fflush(stdout);
2073 }
2074
2075 if (omitFlag) {
2076 potential = field.X = field.Y = field.Z = 0.0;
2077 } else {
2078 // fstatus = ElePFAtPoint(&point, &potential, &field);
2079 fstatus =
2080 PFAtPoint(&point, &potential, &field); // both ele & KnCh
2081 if (fstatus != 0) {
2083 "wrong PFAtPoint return value in FastVolElePF.\n");
2084 // return -1;
2085 }
2086 } // else omitFlag
2087 if (dbgFn) {
2088 printf("%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\n",
2089 point.X / LengthScale, point.Y / LengthScale,
2090 point.Z / LengthScale, potential / LengthScale, field.X,
2091 field.Y, field.Z);
2092 fflush(stdout);
2093 }
2094
2095 StgFastPot[block][i][j][k] = potential;
2096 StgFastFX[block][i][j][k] = field.X;
2097 StgFastFY[block][i][j][k] = field.Y;
2098 StgFastFZ[block][i][j][k] = field.Z;
2099 } // loop k
2100 } // pragma omp
2101
2102 for (int k = 1 + kskip; k <= nbZCells + 1; ++k) // file output
2103 {
2104 point.X = startX + (i - 1) * delX;
2105 point.Y = startY + (j - 1) * delY;
2106 point.Z = startZ + (k - 1) * delZ;
2107
2108 fprintf(fStgFastVolPF,
2109 "%4d\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\n",
2110 block, point.X / LengthScale, point.Y / LengthScale,
2111 point.Z / LengthScale, StgFastPot[block][i][j][k],
2112 StgFastFX[block][i][j][k], StgFastFY[block][i][j][k],
2113 StgFastFZ[block][i][j][k]);
2114 }
2115 fflush(fStgFastVolPF); // file output over
2116
2117 printf(
2118 "\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"
2119 "\b\b\b\b\b\b\b\b\b\b\b");
2120 } // loop j
2121 } // loop i
2122 } // loop block
2123
2124 fclose(fStgFastVolPF);
2125 } // if OptStaggerFastVol
2126
2127 return 0;
2128} // CreateFastVolElePF ends
int PFAtPoint(Point3D *globalP, double *Potential, Vector3D *globalF)
int neBEMMessage(const char *message)
neBEMGLOBAL double **** FastFY
Definition neBEM.h:461
neBEMGLOBAL int OptStaggerFastVol
Definition neBEM.h:419
neBEMGLOBAL double **** FastFZ
Definition neBEM.h:461
neBEMGLOBAL double * OmitVolCrnrZ
Definition neBEM.h:451
neBEMGLOBAL double * OmitVolLX
Definition neBEM.h:446
neBEMGLOBAL double **** StgFastFY
Definition neBEM.h:463
neBEMGLOBAL double **** StgFastFZ
Definition neBEM.h:463
neBEMGLOBAL double * BlkCrnrZ
Definition neBEM.h:445
neBEMGLOBAL FastAlgoVol FastVol
Definition neBEM.h:439
neBEMGLOBAL double * BlkLZ
Definition neBEM.h:444
neBEMGLOBAL double * OmitVolCrnrX
Definition neBEM.h:449
neBEMGLOBAL double * OmitVolLZ
Definition neBEM.h:448
neBEMGLOBAL int NbStgPtSkip
Definition neBEM.h:425
neBEMGLOBAL int NbPtSkip
Definition neBEM.h:424
neBEMGLOBAL double * OmitVolCrnrY
Definition neBEM.h:450
neBEMGLOBAL double **** FastFX
Definition neBEM.h:461
neBEMGLOBAL double * OmitVolLY
Definition neBEM.h:447
neBEMGLOBAL int * BlkNbXCells
Definition neBEM.h:441
neBEMGLOBAL int * BlkNbZCells
Definition neBEM.h:443
neBEMGLOBAL double LengthScale
Definition neBEM.h:198
neBEMGLOBAL double **** FastPot
Definition neBEM.h:460
neBEMGLOBAL double **** StgFastFX
Definition neBEM.h:463
neBEMGLOBAL char BCOutDir[256]
Definition neBEM.h:223
neBEMGLOBAL double **** StgFastPot
Definition neBEM.h:462
neBEMGLOBAL int * BlkNbYCells
Definition neBEM.h:442
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

Referenced by CreateFastVolPF().

◆ CreateFastVolPF()

int CreateFastVolPF ( void )

Definition at line 1689 of file ComputeProperties.c.

1689 {
1690 // The following may be necessary only during the first time step / iteration
1691 // At present, FastVolElePF() considers both element and KnCh effects
1692 // and create one combined fast volume.
1693 int fstatus = CreateFastVolElePF();
1694 if (fstatus) {
1695 printf(
1696 "Problem in FastVolElePF being called from FastVolPF ... returning\n");
1697 return -1;
1698 }
1699
1700 /*
1701 // The following is likely to change throughout the computation and necessary
1702 // at all time steps. However, in order to achieve computational economy, it
1703 // may be prudent to carry out the following only after several time steps.
1704 if (OptKnCh) {
1705 fstatus = CreateFastVolKnChPF();
1706 if (fstatus) {
1707 printf("Problem in FastVolKnChPF being called from FastVolPF...
1708 returning\n"); return -1;
1709 }
1710 }
1711 */
1712
1713 return 0;
1714} // CreateFastVolPF ends
int CreateFastVolElePF(void)

Referenced by neBEMSolve().

◆ CreateWtFldFastVolPF()

int CreateWtFldFastVolPF ( int IdWtField)

Definition at line 3536 of file ComputeProperties.c.

3536 {
3537 if (IdWtField >= MAXWtFld) {
3538 printf(
3539 "neBEMPrepareWeightingField: reached MaxWtField (%d) weighting "
3540 "fields.\n",
3541 MAXWtFld);
3542 return -1;
3543 }
3544
3545 int dbgFn = 0;
3546 int fstatus;
3547
3548 int nbXCells;
3549 int nbYCells;
3550 int nbZCells;
3551 double startX;
3552 double startY;
3553 double startZ;
3554 double delX;
3555 double delY;
3556 double delZ;
3557
3558 printf("\nComputing weighting potential & field within basic fast volume\n");
3559 int bskip = 0, iskip = 0, jskip = 0, kskip = 0;
3560
3561 // calculate n-skips based on NbPtSkip
3562 if (NbPtSkip) {
3563 int volptcnt = 0, endskip = 0;
3564
3565 for (int block = 1; block <= WtFldFastVol[IdWtField].NbBlocks; ++block) {
3566 nbXCells = WtFldBlkNbXCells[IdWtField][block];
3567 nbYCells = WtFldBlkNbYCells[IdWtField][block];
3568 nbZCells = WtFldBlkNbZCells[IdWtField][block];
3569 for (int i = 1; i <= nbXCells + 1; ++i) {
3570 for (int j = 1; j <= nbYCells + 1; ++j) {
3571 for (int k = 1; k <= nbZCells + 1; ++k) {
3572 ++volptcnt;
3573
3574 if (volptcnt == WtFldNbPtSkip[IdWtField]) {
3575 bskip = block - 1;
3576 iskip = i - 1;
3577 jskip = j - 1;
3578 kskip = k;
3579 endskip = 1;
3580 }
3581
3582 if (endskip) break;
3583 }
3584 if (endskip) break;
3585 }
3586 if (endskip) break;
3587 }
3588 if (endskip) break;
3589 }
3590 if (dbgFn) {
3591 printf(
3592 "Basic fast volume => bskip, iskip, jskip, kskip: %d, %d, %d, %d\n",
3593 bskip, iskip, jskip, kskip);
3594 }
3595 } // WtFldNbPtSkip
3596
3597 // stringify the integer
3598 char stringIdWtField[16];
3599 snprintf(stringIdWtField, 16, "%d", IdWtField);
3600
3601 char WtFldFastVolPFFile[256];
3602 strcpy(WtFldFastVolPFFile, BCOutDir);
3603 strcat(WtFldFastVolPFFile, "/WtFldFastVolPF_");
3604 strcat(WtFldFastVolPFFile, stringIdWtField);
3605 strcat(WtFldFastVolPFFile, ".out");
3606 FILE *fWtFldFastVolPF = fopen(WtFldFastVolPFFile, "w");
3607 if (fWtFldFastVolPF == NULL) {
3608 neBEMMessage("CreateWtFldFastVolPF - WtFldFastVolPFFile");
3609 return -1;
3610 }
3611 fprintf(fWtFldFastVolPF, "#block\tX\tY\tZ\tPot\tFX\tFY\tFZ\n");
3612
3613 if (dbgFn) {
3614 printf("WtFldFastVolPF.out created ...\n");
3615 fflush(stdout);
3616 }
3617
3618 for (int block = 1 + bskip; block <= WtFldFastVol[IdWtField].NbBlocks;
3619 ++block) {
3620 nbXCells = WtFldBlkNbXCells[IdWtField][block];
3621 nbYCells = WtFldBlkNbYCells[IdWtField][block];
3622 nbZCells = WtFldBlkNbZCells[IdWtField][block];
3623 startX = WtFldFastVol[IdWtField].CrnrX;
3624 startY = WtFldFastVol[IdWtField].CrnrY;
3625 startZ = WtFldBlkCrnrZ[IdWtField][block];
3626 delX = WtFldFastVol[IdWtField].LX / nbXCells;
3627 delY = WtFldFastVol[IdWtField].LY / nbYCells;
3628 delZ = WtFldBlkLZ[IdWtField][block] / nbZCells;
3629 printf(
3630 "WtFldNbBlocks: %d, block: %d, nbXCells: %d, nbYCells: %d, nbZCells: "
3631 "%d\n",
3632 WtFldFastVol[IdWtField].NbBlocks, block, nbXCells, nbYCells, nbZCells);
3633
3634 if (dbgFn) {
3635 printf("block: %d\n", block);
3636 printf("nbXCells, nbYCells, nbZCells: %d, %d, %d\n", nbXCells, nbYCells,
3637 nbZCells);
3638 printf("startX, startY, startZ: %le, %le, %le\n", startX, startY, startZ);
3639 printf("delX, delY, delZ: %le, %le, %le\n", delX, delY, delZ);
3640 printf("bskip, iskip, jskip, kskip: %d, %d, %d, %d\n", bskip, iskip,
3641 jskip, kskip);
3642 fflush(stdout);
3643 }
3644 // total number of points in a given block
3645 // int blktotpt = (nbXCells + 1) * (nbYCells + 1) * (nbZCells + 1);
3646 for (int i = 1 + iskip; i <= nbXCells + 1; ++i) {
3647 for (int j = 1 + jskip; j <= nbYCells + 1; ++j) {
3648 printf("Fast volume => block: %3d, i: %4d, j: %4d", block, i, j);
3649 fflush(stdout);
3650
3651 Point3D point;
3652#ifdef _OPENMP
3653 int nthreads = 1, tid = 0;
3654#pragma omp parallel private(nthreads, tid)
3655#endif
3656 {
3657#ifdef _OPENMP
3658 if (dbgFn) {
3659 tid = omp_get_thread_num();
3660 if (tid == 0) {
3661 nthreads = omp_get_num_threads();
3662 printf("Starting fast volume computation with %d threads\n",
3663 nthreads);
3664 }
3665 }
3666#endif
3667 int k;
3668 int omitFlag;
3669 double potential;
3670 Vector3D field;
3671#ifdef _OPENMP
3672#pragma omp for private(k, point, omitFlag, potential, field)
3673#endif
3674 for (k = 1 + kskip; k <= nbZCells + 1; ++k) {
3675 potential = 0.0;
3676 field.X = field.Y = field.Z = 0.0;
3677
3678 point.X = startX + (i - 1) * delX;
3679 point.Y = startY + (j - 1) * delY;
3680 point.Z = startZ + (k - 1) * delZ;
3681
3682 // Check whether the point falls within a volume that should be
3683 // ignored
3684 omitFlag = 0;
3685 for (int omit = 1; omit <= WtFldFastVol[IdWtField].NbOmitVols;
3686 ++omit) {
3687 if ((point.X > WtFldOmitVolCrnrX[IdWtField][omit]) &&
3688 (point.X < WtFldOmitVolCrnrX[IdWtField][omit] +
3689 WtFldOmitVolLX[IdWtField][omit]) &&
3690 (point.Y > WtFldOmitVolCrnrY[IdWtField][omit]) &&
3691 (point.Y < WtFldOmitVolCrnrY[IdWtField][omit] +
3692 WtFldOmitVolLY[IdWtField][omit]) &&
3693 (point.Z > WtFldOmitVolCrnrZ[IdWtField][omit]) &&
3694 (point.Z < WtFldOmitVolCrnrZ[IdWtField][omit] +
3695 WtFldOmitVolLZ[IdWtField][omit])) {
3696 omitFlag = 1;
3697 break;
3698 }
3699 } // loop over omitted volumes
3700
3701 if (dbgFn) {
3702 printf("block, i, j, k: %d, %d, %d, %d\n", block, i, j, k);
3703 printf("point X, Y, Z: %.8lg\t%.8lg\t%.8lg\n",
3704 point.X / LengthScale, point.Y / LengthScale,
3705 point.Z / LengthScale);
3706 printf("omitFlag: %d\n", omitFlag);
3707 fflush(stdout);
3708 }
3709
3710 if (omitFlag) {
3711 potential = field.X = field.Y = field.Z = 0.0;
3712 } else {
3713 fstatus = WtFldPFAtPoint(&point, &potential, &field, IdWtField);
3714 if (fstatus != 0) {
3715 neBEMMessage("wrong return from WtFldPFAtPoint.\n");
3716 // return -1;
3717 }
3718 } // else omitFlag
3719 if (dbgFn) {
3720 printf("%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\n",
3721 point.X / LengthScale, point.Y / LengthScale,
3722 point.Z / LengthScale, potential / LengthScale, field.X,
3723 field.Y, field.Z);
3724 fflush(stdout);
3725 }
3726
3727 WtFldFastPot[IdWtField][block][i][j][k] = potential;
3728 WtFldFastFX[IdWtField][block][i][j][k] = field.X;
3729 WtFldFastFY[IdWtField][block][i][j][k] = field.Y;
3730 WtFldFastFZ[IdWtField][block][i][j][k] = field.Z;
3731 } // loop k
3732 } // pragma omp parallel
3733
3734 for (int k = 1 + kskip; k <= nbZCells + 1; ++k) // file output
3735 {
3736 point.X = startX + (i - 1) * delX;
3737 point.Y = startY + (j - 1) * delY;
3738 point.Z = startZ + (k - 1) * delZ;
3739
3740 fprintf(fWtFldFastVolPF,
3741 "%4d\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\n",
3742 block, point.X / LengthScale, point.Y / LengthScale,
3743 point.Z / LengthScale,
3744 WtFldFastPot[IdWtField][block][i][j][k],
3745 WtFldFastFX[IdWtField][block][i][j][k],
3746 WtFldFastFY[IdWtField][block][i][j][k],
3747 WtFldFastFZ[IdWtField][block][i][j][k]);
3748 }
3749 fflush(fWtFldFastVolPF); // file output over
3750
3751 printf(
3752 "\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"
3753 "\b\b\b\b\b\b\b\b\b\b");
3754 } // loop j
3755 } // loop i
3756 } // loop block
3757
3758 fclose(fWtFldFastVolPF);
3759
3760 if (OptStaggerWtFldFastVol[IdWtField]) {
3761 printf(
3762 "\nComputing weighting potential & field within staggered fast "
3763 "volume\n");
3764
3765 bskip = iskip = jskip = kskip = 0;
3766
3767 // calculate n-skips based on StgWtFldNbPtSkip
3768 if (StgWtFldNbPtSkip[IdWtField]) {
3769 int volptcnt = 0, endskip = 0;
3770
3771 for (int block = 1; block <= WtFldFastVol[IdWtField].NbBlocks; ++block) {
3772 nbXCells = WtFldBlkNbXCells[IdWtField][block];
3773 nbYCells = WtFldBlkNbYCells[IdWtField][block];
3774 nbZCells = WtFldBlkNbZCells[IdWtField][block];
3775 for (int i = 1; i <= nbXCells + 1; ++i) {
3776 for (int j = 1; j <= nbYCells + 1; ++j) {
3777 for (int k = 1; k <= nbZCells + 1; ++k) {
3778 ++volptcnt;
3779
3780 if (volptcnt == StgWtFldNbPtSkip[IdWtField]) {
3781 bskip = block - 1;
3782 iskip = i - 1;
3783 jskip = j - 1;
3784 kskip = k;
3785 endskip = 1;
3786 }
3787
3788 if (endskip) break;
3789 }
3790 if (endskip) break;
3791 }
3792 if (endskip) break;
3793 }
3794 if (endskip) break;
3795 }
3796 if (dbgFn) {
3797 printf(
3798 "Staggered volume => bskip, iskip, jskip, kskip: %d, %d, %d, %d\n",
3799 bskip, iskip, jskip, kskip);
3800 }
3801 } // StgWtFldNbPtSkip
3802
3803 char StgWtFldFastVolPFFile[256];
3804 strcpy(StgWtFldFastVolPFFile, BCOutDir);
3805 strcat(StgWtFldFastVolPFFile, "/StgWtFldFastVolPF_");
3806 strcat(StgWtFldFastVolPFFile, stringIdWtField);
3807 strcat(StgWtFldFastVolPFFile, ".out");
3808 FILE *fStgWtFldFastVolPF = fopen(StgWtFldFastVolPFFile, "w");
3809 if (fStgWtFldFastVolPF == NULL) {
3810 neBEMMessage("WtFldFastVolPF - StgWtFldFastVolPFFile");
3811 return -1;
3812 }
3813 fprintf(fStgWtFldFastVolPF, "#block\tX\tY\tZ\tPot\tFX\tFY\tFZ\n");
3814
3815 if (dbgFn) {
3816 printf("StgWtFldFastVolPF.out created ...\n");
3817 fflush(stdout);
3818 }
3819
3820 for (int block = 1 + bskip; block <= WtFldFastVol[IdWtField].NbBlocks;
3821 ++block) {
3822 nbXCells = WtFldBlkNbXCells[IdWtField][block];
3823 nbYCells = WtFldBlkNbYCells[IdWtField][block];
3824 nbZCells = WtFldBlkNbZCells[IdWtField][block];
3825 startX = WtFldFastVol[IdWtField].CrnrX + WtFldFastVol[IdWtField].LX;
3826 startY = WtFldFastVol[IdWtField].CrnrY + WtFldFastVol[IdWtField].YStagger;
3827 startZ = WtFldBlkCrnrZ[IdWtField][block];
3828 delX = WtFldFastVol[IdWtField].LX / nbXCells;
3829 delY = WtFldFastVol[IdWtField].LY / nbYCells;
3830 delZ = WtFldBlkLZ[IdWtField][block] / nbZCells;
3831 printf(
3832 "NbBlocks: %d, block: %d, nbXCells: %d, nbYCells: %d, nbZCells: %d\n",
3833 WtFldFastVol[IdWtField].NbBlocks, block, nbXCells, nbYCells,
3834 nbZCells);
3835
3836 if (dbgFn) {
3837 printf("block: %d\n", block);
3838 printf("nbXCells, nbYCells, nbZCells: %d, %d, %d\n", nbXCells, nbYCells,
3839 nbZCells);
3840 printf("startX, startY, startZ: %le, %le, %le\n", startX, startY,
3841 startZ);
3842 printf("delX, delY, delZ: %le, %le, %le\n", delX, delY, delZ);
3843 printf("bskip, iskip, jskip, kskip: %d, %d, %d, %d\n", bskip, iskip,
3844 jskip, kskip);
3845 fflush(stdout);
3846 }
3847
3848 // int blktotpt = (nbXCells + 1) * (nbYCells + 1) * (nbZCells + 1);
3849 for (int i = 1 + iskip; i <= nbXCells + 1; ++i) {
3850 for (int j = 1 + jskip; j <= nbYCells + 1; ++j) {
3851 printf("Fast volume => block: %3d, i: %4d, j: %4d", block, i, j);
3852 fflush(stdout);
3853
3854 Point3D point;
3855#ifdef _OPENMP
3856 int nthreads = 1, tid = 0;
3857#pragma omp parallel private(nthreads, tid)
3858#endif
3859 {
3860#ifdef _OPENMP
3861 if (dbgFn) {
3862 tid = omp_get_thread_num();
3863 if (tid == 0) {
3864 nthreads = omp_get_num_threads();
3865 printf(
3866 "Starting staggered fast volume computation with %d "
3867 "threads\n",
3868 nthreads);
3869 }
3870 }
3871#endif
3872 int k;
3873 int omitFlag;
3874 double potential;
3875 Vector3D field;
3876#ifdef _OPENMP
3877#pragma omp for private(k, point, omitFlag, potential, field)
3878#endif
3879 for (k = 1 + kskip; k <= nbZCells + 1; ++k) {
3880 potential = 0.0;
3881 field.X = field.Y = field.Z = 0.0;
3882
3883 point.X = startX + (i - 1) * delX;
3884 point.Y = startY + (j - 1) * delY;
3885 point.Z = startZ + (k - 1) * delZ;
3886
3887 // Check whether point falls within a volume that should be
3888 // ignored
3889 omitFlag = 0;
3890 for (int omit = 1; omit <= WtFldFastVol[IdWtField].NbOmitVols;
3891 ++omit) {
3892 if ((point.X > WtFldOmitVolCrnrX[IdWtField][omit] +
3893 WtFldFastVol[IdWtField].LX) &&
3894 (point.X < WtFldOmitVolCrnrX[IdWtField][omit] +
3895 WtFldOmitVolLX[IdWtField][omit] +
3896 WtFldFastVol[IdWtField].LX) &&
3897 (point.Y > WtFldOmitVolCrnrY[IdWtField][omit] +
3898 WtFldFastVol[IdWtField].YStagger) &&
3899 (point.Y < WtFldOmitVolCrnrY[IdWtField][omit] +
3900 WtFldOmitVolLY[IdWtField][omit] +
3901 WtFldFastVol[IdWtField].YStagger) &&
3902 (point.Z > WtFldOmitVolCrnrZ[IdWtField][omit]) &&
3903 (point.Z < WtFldOmitVolCrnrZ[IdWtField][omit] +
3904 WtFldOmitVolLZ[IdWtField][omit])) {
3905 omitFlag = 1;
3906 break;
3907 }
3908 } // loop over omitted volumes
3909
3910 if (dbgFn) {
3911 printf("point X, Y, Z: %.8lg\t%.8lg\t%.8lg\n",
3912 point.X / LengthScale, point.Y / LengthScale,
3913 point.Z / LengthScale);
3914 printf("omitFlag: %d\n", omitFlag);
3915 fflush(stdout);
3916 }
3917
3918 if (omitFlag) {
3919 potential = field.X = field.Y = field.Z = 0.0;
3920 } else {
3921 fstatus = WtFldPFAtPoint(&point, &potential, &field, IdWtField);
3922 if (fstatus != 0) {
3924 "wrong WtFldPFAtPoint return value in staggered part of "
3925 "CreateWtFldFastVolElePF.\n");
3926 // return -1;
3927 }
3928 } // else omitFlag
3929 if (dbgFn) {
3930 printf("%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\n",
3931 point.X / LengthScale, point.Y / LengthScale,
3932 point.Z / LengthScale, potential / LengthScale, field.X,
3933 field.Y, field.Z);
3934 fflush(stdout);
3935 }
3936
3937 StgWtFldFastPot[IdWtField][block][i][j][k] = potential;
3938 StgWtFldFastFX[IdWtField][block][i][j][k] = field.X;
3939 StgWtFldFastFY[IdWtField][block][i][j][k] = field.Y;
3940 StgWtFldFastFZ[IdWtField][block][i][j][k] = field.Z;
3941 } // loop k
3942 } // pragma omp
3943
3944 for (int k = 1 + kskip; k <= nbZCells + 1; ++k) {
3945 // file output
3946 point.X = startX + (i - 1) * delX;
3947 point.Y = startY + (j - 1) * delY;
3948 point.Z = startZ + (k - 1) * delZ;
3949
3950 fprintf(fStgWtFldFastVolPF,
3951 "%4d\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\n",
3952 block, point.X / LengthScale, point.Y / LengthScale,
3953 point.Z / LengthScale,
3954 StgWtFldFastPot[IdWtField][block][i][j][k],
3955 StgWtFldFastFX[IdWtField][block][i][j][k],
3956 StgWtFldFastFY[IdWtField][block][i][j][k],
3957 StgWtFldFastFZ[IdWtField][block][i][j][k]);
3958 }
3959 fflush(fStgWtFldFastVolPF); // file output over
3960
3961 printf(
3962 "\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"
3963 "\b\b\b\b\b\b\b\b\b\b\b");
3964 } // loop j
3965 } // loop i
3966 } // loop block
3967
3968 fclose(fStgWtFldFastVolPF);
3969 } // if OptStaggerWtFldFastVol
3970
3971 return 0;
3972} // CreateWtFldFastVol ends
int WtFldPFAtPoint(Point3D *globalP, double *Potential, Vector3D *globalF, int IdWtField)
neBEMGLOBAL int WtFldNbPtSkip[MAXWtFld]
Definition neBEM.h:498
neBEMGLOBAL int OptStaggerWtFldFastVol[MAXWtFld]
Definition neBEM.h:493
neBEMGLOBAL double **** StgWtFldFastPot[MAXWtFld]
Definition neBEM.h:537
neBEMGLOBAL int * WtFldBlkNbZCells[MAXWtFld]
Definition neBEM.h:517
neBEMGLOBAL double * WtFldBlkLZ[MAXWtFld]
Definition neBEM.h:518
neBEMGLOBAL double * WtFldOmitVolCrnrY[MAXWtFld]
Definition neBEM.h:524
neBEMGLOBAL double **** WtFldFastFY[MAXWtFld]
Definition neBEM.h:535
neBEMGLOBAL double * WtFldOmitVolLX[MAXWtFld]
Definition neBEM.h:520
neBEMGLOBAL int * WtFldBlkNbYCells[MAXWtFld]
Definition neBEM.h:516
neBEMGLOBAL int StgWtFldNbPtSkip[MAXWtFld]
Definition neBEM.h:499
neBEMGLOBAL double * WtFldOmitVolCrnrX[MAXWtFld]
Definition neBEM.h:523
#define MAXWtFld
Definition neBEM.h:30
neBEMGLOBAL double * WtFldBlkCrnrZ[MAXWtFld]
Definition neBEM.h:519
neBEMGLOBAL double **** WtFldFastFZ[MAXWtFld]
Definition neBEM.h:536
neBEMGLOBAL double * WtFldOmitVolCrnrZ[MAXWtFld]
Definition neBEM.h:525
neBEMGLOBAL double * WtFldOmitVolLZ[MAXWtFld]
Definition neBEM.h:522
neBEMGLOBAL double **** StgWtFldFastFX[MAXWtFld]
Definition neBEM.h:538
neBEMGLOBAL int * WtFldBlkNbXCells[MAXWtFld]
Definition neBEM.h:515
neBEMGLOBAL double **** WtFldFastFX[MAXWtFld]
Definition neBEM.h:535
neBEMGLOBAL double **** WtFldFastPot[MAXWtFld]
Definition neBEM.h:534
neBEMGLOBAL WtFldFastAlgoVol WtFldFastVol[MAXWtFld]
Definition neBEM.h:513
neBEMGLOBAL double * WtFldOmitVolLY[MAXWtFld]
Definition neBEM.h:521
neBEMGLOBAL double **** StgWtFldFastFY[MAXWtFld]
Definition neBEM.h:538
neBEMGLOBAL double **** StgWtFldFastFZ[MAXWtFld]
Definition neBEM.h:539

Referenced by neBEMPrepareWeightingField().

◆ ElePFAtPoint()

int ElePFAtPoint ( Point3D * globalP,
double * Potential,
Vector3D * globalF )

Definition at line 402 of file ComputeProperties.c.

402 {
403 int dbgFn = 0;
404
405 const double xfld = globalP->X;
406 const double yfld = globalP->Y;
407 const double zfld = globalP->Z;
408
409 // Compute Potential and field at different locations
410 *Potential = globalF->X = globalF->Y = globalF->Z = 0.0;
411
412 // Effects due to base primitives and their repetitions are considered in the
413 // local coordinate system of the primitive (or element), while effects due to
414 // mirror elements and their repetitions are considered in the global
415 // coordinate system (GCS). This works because the direction cosines of a
416 // primitive (and its elements) and those of its repetitions are the same.
417 // As a result, we can do just one transformation from local to global at the
418 // end of calculations related to a primitive. This can save substantial
419 // computation if a discretized version of the primitive is being used since
420 // we avoid one unnecessary transformation for each element that comprises a
421 // primitive.
422 // Begin with primitive description of the device
423
424 // Scope in OpenMP: Variables in the global data space are accessible to all
425 // threads, while variables in a thread's private space is accessible to the
426 // thread only (there are several variations - copying outside region etc)
427 // Field point remains the same - kept outside private
428 // source point changes with change in primitive - private
429 // TransformationMatrix changes - kept within private (Note: matrices with
430 // fixed dimensions can be maintained, but those with dynamic allocation
431 // can not).
432 double *pPot = dvector(1, NbPrimitives);
433 // Field components in LCS for a primitive and its other incarnations.
434 double *plFx = dvector(1, NbPrimitives);
435 double *plFy = dvector(1, NbPrimitives);
436 double *plFz = dvector(1, NbPrimitives);
437
438 for (int prim = 1; prim <= NbPrimitives; ++prim) {
439 pPot[prim] = plFx[prim] = plFy[prim] = plFz[prim] = 0.0;
440 }
441
442#ifdef _OPENMP
443 int tid = 0, nthreads = 1;
444#pragma omp parallel private(tid, nthreads)
445#endif
446 {
447#ifdef _OPENMP
448 if (dbgFn) {
449 tid = omp_get_thread_num();
450 if (tid == 0) {
451 nthreads = omp_get_num_threads();
452 printf("PFAtPoint computation with %d threads\n", nthreads);
453 }
454 }
455#endif
456// by default, nested parallelization is off in C
457#ifdef _OPENMP
458#pragma omp for
459#endif
460 for (int primsrc = 1; primsrc <= NbPrimitives; ++primsrc) {
461 if (dbgFn) {
462 printf("Evaluating effect of primsrc %d using on %lg, %lg, %lg\n",
463 primsrc, xfld, yfld, zfld);
464 fflush(stdout);
465 }
466
467 const double xpsrc = PrimOriginX[primsrc];
468 const double ypsrc = PrimOriginY[primsrc];
469 const double zpsrc = PrimOriginZ[primsrc];
470
471 // Field in the local frame.
472 double lFx = 0.;
473 double lFy = 0.;
474 double lFz = 0.;
475
476 // Set up transform matrix for this primitive, which is also the same
477 // for all the elements belonging to this primitive.
478 double TransformationMatrix[3][3];
479 TransformationMatrix[0][0] = PrimDC[primsrc].XUnit.X;
480 TransformationMatrix[0][1] = PrimDC[primsrc].XUnit.Y;
481 TransformationMatrix[0][2] = PrimDC[primsrc].XUnit.Z;
482 TransformationMatrix[1][0] = PrimDC[primsrc].YUnit.X;
483 TransformationMatrix[1][1] = PrimDC[primsrc].YUnit.Y;
484 TransformationMatrix[1][2] = PrimDC[primsrc].YUnit.Z;
485 TransformationMatrix[2][0] = PrimDC[primsrc].ZUnit.X;
486 TransformationMatrix[2][1] = PrimDC[primsrc].ZUnit.Y;
487 TransformationMatrix[2][2] = PrimDC[primsrc].ZUnit.Z;
488
489 // The total influence is due to primitives on the basic device and due to
490 // virtual primitives arising out of repetition, reflection etc and not
491 // residing on the basic device
492
493 // Influence due to basic primitive
494
495 // Evaluate possibility whether primitive influence is accurate enough.
496 // This could be based on localPP and the subtended solid angle.
497 // If 1, then only primitive influence will be considered.
498 int PrimOK = 0;
499 // consider primitive representation accurate enough if it is
500 // repeated and beyond PrimAfter repetitions.
501 if (PrimAfter < 0) { // If PrimAfter < 0, PrimOK is zero
502 PrimOK = 0;
503 } else if (PrimAfter == 0) { // only this is necessary
504 PrimOK = 1;
505 } else if (PrimAfter > 0) {
506 PrimOK = 1;
507 }
508 if (PrimOK) {
509 // Only primitive influence will be considered
510 // Potential and flux (local system) due to base primitive
511 double tmpPot;
512 Vector3D tmpF;
513 // Rotate point from global to local system
514 double InitialVector[3] = {xfld - xpsrc, yfld - ypsrc, zfld - zpsrc};
515 double FinalVector[3] = {0., 0., 0.};
516 for (int i = 0; i < 3; ++i) {
517 for (int j = 0; j < 3; ++j) {
518 FinalVector[i] += TransformationMatrix[i][j] * InitialVector[j];
519 }
520 }
521 Point3D localPP;
522 localPP.X = FinalVector[0];
523 localPP.Y = FinalVector[1];
524 localPP.Z = FinalVector[2];
525 GetPrimPF(primsrc, &localPP, &tmpPot, &tmpF);
526 const double qpr = AvChDen[primsrc] + AvAsgndChDen[primsrc];
527 pPot[primsrc] += qpr * tmpPot;
528 lFx += qpr * tmpF.X;
529 lFy += qpr * tmpF.Y;
530 lFz += qpr * tmpF.Z;
531 // if(DebugLevel == 301)
532 if (dbgFn) {
533 printf("PFAtPoint base primitive =>\n");
534 printf("primsrc: %d, xlocal: %lg, ylocal: %lg, zlocal %lg\n", primsrc,
535 localPP.X, localPP.Y, localPP.Z);
536 printf("primsrc: %d, Pot: %lg, Fx: %lg, Fx: %lg, Fz: %lg\n", primsrc,
537 tmpPot, tmpF.X, tmpF.Y, tmpF.Z);
538 printf("primsrc: %d, pPot: %lg, lFx: %lg, lFy: %lg, lFz: %lg\n",
539 primsrc, pPot[primsrc], lFx, lFy, lFz);
540 fflush(stdout);
541 // exit(-1);
542 }
543 } else {
544 // Need to consider element influence.
545 double tPot;
546 Vector3D tF;
547 double ePot = 0.;
548 Vector3D eF;
549 eF.X = 0.0;
550 eF.Y = 0.0;
551 eF.Z = 0.0;
552 const int eleMin = ElementBgn[primsrc];
553 const int eleMax = ElementEnd[primsrc];
554 for (int ele = eleMin; ele <= eleMax; ++ele) {
555 const double xsrc = (EleArr + ele - 1)->G.Origin.X;
556 const double ysrc = (EleArr + ele - 1)->G.Origin.Y;
557 const double zsrc = (EleArr + ele - 1)->G.Origin.Z;
558 // Rotate from global to local system; matrix as for primitive
559 double vG[3] = {xfld - xsrc, yfld - ysrc, zfld - zsrc};
560 double vL[3] = {0., 0., 0.};
561 for (int i = 0; i < 3; ++i) {
562 for (int j = 0; j < 3; ++j) {
563 vL[i] += TransformationMatrix[i][j] * vG[j];
564 }
565 }
566 // Potential and flux (local system) due to base primitive
567 const int type = (EleArr + ele - 1)->G.Type;
568 const double a = (EleArr + ele - 1)->G.LX;
569 const double b = (EleArr + ele - 1)->G.LZ;
570 GetPF(type, a, b, vL[0], vL[1], vL[2], &tPot, &tF);
571 const double qel =
572 (EleArr + ele - 1)->Solution + (EleArr + ele - 1)->Assigned;
573 ePot += qel * tPot;
574 eF.X += qel * tF.X;
575 eF.Y += qel * tF.Y;
576 eF.Z += qel * tF.Z;
577 // if(DebugLevel == 301)
578 if (dbgFn) {
579 printf("PFAtPoint base primitive:%d\n", primsrc);
580 printf("ele: %d, xlocal: %lg, ylocal: %lg, zlocal %lg\n", ele,
581 vL[0], vL[1], vL[2]);
582 printf(
583 "ele: %d, tPot: %lg, tFx: %lg, tFy: %lg, tFz: %lg, Solution: "
584 "%g\n",
585 ele, tPot, tF.X, tF.Y, tF.Z, qel);
586 printf("ele: %d, ePot: %lg, eFx: %lg, eFy: %lg, eFz: %lg\n", ele,
587 ePot, eF.X, eF.Y, eF.Z);
588 fflush(stdout);
589 }
590 } // for all the elements on this primsrc primitive
591
592 pPot[primsrc] += ePot;
593 lFx += eF.X;
594 lFy += eF.Y;
595 lFz += eF.Z;
596 if (dbgFn) {
597 printf("prim%d, ePot: %lg, eFx: %lg, eFy: %lg, eFz: %lg\n", primsrc,
598 ePot, eF.X, eF.Y, eF.Z);
599 printf("prim%d, pPot: %lg, lFx: %lg, lFy: %lg, lFz: %lg\n", primsrc,
600 pPot[primsrc], lFx, lFy, lFz);
601 fflush(stdout);
602 }
603 } // else elements influence
604
605 // if(DebugLevel == 301)
606 if (dbgFn) {
607 printf("basic primitive\n");
608 printf("primsrc: %d, pPot: %lg, lFx: %lg, lFy: %lg, lFz: %lg\n",
609 primsrc, pPot[primsrc], lFx, lFy, lFz);
610 fflush(stdout);
611 }
612
613 if (MirrorTypeX[primsrc] || MirrorTypeY[primsrc] ||
614 MirrorTypeZ[primsrc]) { // Mirror effect of base primitives
615 printf("Mirror may not be correctly implemented ...\n");
616 exit(0);
617 } // Mirror effect ends
618
619 // Flux due to repeated primitives
620 if ((PeriodicTypeX[primsrc] == 1) || (PeriodicTypeY[primsrc] == 1) ||
621 (PeriodicTypeZ[primsrc] == 1)) {
622 const int perx = PeriodicInX[primsrc];
623 const int pery = PeriodicInY[primsrc];
624 const int perz = PeriodicInZ[primsrc];
625 if (perx || pery || perz) {
626 for (int xrpt = -perx; xrpt <= perx; ++xrpt) {
627 const double xShift = XPeriod[primsrc] * (double)xrpt;
628 const double XPOfRpt = xpsrc + xShift;
629 for (int yrpt = -pery; yrpt <= pery; ++yrpt) {
630 const double yShift = YPeriod[primsrc] * (double)yrpt;
631 const double YPOfRpt = ypsrc + yShift;
632 for (int zrpt = -perz; zrpt <= perz; ++zrpt) {
633 const double zShift = ZPeriod[primsrc] * (double)zrpt;
634 const double ZPOfRpt = zpsrc + zShift;
635 // Skip the basic primitive.
636 if ((xrpt == 0) && (yrpt == 0) && (zrpt == 0)) continue;
637
638 // Basic primitive repeated
639 int repPrimOK = 0;
640 // consider primitive representation accurate enough if it is
641 // repeated and beyond PrimAfter repetitions.
642 if (PrimAfter < 0) { // If PrimAfter <0, repPrimOK is zero
643 repPrimOK = 0;
644 } else if ((abs(xrpt) >= PrimAfter)
645 && (abs(yrpt) >= PrimAfter)) {
646 repPrimOK = 1;
647 }
648 if (repPrimOK) {
649 // Use primitive representation
650 // Rotate point from global to local system
651 double InitialVector[3] = {xfld - XPOfRpt, yfld - YPOfRpt,
652 zfld - ZPOfRpt};
653 double FinalVector[3] = {0., 0., 0.};
654 for (int i = 0; i < 3; ++i) {
655 for (int j = 0; j < 3; ++j) {
656 FinalVector[i] +=
657 TransformationMatrix[i][j] * InitialVector[j];
658 }
659 }
660 Point3D localPPR;
661 localPPR.X = FinalVector[0];
662 localPPR.Y = FinalVector[1];
663 localPPR.Z = FinalVector[2];
664 // Potential and flux (local system) due to repeated
665 // primitive
666 double tmpPot;
667 Vector3D tmpF;
668 GetPrimPF(primsrc, &localPPR, &tmpPot, &tmpF);
669 const double qpr = AvChDen[primsrc] + AvAsgndChDen[primsrc];
670 pPot[primsrc] += qpr * tmpPot;
671 lFx += qpr * tmpF.X;
672 lFy += qpr * tmpF.Y;
673 lFz += qpr * tmpF.Z;
674 // if(DebugLevel == 301)
675 if (dbgFn) {
676 printf(
677 "primsrc: %d, xlocal: %lg, ylocal: %lg, zlocal: "
678 "%lg\n",
679 primsrc, localPPR.X, localPPR.Y, localPPR.Z);
680 printf("primsrc: %d, Pot: %lg, Fx: %lg, Fy: %lg, Fz: %lg\n",
681 primsrc, tmpPot * qpr, tmpF.X * qpr, tmpF.Y * qpr,
682 tmpF.Z * qpr);
683 printf(
684 "primsrc: %d, pPot: %lg, lFx: %lg, lFy: %lg, lFz: "
685 "%lg\n",
686 primsrc, pPot[primsrc], lFx, lFy, lFz);
687 fflush(stdout);
688 }
689 } else {
690 // Use discretized representation of a repeated primitive
691 double tPot;
692 Vector3D tF;
693 double erPot = 0.0;
694 Vector3D erF;
695 erF.X = 0.0;
696 erF.Y = 0.0;
697 erF.Z = 0.0;
698 const int eleMin = ElementBgn[primsrc];
699 const int eleMax = ElementEnd[primsrc];
700 for (int ele = eleMin; ele <= eleMax; ++ele) {
701 const double xrsrc = (EleArr + ele - 1)->G.Origin.X;
702 const double yrsrc = (EleArr + ele - 1)->G.Origin.Y;
703 const double zrsrc = (EleArr + ele - 1)->G.Origin.Z;
704
705 const double XEOfRpt = xrsrc + xShift;
706 const double YEOfRpt = yrsrc + yShift;
707 const double ZEOfRpt = zrsrc + zShift;
708 // Rotate from global to local system
709 double vG[3] = {xfld - XEOfRpt, yfld - YEOfRpt,
710 zfld - ZEOfRpt};
711 double vL[3] = {0., 0., 0.};
712 for (int i = 0; i < 3; ++i) {
713 for (int j = 0; j < 3; ++j) {
714 vL[i] += TransformationMatrix[i][j] * vG[j];
715 }
716 }
717 // Allowed, because all the local coordinates have the
718 // same orientations. Only the origins are mutually
719 // displaced along a line.
720 const int type = (EleArr + ele - 1)->G.Type;
721 const double a = (EleArr + ele - 1)->G.LX;
722 const double b = (EleArr + ele - 1)->G.LZ;
723 GetPF(type, a, b, vL[0], vL[1], vL[2], &tPot, &tF);
724 const double qel = (EleArr + ele - 1)->Solution +
725 (EleArr + ele - 1)->Assigned;
726 erPot += qel * tPot;
727 erF.X += qel * tF.X;
728 erF.Y += qel * tF.Y;
729 erF.Z += qel * tF.Z;
730 // if(DebugLevel == 301)
731 if (dbgFn) {
732 printf("PFAtPoint base primitive:%d\n", primsrc);
733 printf("ele: %d, xlocal: %lg, ylocal: %lg, zlocal %lg\n",
734 ele, vL[0], vL[1], vL[2]);
735 printf(
736 "ele: %d, tPot: %lg, tFx: %lg, tFy: %lg, tFz: %lg, "
737 "Solution: %g\n",
738 ele, tPot, tF.X, tF.Y, tF.Z, qel);
739 printf(
740 "ele: %d, ePot: %lg, eFx: %lg, eFy: %lg, eFz: %lg\n",
741 ele, erPot, erF.X, erF.Y, erF.Z);
742 fflush(stdout);
743 }
744 } // for all the elements on this primsrc repeated
745 // primitive
746
747 pPot[primsrc] += erPot;
748 lFx += erF.X;
749 lFy += erF.Y;
750 lFz += erF.Z;
751 } // else discretized representation of this primitive
752
753 // if(DebugLevel == 301)
754 if (dbgFn) {
755 printf("basic repeated xrpt: %d. yrpt: %d, zrpt: %d\n", xrpt,
756 yrpt, zrpt);
757 printf(
758 "primsrc: %d, pPot: %lg, lFx: %lg, lFy: %lg, lFz: %lg\n",
759 primsrc, pPot[primsrc], lFx, lFy, lFz);
760 fflush(stdout);
761 }
762
763 if (MirrorTypeX[primsrc] || MirrorTypeY[primsrc] ||
764 MirrorTypeZ[primsrc]) { // Mirror effect of repeated
765 // primitives - not parallelized
766 printf(
767 "Mirror not correctly implemented in this version of "
768 "neBEM ...\n");
769 exit(0);
770
771 double tmpPot;
772 Vector3D tmpF;
773 Point3D srcptp;
774 Point3D localPPRM; // point primitive repeated mirrored
775 DirnCosn3D DirCos;
776
777 srcptp.X = XPOfRpt;
778 srcptp.Y = YPOfRpt;
779 srcptp.Z = ZPOfRpt;
780
781 Point3D fldpt;
782 fldpt.X = xfld;
783 fldpt.Y = yfld;
784 fldpt.Z = zfld;
785 if (MirrorTypeX[primsrc]) {
786 MirrorTypeY[primsrc] = 0;
787 MirrorTypeZ[primsrc] = 0;
788 }
789 if (MirrorTypeY[primsrc]) MirrorTypeZ[primsrc] = 0;
790
791 if (MirrorTypeX[primsrc]) {
792 localPPRM = ReflectPrimitiveOnMirror(
793 'X', primsrc, srcptp, fldpt,
794 MirrorDistXFromOrigin[primsrc], &DirCos);
795
796 // check whether primitive description is good enough
797 int mirrPrimOK = 0;
798 if (mirrPrimOK) {
799 GetPrimPFGCS(primsrc, &localPPRM, &tmpPot, &tmpF,
800 &DirCos);
801 const double qpr =
802 AvChDen[primsrc] + AvAsgndChDen[primsrc];
803 if (MirrorTypeX[primsrc] == 1) {
804 // opposite charge density
805 pPot[primsrc] -= qpr * tmpPot;
806 lFx -= qpr * tmpF.X;
807 lFy -= qpr * tmpF.Y;
808 lFz -= qpr * tmpF.Z;
809 } else if (MirrorTypeX[primsrc] == 2) {
810 // same charge density
811 pPot[primsrc] += qpr * tmpPot;
812 lFx += qpr * tmpF.X;
813 lFy += qpr * tmpF.Y;
814 lFz += qpr * tmpF.Z;
815 }
816 } else { // consider element representation
817 Point3D localPERM; // point element repeated mirrored
818 Point3D srcpte;
819
820 const int eleMin = ElementBgn[primsrc];
821 const int eleMax = ElementEnd[primsrc];
822 for (int ele = eleMin; ele <= eleMax; ++ele) {
823 const double xsrc = (EleArr + ele - 1)->G.Origin.X;
824 const double ysrc = (EleArr + ele - 1)->G.Origin.Y;
825 const double zsrc = (EleArr + ele - 1)->G.Origin.Z;
826
827 const double XEOfRpt = xsrc + xShift;
828 const double YEOfRpt = ysrc + yShift;
829 const double ZEOfRpt = zsrc + zShift;
830
831 srcpte.X = XEOfRpt;
832 srcpte.Y = YEOfRpt;
833 srcpte.Z = ZEOfRpt;
834
835 localPERM = ReflectOnMirror(
836 'X', ele, srcpte, fldpt,
837 MirrorDistXFromOrigin[primsrc], &DirCos);
838 const int type = (EleArr + ele - 1)->G.Type;
839 const double a = (EleArr + ele - 1)->G.LX;
840 const double b = (EleArr + ele - 1)->G.LZ;
841 GetPFGCS(type, a, b, &localPERM, &tmpPot, &tmpF,
842 &DirCos); // force?
843 const double qel = (EleArr + ele - 1)->Solution +
844 (EleArr + ele - 1)->Assigned;
845 if (MirrorTypeX[primsrc] == 1) {
846 // opposite charge density
847 pPot[primsrc] -= qel * tmpPot;
848 lFx -= qel * tmpF.X;
849 lFy -= qel * tmpF.Y;
850 lFz -= qel * tmpF.Z;
851 } else if (MirrorTypeX[primsrc] == 2) {
852 // same charge density
853 pPot[primsrc] += qel * tmpPot;
854 lFx += qel * tmpF.X;
855 lFy += qel * tmpF.Y;
856 lFz += qel * tmpF.Z;
857 }
858 } // loop for all elements on the primsrc primitive
859 } // else element representation
860 } // MirrorTypeX
861
862 if (MirrorTypeY[primsrc]) {
863 localPPRM = ReflectOnMirror('Y', primsrc, srcptp, fldpt,
864 MirrorDistYFromOrigin[primsrc],
865 &DirCos);
866
867 // check whether primitive description is good enough
868 int mirrPrimOK = 0;
869 if (mirrPrimOK) {
870 GetPrimPFGCS(primsrc, &localPPRM, &tmpPot, &tmpF,
871 &DirCos);
872 const double qpr =
873 AvChDen[primsrc] + AvAsgndChDen[primsrc];
874 if (MirrorTypeY[primsrc] == 1) {
875 // opposite charge density
876 pPot[primsrc] -= qpr * tmpPot;
877 lFx -= qpr * tmpF.X;
878 lFy -= qpr * tmpF.Y;
879 lFz -= qpr * tmpF.Z;
880 } else if (MirrorTypeY[primsrc] == 2) {
881 // same charge density
882 pPot[primsrc] += qpr * tmpPot;
883 lFx += qpr * tmpF.X;
884 lFy += qpr * tmpF.Y;
885 lFz += qpr * tmpF.Z;
886 }
887 } else { // consider element representation
888 Point3D localPERM;
889 Point3D srcpte;
890
891 const int eleMin = ElementBgn[primsrc];
892 const int eleMax = ElementEnd[primsrc];
893 for (int ele = eleMin; ele <= eleMax; ++ele) {
894 const double xsrc = (EleArr + ele - 1)->G.Origin.X;
895 const double ysrc = (EleArr + ele - 1)->G.Origin.Y;
896 const double zsrc = (EleArr + ele - 1)->G.Origin.Z;
897
898 const double XEOfRpt = xsrc + xShift;
899 const double YEOfRpt = ysrc + yShift;
900 const double ZEOfRpt = zsrc + zShift;
901
902 srcpte.X = XEOfRpt;
903 srcpte.Y = YEOfRpt;
904 srcpte.Z = ZEOfRpt;
905
906 localPERM = ReflectOnMirror(
907 'Y', ele, srcpte, fldpt,
908 MirrorDistYFromOrigin[primsrc], &DirCos);
909 const int type = (EleArr + ele - 1)->G.Type;
910 const double a = (EleArr + ele - 1)->G.LX;
911 const double b = (EleArr + ele - 1)->G.LZ;
912 GetPFGCS(type, a, b, &localPERM, &tmpPot, &tmpF,
913 &DirCos);
914 const double qel = (EleArr + ele - 1)->Solution +
915 (EleArr + ele - 1)->Assigned;
916 if (MirrorTypeY[primsrc] == 1) {
917 // opposite charge density
918 pPot[primsrc] -= qel * tmpPot;
919 lFx -= qel * tmpF.X;
920 lFy -= qel * tmpF.Y;
921 lFz -= qel * tmpF.Z;
922 } else if (MirrorTypeY[primsrc] == 2) {
923 // same charge density
924 pPot[primsrc] += qel * tmpPot;
925 lFx += qel * tmpF.X;
926 lFy += qel * tmpF.Y;
927 lFz += qel * tmpF.Z;
928 }
929 } // loop for all elements on the primsrc primitive
930 } // else element representations
931 } // MirrorTypeY
932
933 if (MirrorTypeZ[primsrc]) {
934 localPPRM = ReflectOnMirror('Z', primsrc, srcptp, fldpt,
935 MirrorDistZFromOrigin[primsrc],
936 &DirCos);
937
938 // check whether primitive description is good enough
939 int mirrPrimOK = 0;
940 if (mirrPrimOK) {
941 GetPrimPFGCS(primsrc, &localPPRM, &tmpPot, &tmpF,
942 &DirCos);
943 const double qpr =
944 AvChDen[primsrc] + AvAsgndChDen[primsrc];
945 if (MirrorTypeZ[primsrc] == 1) {
946 // opposite charge density
947 pPot[primsrc] -= qpr * tmpPot;
948 lFx -= qpr * tmpF.X;
949 lFy -= qpr * tmpF.Y;
950 lFz -= qpr * tmpF.Z;
951 } else if (MirrorTypeZ[primsrc] == 2) {
952 // same charge density
953 pPot[primsrc] += qpr * tmpPot;
954 lFx += qpr * tmpF.X;
955 lFy += qpr * tmpF.Y;
956 lFz += qpr * tmpF.Z;
957 }
958 } else {
959 // elements to be considered
960 Point3D localPERM;
961 Point3D srcpte;
962
963 const int eleMin = ElementBgn[primsrc];
964 const int eleMax = ElementEnd[primsrc];
965 for (int ele = eleMin; ele <= eleMax; ++ele) {
966 const double xsrc = (EleArr + ele - 1)->G.Origin.X;
967 const double ysrc = (EleArr + ele - 1)->G.Origin.Y;
968 const double zsrc = (EleArr + ele - 1)->G.Origin.Z;
969
970 const double XEOfRpt = xsrc + xShift;
971 const double YEOfRpt = ysrc + yShift;
972 const double ZEOfRpt = zsrc + zShift;
973
974 srcpte.X = XEOfRpt;
975 srcpte.Y = YEOfRpt;
976 srcpte.Z = ZEOfRpt;
977
978 localPERM = ReflectOnMirror(
979 'Z', ele, srcpte, fldpt,
980 MirrorDistZFromOrigin[primsrc], &DirCos);
981 const int type = (EleArr + ele - 1)->G.Type;
982 const double a = (EleArr + ele - 1)->G.LX;
983 const double b = (EleArr + ele - 1)->G.LZ;
984 GetPFGCS(type, a, b, &localPERM, &tmpPot, &tmpF,
985 &DirCos);
986 const double qel = (EleArr + ele - 1)->Solution +
987 (EleArr + ele - 1)->Assigned;
988 if (MirrorTypeZ[primsrc] == 1) {
989 // opposite charge density
990 pPot[primsrc] -= qel * tmpPot;
991 lFx -= qel * tmpF.X;
992 lFy -= qel * tmpF.Y;
993 lFz -= qel * tmpF.Z;
994 } else if (MirrorTypeZ[primsrc] == 2) {
995 // same charge density
996 pPot[primsrc] += qel * tmpPot;
997 lFx += qel * tmpF.X;
998 lFy += qel * tmpF.Y;
999 lFz += qel * tmpF.Z;
1000 }
1001 } // loop for all elements on the primsrc primitive
1002 } // else consider element representation
1003 } // MirrorTypeZ
1004 } // Mirror effect for repeated primitives ends
1005
1006 } // for zrpt
1007 } // for yrpt
1008 } // for xrpt
1009 } // PeriodicInX || PeriodicInY || PeriodicInZ
1010 } // PeriodicType == 1
1011 Vector3D localF;
1012 localF.X = lFx;
1013 localF.Y = lFy;
1014 localF.Z = lFz;
1015 Vector3D tmpF = RotateVector3D(&localF, &PrimDC[primsrc], local2global);
1016 plFx[primsrc] = tmpF.X;
1017 plFy[primsrc] = tmpF.Y;
1018 plFz[primsrc] = tmpF.Z;
1019 } // for all primitives: basic device, mirror reflections and repetitions
1020 } // pragma omp parallel
1021
1022 double totPot = 0.0;
1023 Vector3D totF;
1024 totF.X = totF.Y = totF.Z = 0.0;
1025 for (int prim = 1; prim <= NbPrimitives; ++prim) {
1026 totPot += pPot[prim];
1027 totF.X += plFx[prim];
1028 totF.Y += plFy[prim];
1029 totF.Z += plFz[prim];
1030 }
1031
1032 // This is done at the end of the function - before freeing memory
1033#ifdef __cplusplus
1034 *Potential = totPot * InvFourPiEps0;
1035 globalF->X = totF.X * InvFourPiEps0;
1036 globalF->Y = totF.Y * InvFourPiEps0;
1037 globalF->Z = totF.Z * InvFourPiEps0;
1038#else
1039 *Potential = totPot / MyFACTOR;
1040 globalF->X = totF.X / MyFACTOR;
1041 globalF->Y = totF.Y / MyFACTOR;
1042 globalF->Z = totF.Z / MyFACTOR;
1043#endif
1044 (*Potential) += VSystemChargeZero; // respect total system charge constraint
1045
1046 if (dbgFn) {
1047 printf("Final values due to all primitives: ");
1048 // printf("xfld\tyfld\tzfld\tPot\tFx\tFy\tFz\n"); // refer, do not
1049 // uncomment
1050 printf("%lg\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n\n", xfld, yfld, zfld,
1051 (*Potential), globalF->X, globalF->Y, globalF->Z);
1052 fflush(stdout);
1053 }
1054
1055 free_dvector(pPot, 1, NbPrimitives);
1056 free_dvector(plFx, 1, NbPrimitives);
1057 free_dvector(plFy, 1, NbPrimitives);
1058 free_dvector(plFz, 1, NbPrimitives);
1059
1060 return (0);
1061} // 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)
Vector3D RotateVector3D(Vector3D *A, DirnCosn3D *DC, int Sense)
Definition Vector.c:395
#define local2global
Definition Vector.h:14
Point3D ReflectPrimitiveOnMirror(char Axis, int primsrc, Point3D srcpt, Point3D fldpt, double distance, DirnCosn3D *MirroredDC)
Definition neBEM.c:4088
Point3D ReflectOnMirror(char Axis, int elesrc, Point3D srcpt, Point3D fldpt, double distance, DirnCosn3D *MirroredDC)
Definition neBEM.c:4177
neBEMGLOBAL Element * EleArr
Definition neBEM.h:176
neBEMGLOBAL int * PeriodicInY
Definition neBEM.h:86
neBEMGLOBAL int * MirrorTypeZ
Definition neBEM.h:88
neBEMGLOBAL double * MirrorDistYFromOrigin
Definition neBEM.h:89
neBEMGLOBAL double * ZPeriod
Definition neBEM.h:87
neBEMGLOBAL double VSystemChargeZero
Definition neBEM.h:129
neBEMGLOBAL double * PrimOriginZ
Definition neBEM.h:80
neBEMGLOBAL int NbPrimitives
Definition neBEM.h:64
neBEMGLOBAL int * PeriodicTypeX
Definition neBEM.h:85
neBEMGLOBAL int * PeriodicTypeY
Definition neBEM.h:85
neBEMGLOBAL double * PrimOriginY
Definition neBEM.h:80
neBEMGLOBAL double * MirrorDistZFromOrigin
Definition neBEM.h:90
neBEMGLOBAL DirnCosn3D * PrimDC
Definition neBEM.h:81
neBEMGLOBAL int PrimAfter
Definition neBEM.h:364
neBEMGLOBAL double * XPeriod
Definition neBEM.h:87
neBEMGLOBAL double * AvAsgndChDen
Definition neBEM.h:97
neBEMGLOBAL int * MirrorTypeY
Definition neBEM.h:88
neBEMGLOBAL int * ElementEnd
Definition neBEM.h:101
neBEMGLOBAL double * AvChDen
Definition neBEM.h:97
neBEMGLOBAL int * MirrorTypeX
Definition neBEM.h:88
neBEMGLOBAL double * Solution
Definition neBEM.h:197
neBEMGLOBAL int * ElementBgn
Definition neBEM.h:101
neBEMGLOBAL double * PrimOriginX
Definition neBEM.h:80
neBEMGLOBAL int * PeriodicInZ
Definition neBEM.h:86
neBEMGLOBAL int * PeriodicInX
Definition neBEM.h:86
neBEMGLOBAL int * PeriodicTypeZ
Definition neBEM.h:85
#define MyFACTOR
Definition neBEM.h:21
neBEMGLOBAL double * YPeriod
Definition neBEM.h:87
neBEMGLOBAL double * MirrorDistXFromOrigin
Definition neBEM.h:89
void free_dvector(double *v, long nl, long)
Definition nrutil.c:471
double * dvector(long nl, long nh)
Definition nrutil.c:64

Referenced by PFAtPoint(), and WtFldFastPFAtPoint().

◆ FastElePFAtPoint()

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

Definition at line 2600 of file ComputeProperties.c.

2601 {
2602 return 0;
2603} // FastElePFAtPoint ends

◆ FastKnChPFAtPoint()

int FastKnChPFAtPoint ( Point3D * globalP,
double * Potential,
Vector3D * globalF )

Definition at line 2608 of file ComputeProperties.c.

2608 {
2609 int dbgFn = 0;
2610 double Xpt = globalP->X;
2611 double Ypt = globalP->Y;
2612 double Zpt = globalP->Z;
2613 double RptVolLX = FastVol.LX;
2614 double RptVolLY = FastVol.LY;
2615 double RptVolLZ = FastVol.LZ;
2616 double CornerX = FastVol.CrnrX;
2617 double CornerY = FastVol.CrnrY;
2618 double CornerZ = FastVol.CrnrZ;
2619 double TriLin(double xd, double yd, double zd, double c000, double c100,
2620 double c010, double c001, double c110, double c101, double c011,
2621 double c111);
2622
2623 // First of all, check how the point in question should be treated ...
2624
2625 // Check whether the point falls within a volume that is not regarded as
2626 // FastVol
2627 for (int ignore = 1; ignore <= FastVol.NbIgnoreVols; ++ignore) {
2628 if ((Xpt >= (IgnoreVolCrnrX[ignore])) &&
2629 (Xpt <= (IgnoreVolCrnrX[ignore] + IgnoreVolLX[ignore])) &&
2630 (Ypt >= (IgnoreVolCrnrY[ignore])) &&
2631 (Ypt <= (IgnoreVolCrnrY[ignore] + IgnoreVolLY[ignore])) &&
2632 (Zpt >= (IgnoreVolCrnrZ[ignore])) &&
2633 (Zpt <= (IgnoreVolCrnrZ[ignore] + IgnoreVolLZ[ignore]))) {
2634 if (dbgFn)
2635 neBEMMessage("In FastKnChPFAtPoint: point in an ignored volume!\n");
2636
2637 int fstatus = KnChPFAtPoint(globalP, Potential, globalF);
2638 if (fstatus != 0) {
2639 neBEMMessage("wrong KnChPFAtPoint return value in FastVolKnChPF.\n");
2640 return -1;
2641 } else
2642 return 0;
2643 }
2644 } // loop over ignored volumes
2645
2646 // If not ignored, the point qualifies for FastVol evaluation ...
2647
2648 // for a staggered fast volume, the volume repeated in X is larger
2649 if (OptStaggerFastVol) {
2650 RptVolLX += FastVol.LX;
2651 }
2652 if (dbgFn) {
2653 printf("\nin FastKnChPFAtPoint\n");
2654 printf("x, y, z: %g, %g, %g\n", Xpt, Ypt, Zpt);
2655 printf("RptVolLX, RptVolLY, RptVolLZ: %g, %g, %g\n", RptVolLX, RptVolLY,
2656 RptVolLZ);
2657 printf("CornerX, CornerY, CornerZ: %g, %g, %g\n", CornerX, CornerY,
2658 CornerZ);
2659 printf("Nb of blocks: %d\n", FastVol.NbBlocks);
2660 for (int block = 1; block <= FastVol.NbBlocks; ++block) {
2661 printf("NbOfXCells: %d\n", BlkNbXCells[block]);
2662 printf("NbOfYCells: %d\n", BlkNbYCells[block]);
2663 printf("NbOfZCells: %d\n", BlkNbZCells[block]);
2664 printf("LZ: %le\n", BlkLZ[block]);
2665 printf("CornerZ: %le\n", BlkCrnrZ[block]);
2666 }
2667 }
2668
2669 // Find equivalent position inside the basic / staggered volume.
2670 // real distance from volume corner
2671 double dx = Xpt - CornerX;
2672 double dy = Ypt - CornerY;
2673 double dz = Zpt - CornerZ;
2674 if (dbgFn)
2675 printf("real dx, dy, dz from volume corner: %g, %g, %g\n", dx, dy, dz);
2676
2677 int NbFastVolX = (int)(dx / RptVolLX);
2678 if (dx < 0.0) --NbFastVolX;
2679 int NbFastVolY = (int)(dy / RptVolLY);
2680 if (dy < 0.0) --NbFastVolY;
2681 int NbFastVolZ = (int)(dz / RptVolLZ);
2682 if (dz < 0.0) --NbFastVolZ;
2683 if (dbgFn)
2684 printf("Volumes in x, y, z: %d, %d, %d\n", NbFastVolX, NbFastVolY,
2685 NbFastVolZ);
2686
2687 // equivalent distances from fast volume corner
2688 dx -= NbFastVolX * RptVolLX;
2689 dy -= NbFastVolY * RptVolLY;
2690 dz -= NbFastVolZ * RptVolLZ;
2691 // The following conditions should never happen - generate an error message
2692 if (dx < 0.0) {
2693 dx = 0.0;
2694 neBEMMessage("equiv dx < 0.0 - not correct!\n");
2695 }
2696 if (dy < 0.0) {
2697 dy = 0.0;
2698 neBEMMessage("equiv dy < 0.0 - not correct!\n");
2699 }
2700 if (dz < 0.0) {
2701 dz = 0.0;
2702 neBEMMessage("equiv dz < 0.0 - not correct!\n");
2703 }
2704 if (dx > RptVolLX) {
2705 dx = RptVolLX;
2706 neBEMMessage("equiv dx > RptVolLX - not correct!\n");
2707 }
2708 if (dy > RptVolLY) {
2709 dy = RptVolLY;
2710 neBEMMessage("equiv dy > RptVolLY - not correct!\n");
2711 }
2712 if (dz > RptVolLZ) {
2713 dz = RptVolLZ;
2714 neBEMMessage("equiv dz > RptVolLZ - not correct!\n");
2715 }
2716 if (dbgFn)
2717 printf("equivalent dist from corner - dx, dy, dz: %g, %g, %g\n", dx, dy,
2718 dz);
2719
2720 // Take care of possible trouble-makers
2721 if (dx < MINDIST) dx = MINDIST; // -ve dx has already been made equal to 0
2722 if (dy < MINDIST) dy = MINDIST;
2723 if (dz < MINDIST) dz = MINDIST;
2724 if ((RptVolLX - dx) < MINDIST)
2725 dx = RptVolLX - MINDIST; // dx > RptVolLX taken care of
2726 if ((RptVolLY - dy) < MINDIST) dy = RptVolLY - MINDIST;
2727 if ((RptVolLZ - dz) < MINDIST) dz = RptVolLZ - MINDIST;
2728 // For staggered volumes, there is another plane where difficulties may occur
2729 if ((dx <= FastVol.LX) && (FastVol.LX - dx) < MINDIST)
2730 dx = FastVol.LX - MINDIST;
2731 // else if((dx > FastVol.LX) && (fabs(FastVol.LX-dx) < MINDIST))
2732 else if ((dx > FastVol.LX) && (dx - FastVol.LX) < MINDIST) // more inttuitive
2733 dx = FastVol.LX + MINDIST;
2734 if (dbgFn)
2735 printf("equivalent dist adjusted - dx, dy, dz: %g, %g, %g\n", dx, dy, dz);
2736
2737 // If volume is staggered, we have a few more things to do before finalizing
2738 // the values of equivalent distance
2739 // sector identification
2740 // _................__________________
2741 // | . . | Sector 3 |
2742 // | . . | |
2743 // | . | . |
2744 // | | . . |
2745 // | Sector 2 | . . |
2746 // |----------------| . . |
2747 // | | . |
2748 // | . | |
2749 // | . . | |
2750 // | . . |----------------|
2751 // | . . | Sector 4 |
2752 // | . | . |
2753 // | | . . |
2754 // | Sector 1 | . . |
2755 // |----------------|................|
2756
2757 int sector = 1; // kept outside `if' since this is necessary further below
2758 if (OptStaggerFastVol) {
2759 if ((dx >= 0.0) && (dx <= FastVol.LX) && (dy >= 0.0) &&
2760 (dy <= FastVol.LY)) {
2761 // point lies in sector 1, everything remains unchanged
2762 sector = 1;
2763 } else if ((dx >= 0.0) && (dx <= FastVol.LX) && (dy > FastVol.LY) &&
2764 (dy <= FastVol.LY + FastVol.YStagger)) {
2765 // point lies in sector 2, move basic volume one step up
2766 sector = 2;
2767 ++NbFastVolY;
2768 CornerY += FastVol.LY; // repeat length in Y is LY
2769 dy -= FastVol.LY;
2770 } else if ((dx > FastVol.LX) && (dx <= 2.0 * FastVol.LX) &&
2771 (dy >= FastVol.YStagger) &&
2772 (dy <= FastVol.LY + FastVol.YStagger)) {
2773 // point lies in sector 3, pt in staggered vol, change corner coords
2774 sector = 3;
2775 CornerX += FastVol.LX;
2776 CornerY += FastVol.YStagger;
2777 dx -= FastVol.LX;
2778 dy -= FastVol.YStagger;
2779 } else if ((dx > FastVol.LX) && (dx <= 2.0 * FastVol.LX) && (dy >= 0.0) &&
2780 (dy < FastVol.YStagger)) {
2781 // point lies in sector 4, move basic volume one step down and consider
2782 // staggered fast volume
2783 sector = 4;
2784 --NbFastVolY;
2785 CornerX += FastVol.LX; // in the staggered part of the repeated volume
2786 CornerY -= (FastVol.LY - FastVol.YStagger);
2787 dx -= FastVol.LX;
2788 dy += (FastVol.LY - FastVol.YStagger);
2789 } else {
2790 neBEMMessage("FastKnChPFAtPoint: point in none of the sectors!\n");
2791 }
2792 if (dbgFn) printf("stagger modified dx, dy, dz: %g, %g, %g\n", dx, dy, dz);
2793 }
2794
2795 // Take care of possible trouble-makers - once more
2796 if (dx < MINDIST) dx = MINDIST; // -ve dx has already been made equal to 0
2797 if (dy < MINDIST) dy = MINDIST;
2798 if (dz < MINDIST) dz = MINDIST;
2799 if ((RptVolLX - dx) < MINDIST)
2800 dx = RptVolLX - MINDIST; // dx > RptVolLX taken care of
2801 if ((RptVolLY - dy) < MINDIST) dy = RptVolLY - MINDIST;
2802 if ((RptVolLZ - dz) < MINDIST) dz = RptVolLZ - MINDIST;
2803 // For staggered volumes, there is another plane where difficulties may occur
2804 if ((dx <= FastVol.LX) && (FastVol.LX - dx) < MINDIST)
2805 dx = FastVol.LX - MINDIST;
2806 // else if((dx > FastVol.LX) && (fabs(FastVol.LX-dx) < MINDIST))
2807 else if ((dx > FastVol.LX) && (dx - FastVol.LX) < MINDIST) // more intuitive
2808 dx = FastVol.LX + MINDIST;
2809 if (dbgFn)
2810 printf("equivalent dist adjusted for staggered: %g, %g, %g\n", dx, dy, dz);
2811
2812 // Check whether the point falls within a volume that is omitted
2813 for(int omit = 1; omit <= FastVol.NbOmitVols; ++omit) {
2814 if((dx >= (OmitVolCrnrX[omit]-FastVol.CrnrX)) &&
2815 (dx <= (OmitVolCrnrX[omit]+OmitVolLX[omit]-FastVol.CrnrX)) &&
2816 (dy >= (OmitVolCrnrY[omit]-FastVol.CrnrY)) &&
2817 (dy <= (OmitVolCrnrY[omit]+OmitVolLY[omit]-FastVol.CrnrY)) &&
2818 (dz >= (OmitVolCrnrZ[omit]-FastVol.CrnrZ)) &&
2819 (dz <= (OmitVolCrnrZ[omit]+OmitVolLZ[omit]-FastVol.CrnrZ))) {
2820 neBEMMessage("In FastKnChPFAtPoint: point in an omitted volume!\n");
2821 *Potential = 0.0;
2822 globalF->X = 0.0; globalF->Y = 0.0; globalF->Z = 0.0;
2823 }
2824 } // loop over omitted volumes
2825
2826 int thisBlock = 0;
2827 for (int block = 1; block <= FastVol.NbBlocks; ++block) {
2828 double blkBtmZ = BlkCrnrZ[block] - CornerZ; // since CornerZ has been
2829 double blkTopZ = blkBtmZ + BlkLZ[block]; // subtracted from dz already
2830 if (dbgFn) {
2831 printf("block, dz, blkBtmZ, blkTopZ: %d, %lg, %lg, %lg\n", block, dz,
2832 blkBtmZ, blkTopZ);
2833 }
2834
2835 // take care of difficult situations
2836 if ((dz <= blkBtmZ) && ((blkBtmZ - dz) < MINDIST)) dz = blkBtmZ - MINDIST;
2837 if ((dz >= blkBtmZ) && ((dz - blkBtmZ) < MINDIST)) dz = blkBtmZ + MINDIST;
2838 if ((dz <= blkTopZ) && ((blkTopZ - dz) < MINDIST)) dz = blkTopZ - MINDIST;
2839 if ((dz >= blkTopZ) && ((dz - blkTopZ) < MINDIST)) dz = blkTopZ + MINDIST;
2840
2841 if ((dz >= blkBtmZ) && (dz <= blkTopZ)) {
2842 thisBlock = block;
2843 break;
2844 }
2845 }
2846 if (!thisBlock) {
2847 neBEMMessage("FastKnChPFAtPoint: point in none of the blocks!\n");
2848 }
2849
2850 int nbXCells = BlkNbXCells[thisBlock];
2851 int nbYCells = BlkNbYCells[thisBlock];
2852 int nbZCells = BlkNbZCells[thisBlock];
2853 double delX = FastVol.LX / nbXCells;
2854 double delY = FastVol.LY / nbYCells;
2855 double delZ = BlkLZ[thisBlock] / nbZCells;
2856 dz -= (BlkCrnrZ[thisBlock] - CornerZ); // distance from the block corner
2857
2858 if (dbgFn) {
2859 printf("thisBlock: %d\n", thisBlock);
2860 printf("nbXCells, nbYCells, nbZCells: %d, %d, %d\n", nbXCells, nbYCells,
2861 nbZCells);
2862 printf("BlkCrnrZ: %lg\n", BlkCrnrZ[thisBlock]);
2863 printf("delX, delY, delZ: %le, %le, %le\n", delX, delY, delZ);
2864 printf("dz: %lg\n", dz);
2865 fflush(stdout);
2866 }
2867
2868 // Find cell in block of basic / staggered volume within which the point lies
2869 int celli = (int)(dx / delX) + 1; // Find cell in which the point lies
2870 if (celli < 1) {
2871 celli = 1;
2872 dx = 0.5 * delX;
2873 neBEMMessage("FastKnChPFAtPoint - celli < 1\n");
2874 }
2875 if (celli > nbXCells) {
2876 celli = nbXCells;
2877 dx = FastVol.LX - 0.5 * delX;
2878 neBEMMessage("FastKnChPFAtPoint - celli > nbXCells\n");
2879 }
2880 int cellj = (int)(dy / delY) + 1;
2881 if (cellj < 1) {
2882 cellj = 1;
2883 dy = 0.5 * delY;
2884 neBEMMessage("FastKnChPFAtPoint - cellj < 1\n");
2885 }
2886 if (cellj > nbYCells) {
2887 cellj = nbYCells;
2888 dy = FastVol.LY - 0.5 * delY;
2889 neBEMMessage("FastKnChPFAtPoint - cellj > nbYCells\n");
2890 }
2891 int cellk = (int)(dz / delZ) + 1;
2892 if (cellk < 1) {
2893 cellk = 1;
2894 dz = 0.5 * delX;
2895 neBEMMessage("FastKnChPFAtPoint - cellk < 1\n");
2896 }
2897 if (cellk > nbZCells) {
2898 cellk = nbZCells;
2899 dz = FastVol.LZ - 0.5 * delZ;
2900 neBEMMessage("FastKnChPFAtPoint - cellk > nbZCells\n");
2901 }
2902 if (dbgFn) printf("Cells in x, y, z: %d, %d, %d\n", celli, cellj, cellk);
2903
2904 // Interpolate potential and field at the point using the corner values of
2905 // of the cell and, if necessary, of the neighbouring cells
2906 // These gradients can also be calculated while computing the potential and
2907 // field at the cells and stored in memory, provided enough memory is
2908 // available
2909
2910 // distances from cell corner
2911 double dxcellcrnr = dx - (double)(celli - 1) * delX;
2912 double dycellcrnr = dy - (double)(cellj - 1) * delY;
2913 double dzcellcrnr = dz - (double)(cellk - 1) * delZ;
2914 if (dbgFn)
2915 printf("cell crnr dx, dy, dz: %g, %g, %g\n", dxcellcrnr, dycellcrnr,
2916 dzcellcrnr);
2917
2918 // normalized distances
2919 double xd = dxcellcrnr / delX; // xd = (x-x0)/(x1-x0)
2920 double yd = dycellcrnr / delY; // etc
2921 double zd = dzcellcrnr / delZ;
2922 if (xd <= 0.0) xd = 0.0;
2923 if (yd <= 0.0) yd = 0.0;
2924 if (zd <= 0.0) zd = 0.0;
2925 if (xd >= 1.0) xd = 1.0;
2926 if (yd >= 1.0) yd = 1.0;
2927 if (zd >= 1.0) zd = 1.0;
2928
2929 // corner values of potential and field
2930 double P000 = FastPotKnCh[thisBlock][celli][cellj][cellk]; // lowest corner
2931 double FX000 = FastFXKnCh[thisBlock][celli][cellj][cellk];
2932 double FY000 = FastFYKnCh[thisBlock][celli][cellj][cellk];
2933 double FZ000 = FastFZKnCh[thisBlock][celli][cellj][cellk];
2934 double P100 = FastPotKnCh[thisBlock][celli + 1][cellj][cellk];
2935 double FX100 = FastFXKnCh[thisBlock][celli + 1][cellj][cellk];
2936 double FY100 = FastFYKnCh[thisBlock][celli + 1][cellj][cellk];
2937 double FZ100 = FastFZKnCh[thisBlock][celli + 1][cellj][cellk];
2938 double P010 = FastPotKnCh[thisBlock][celli][cellj + 1][cellk];
2939 double FX010 = FastFXKnCh[thisBlock][celli][cellj + 1][cellk];
2940 double FY010 = FastFYKnCh[thisBlock][celli][cellj + 1][cellk];
2941 double FZ010 = FastFZKnCh[thisBlock][celli][cellj + 1][cellk];
2942 double P001 = FastPotKnCh[thisBlock][celli][cellj][cellk + 1];
2943 double FX001 = FastFXKnCh[thisBlock][celli][cellj][cellk + 1];
2944 double FY001 = FastFYKnCh[thisBlock][celli][cellj][cellk + 1];
2945 double FZ001 = FastFZKnCh[thisBlock][celli][cellj][cellk + 1];
2946 double P110 = FastPotKnCh[thisBlock][celli + 1][cellj + 1][cellk];
2947 double FX110 = FastFXKnCh[thisBlock][celli + 1][cellj + 1][cellk];
2948 double FY110 = FastFYKnCh[thisBlock][celli + 1][cellj + 1][cellk];
2949 double FZ110 = FastFZKnCh[thisBlock][celli + 1][cellj + 1][cellk];
2950 double P101 = FastPotKnCh[thisBlock][celli + 1][cellj][cellk + 1];
2951 double FX101 = FastFXKnCh[thisBlock][celli + 1][cellj][cellk + 1];
2952 double FY101 = FastFYKnCh[thisBlock][celli + 1][cellj][cellk + 1];
2953 double FZ101 = FastFZKnCh[thisBlock][celli + 1][cellj][cellk + 1];
2954 double P011 = FastPotKnCh[thisBlock][celli][cellj + 1][cellk + 1];
2955 double FX011 = FastFXKnCh[thisBlock][celli][cellj + 1][cellk + 1];
2956 double FY011 = FastFYKnCh[thisBlock][celli][cellj + 1][cellk + 1];
2957 double FZ011 = FastFZKnCh[thisBlock][celli][cellj + 1][cellk + 1];
2958 double P111 = FastPotKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
2959 double FX111 = FastFXKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
2960 double FY111 = FastFYKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
2961 double FZ111 = FastFZKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
2962 if (OptStaggerFastVol) {
2963 if (sector == 1) { // nothing to be done
2964 }
2965 if (sector == 2) { // volume shifted up but point not in the staggered part
2966 }
2967 if (sector == 3) { // staggered volume
2968 P000 = StgFastPotKnCh[thisBlock][celli][cellj][cellk];
2969 FX000 = StgFastFXKnCh[thisBlock][celli][cellj][cellk];
2970 FY000 = StgFastFYKnCh[thisBlock][celli][cellj][cellk];
2971 FZ000 = StgFastFZKnCh[thisBlock][celli][cellj][cellk];
2972 P100 = StgFastPotKnCh[thisBlock][celli + 1][cellj][cellk];
2973 FX100 = StgFastFXKnCh[thisBlock][celli + 1][cellj][cellk];
2974 FY100 = StgFastFYKnCh[thisBlock][celli + 1][cellj][cellk];
2975 FZ100 = StgFastFZKnCh[thisBlock][celli + 1][cellj][cellk];
2976 P010 = StgFastPotKnCh[thisBlock][celli][cellj + 1][cellk];
2977 FX010 = StgFastFXKnCh[thisBlock][celli][cellj + 1][cellk];
2978 FY010 = StgFastFYKnCh[thisBlock][celli][cellj + 1][cellk];
2979 FZ010 = StgFastFZKnCh[thisBlock][celli][cellj + 1][cellk];
2980 P001 = StgFastPotKnCh[thisBlock][celli][cellj][cellk + 1];
2981 FX001 = StgFastFXKnCh[thisBlock][celli][cellj][cellk + 1];
2982 FY001 = StgFastFYKnCh[thisBlock][celli][cellj][cellk + 1];
2983 FZ001 = StgFastFZKnCh[thisBlock][celli][cellj][cellk + 1];
2984 P110 = StgFastPotKnCh[thisBlock][celli + 1][cellj + 1][cellk];
2985 FX110 = StgFastFXKnCh[thisBlock][celli + 1][cellj + 1][cellk];
2986 FY110 = StgFastFYKnCh[thisBlock][celli + 1][cellj + 1][cellk];
2987 FZ110 = StgFastFZKnCh[thisBlock][celli + 1][cellj + 1][cellk];
2988 P101 = StgFastPotKnCh[thisBlock][celli + 1][cellj][cellk + 1];
2989 FX101 = StgFastFXKnCh[thisBlock][celli + 1][cellj][cellk + 1];
2990 FY101 = StgFastFYKnCh[thisBlock][celli + 1][cellj][cellk + 1];
2991 FZ101 = StgFastFZKnCh[thisBlock][celli + 1][cellj][cellk + 1];
2992 P011 = StgFastPotKnCh[thisBlock][celli][cellj + 1][cellk + 1];
2993 FX011 = StgFastFXKnCh[thisBlock][celli][cellj + 1][cellk + 1];
2994 FY011 = StgFastFYKnCh[thisBlock][celli][cellj + 1][cellk + 1];
2995 FZ011 = StgFastFZKnCh[thisBlock][celli][cellj + 1][cellk + 1];
2996 P111 = StgFastPotKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
2997 FX111 = StgFastFXKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
2998 FY111 = StgFastFYKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
2999 FZ111 = StgFastFZKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
3000 }
3001 if (sector == 4) { // volume shifted down and point in the staggered part
3002 P000 = StgFastPotKnCh[thisBlock][celli][cellj][cellk];
3003 FX000 = StgFastFXKnCh[thisBlock][celli][cellj][cellk];
3004 FY000 = StgFastFYKnCh[thisBlock][celli][cellj][cellk];
3005 FZ000 = StgFastFZKnCh[thisBlock][celli][cellj][cellk];
3006 P100 = StgFastPotKnCh[thisBlock][celli + 1][cellj][cellk];
3007 FX100 = StgFastFXKnCh[thisBlock][celli + 1][cellj][cellk];
3008 FY100 = StgFastFYKnCh[thisBlock][celli + 1][cellj][cellk];
3009 FZ100 = StgFastFZKnCh[thisBlock][celli + 1][cellj][cellk];
3010 P010 = StgFastPotKnCh[thisBlock][celli][cellj + 1][cellk];
3011 FX010 = StgFastFXKnCh[thisBlock][celli][cellj + 1][cellk];
3012 FY010 = StgFastFYKnCh[thisBlock][celli][cellj + 1][cellk];
3013 FZ010 = StgFastFZKnCh[thisBlock][celli][cellj + 1][cellk];
3014 P001 = StgFastPotKnCh[thisBlock][celli][cellj][cellk + 1];
3015 FX001 = StgFastFXKnCh[thisBlock][celli][cellj][cellk + 1];
3016 FY001 = StgFastFYKnCh[thisBlock][celli][cellj][cellk + 1];
3017 FZ001 = StgFastFZKnCh[thisBlock][celli][cellj][cellk + 1];
3018 P110 = StgFastPotKnCh[thisBlock][celli + 1][cellj + 1][cellk];
3019 FX110 = StgFastFXKnCh[thisBlock][celli + 1][cellj + 1][cellk];
3020 FY110 = StgFastFYKnCh[thisBlock][celli + 1][cellj + 1][cellk];
3021 FZ110 = StgFastFZKnCh[thisBlock][celli + 1][cellj + 1][cellk];
3022 P101 = StgFastPotKnCh[thisBlock][celli + 1][cellj][cellk + 1];
3023 FX101 = StgFastFXKnCh[thisBlock][celli + 1][cellj][cellk + 1];
3024 FY101 = StgFastFYKnCh[thisBlock][celli + 1][cellj][cellk + 1];
3025 FZ101 = StgFastFZKnCh[thisBlock][celli + 1][cellj][cellk + 1];
3026 P011 = StgFastPotKnCh[thisBlock][celli][cellj + 1][cellk + 1];
3027 FX011 = StgFastFXKnCh[thisBlock][celli][cellj + 1][cellk + 1];
3028 FY011 = StgFastFYKnCh[thisBlock][celli][cellj + 1][cellk + 1];
3029 FZ011 = StgFastFZKnCh[thisBlock][celli][cellj + 1][cellk + 1];
3030 P111 = StgFastPotKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
3031 FX111 = StgFastFXKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
3032 FY111 = StgFastFYKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
3033 FZ111 = StgFastFZKnCh[thisBlock][celli + 1][cellj + 1][cellk + 1];
3034 }
3035 } // if OptStaggerFastVol
3036
3037 double intP =
3038 TriLin(xd, yd, zd, P000, P100, P010, P001, P110, P101, P011, P111);
3039 double intFX = TriLin(xd, yd, zd, FX000, FX100, FX010, FX001, FX110, FX101,
3040 FX011, FX111);
3041 double intFY = TriLin(xd, yd, zd, FY000, FY100, FY010, FY001, FY110, FY101,
3042 FY011, FY111);
3043 double intFZ = TriLin(xd, yd, zd, FZ000, FZ100, FZ010, FZ001, FZ110, FZ101,
3044 FZ011, FZ111);
3045
3046 *Potential = intP;
3047 globalF->X = intFX;
3048 globalF->Y = intFY;
3049 globalF->Z = intFZ;
3050
3051 if (dbgFn) {
3052 printf("Cell corner values:\n");
3053 printf("Potential: %g, %g, %g, %g\n", P000, P100, P010, P001);
3054 printf("Potential: %g, %g, %g, %g\n", P110, P101, P011, P111);
3055 printf("FastFX: %g, %g, %g, %g\n", FX000, FX100, FX010, FX001);
3056 printf("FastFX: %g, %g, %g, %g\n", FX110, FX101, FX011, FX111);
3057 printf("FastFY: %g, %g, %g, %g\n", FY000, FY100, FY010, FY001);
3058 printf("FastFY: %g, %g, %g, %g\n", FY110, FY101, FY011, FY111);
3059 printf("FastFZ: %g, %g, %g, %g\n", FZ000, FZ100, FZ010, FZ001);
3060 printf("FastFZ: %g, %g, %g, %g\n", FZ110, FZ101, FZ011, FZ111);
3061 printf("Pot, FX, FY, FZ: %g, %g, %g, %g\n", *Potential, globalF->X,
3062 globalF->Y, globalF->Z);
3063 }
3064
3065 if (dbgFn) {
3066 printf("out FastKnChPFAtPoint\n");
3067 fflush(stdout);
3068 }
3069
3070 return 0;
3071} // 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)
#define MINDIST
Definition Isles.h:18
neBEMGLOBAL double **** FastFYKnCh
Definition neBEM.h:465
neBEMGLOBAL double **** StgFastFYKnCh
Definition neBEM.h:467
neBEMGLOBAL double **** StgFastFZKnCh
Definition neBEM.h:467
neBEMGLOBAL double * IgnoreVolCrnrY
Definition neBEM.h:456
neBEMGLOBAL double **** StgFastPotKnCh
Definition neBEM.h:466
neBEMGLOBAL double * IgnoreVolLY
Definition neBEM.h:453
neBEMGLOBAL double * IgnoreVolLX
Definition neBEM.h:452
neBEMGLOBAL double **** FastFXKnCh
Definition neBEM.h:465
neBEMGLOBAL double **** StgFastFXKnCh
Definition neBEM.h:467
neBEMGLOBAL double * IgnoreVolLZ
Definition neBEM.h:454
neBEMGLOBAL double **** FastFZKnCh
Definition neBEM.h:465
neBEMGLOBAL double **** FastPotKnCh
Definition neBEM.h:464
neBEMGLOBAL double * IgnoreVolCrnrX
Definition neBEM.h:455
neBEMGLOBAL double * IgnoreVolCrnrZ
Definition neBEM.h:457

◆ FastPFAtPoint()

int FastPFAtPoint ( Point3D * globalP,
double * Potential,
Vector3D * globalF )

Definition at line 2133 of file ComputeProperties.c.

2133 {
2134 int dbgFn = 0;
2135 double Xpt = globalP->X;
2136 double Ypt = globalP->Y;
2137 double Zpt = globalP->Z;
2138 double RptVolLX = FastVol.LX;
2139 double RptVolLY = FastVol.LY;
2140 double RptVolLZ = FastVol.LZ;
2141 double CornerX = FastVol.CrnrX;
2142 double CornerY = FastVol.CrnrY;
2143 double CornerZ = FastVol.CrnrZ;
2144 double TriLin(double xd, double yd, double zd, double c000, double c100,
2145 double c010, double c001, double c110, double c101, double c011,
2146 double c111);
2147
2148 // First of all, check how the point in question should be treated ...
2149
2150 // Check whether the point falls within a volume that is not regarded as
2151 // FastVol
2152 for (int ignore = 1; ignore <= FastVol.NbIgnoreVols; ++ignore) {
2153 if ((Xpt >= (IgnoreVolCrnrX[ignore])) &&
2154 (Xpt <= (IgnoreVolCrnrX[ignore] + IgnoreVolLX[ignore])) &&
2155 (Ypt >= (IgnoreVolCrnrY[ignore])) &&
2156 (Ypt <= (IgnoreVolCrnrY[ignore] + IgnoreVolLY[ignore])) &&
2157 (Zpt >= (IgnoreVolCrnrZ[ignore])) &&
2158 (Zpt <= (IgnoreVolCrnrZ[ignore] + IgnoreVolLZ[ignore]))) {
2159 if (dbgFn)
2160 neBEMMessage("In FastPFAtPoint: point in an ignored volume!\n");
2161
2162 int fstatus = PFAtPoint(globalP, Potential, globalF);
2163 if (fstatus != 0) {
2164 neBEMMessage("wrong PFAtPoint return value in FastVolPF.\n");
2165 return -1;
2166 } else
2167 return 0;
2168 }
2169 } // loop over ignored volumes
2170
2171 // If not ignored, the point qualifies for FastVol evaluation ...
2172
2173 // for a staggered fast volume, the volume repeated in X is larger
2174 if (OptStaggerFastVol) {
2175 RptVolLX += FastVol.LX;
2176 }
2177 if (dbgFn) {
2178 printf("\nin FastPFAtPoint\n");
2179 printf("x, y, z: %g, %g, %g\n", Xpt, Ypt, Zpt);
2180 printf("RptVolLX, RptVolLY, RptVolLZ: %g, %g, %g\n", RptVolLX, RptVolLY,
2181 RptVolLZ);
2182 printf("CornerX, CornerY, CornerZ: %g, %g, %g\n", CornerX, CornerY,
2183 CornerZ);
2184 printf("Nb of blocks: %d\n", FastVol.NbBlocks);
2185 for (int block = 1; block <= FastVol.NbBlocks; ++block) {
2186 printf("NbOfXCells: %d\n", BlkNbXCells[block]);
2187 printf("NbOfYCells: %d\n", BlkNbYCells[block]);
2188 printf("NbOfZCells: %d\n", BlkNbZCells[block]);
2189 printf("LZ: %le\n", BlkLZ[block]);
2190 printf("CornerZ: %le\n", BlkCrnrZ[block]);
2191 }
2192 }
2193
2194 // Find equivalent position inside the basic / staggered volume.
2195 // real distance from volume corner
2196 double dx = Xpt - CornerX;
2197 double dy = Ypt - CornerY;
2198 double dz = Zpt - CornerZ;
2199 if (dbgFn)
2200 printf("real dx, dy, dz from volume corner: %g, %g, %g\n", dx, dy, dz);
2201
2202 int NbFastVolX = (int)(dx / RptVolLX);
2203 if (dx < 0.0) --NbFastVolX;
2204 int NbFastVolY = (int)(dy / RptVolLY);
2205 if (dy < 0.0) --NbFastVolY;
2206 int NbFastVolZ = (int)(dz / RptVolLZ);
2207 if (dz < 0.0) --NbFastVolZ;
2208 if (dbgFn)
2209 printf("Volumes in x, y, z: %d, %d, %d\n", NbFastVolX, NbFastVolY,
2210 NbFastVolZ);
2211
2212 // equivalent distances from fast volume corner
2213 dx -= NbFastVolX * RptVolLX;
2214 dy -= NbFastVolY * RptVolLY;
2215 dz -= NbFastVolZ * RptVolLZ;
2216 // The following conditions should never happen - generate an error message
2217 if (dx < 0.0) {
2218 dx = 0.0;
2219 neBEMMessage("equiv dx < 0.0 - not correct!\n");
2220 }
2221 if (dy < 0.0) {
2222 dy = 0.0;
2223 neBEMMessage("equiv dy < 0.0 - not correct!\n");
2224 }
2225 if (dz < 0.0) {
2226 dz = 0.0;
2227 neBEMMessage("equiv dz < 0.0 - not correct!\n");
2228 }
2229 if (dx > RptVolLX) {
2230 dx = RptVolLX;
2231 neBEMMessage("equiv dx > RptVolLX - not correct!\n");
2232 }
2233 if (dy > RptVolLY) {
2234 dy = RptVolLY;
2235 neBEMMessage("equiv dy > RptVolLY - not correct!\n");
2236 }
2237 if (dz > RptVolLZ) {
2238 dz = RptVolLZ;
2239 neBEMMessage("equiv dz > RptVolLZ - not correct!\n");
2240 }
2241 if (dbgFn)
2242 printf("equivalent dist from corner - dx, dy, dz: %g, %g, %g\n", dx, dy,
2243 dz);
2244
2245 // Take care of possible trouble-makers
2246 if (dx < MINDIST) dx = MINDIST; // -ve dx has already been made equal to 0
2247 if (dy < MINDIST) dy = MINDIST;
2248 if (dz < MINDIST) dz = MINDIST;
2249 if ((RptVolLX - dx) < MINDIST)
2250 dx = RptVolLX - MINDIST; // dx > RptVolLX taken care of
2251 if ((RptVolLY - dy) < MINDIST) dy = RptVolLY - MINDIST;
2252 if ((RptVolLZ - dz) < MINDIST) dz = RptVolLZ - MINDIST;
2253 // For staggered volumes, there is another plane where difficulties may occur
2254 if ((dx <= FastVol.LX) && (FastVol.LX - dx) < MINDIST)
2255 dx = FastVol.LX - MINDIST;
2256 // else if((dx > FastVol.LX) && (fabs(FastVol.LX-dx) < MINDIST))
2257 else if ((dx > FastVol.LX) && (dx - FastVol.LX) < MINDIST) // more inttuitive
2258 dx = FastVol.LX + MINDIST;
2259 if (dbgFn)
2260 printf("equivalent dist adjusted - dx, dy, dz: %g, %g, %g\n", dx, dy, dz);
2261
2262 // If volume is staggered, we have a few more things to do before finalizing
2263 // the values of equivalent distance
2264 // sector identification
2265 // _................__________________
2266 // | . . | Sector 3 |
2267 // | . . | |
2268 // | . | . |
2269 // | | . . |
2270 // | Sector 2 | . . |
2271 // |----------------| . . |
2272 // | | . |
2273 // | . | |
2274 // | . . | |
2275 // | . . |----------------|
2276 // | . . | Sector 4 |
2277 // | . | . |
2278 // | | . . |
2279 // | Sector 1 | . . |
2280 // |----------------|................|
2281
2282 int sector = 1; // kept outside `if' since this is necessary further below
2283 if (OptStaggerFastVol) {
2284 if ((dx >= 0.0) && (dx <= FastVol.LX) && (dy >= 0.0) &&
2285 (dy <= FastVol.LY)) {
2286 // point lies in sector 1, everything remains unchanged
2287 sector = 1;
2288 } else if ((dx >= 0.0) && (dx <= FastVol.LX) && (dy > FastVol.LY) &&
2289 (dy <= FastVol.LY + FastVol.YStagger)) {
2290 // point lies in sector 2, move basic volume one step up
2291 sector = 2;
2292 ++NbFastVolY;
2293 CornerY += FastVol.LY; // repeat length in Y is LY
2294 dy -= FastVol.LY;
2295 } else if ((dx > FastVol.LX) && (dx <= 2.0 * FastVol.LX) &&
2296 (dy >= FastVol.YStagger) &&
2297 (dy <= FastVol.LY + FastVol.YStagger)) {
2298 // point lies in sector 3, pt in staggered vol, change corner coords
2299 sector = 3;
2300 CornerX += FastVol.LX;
2301 CornerY += FastVol.YStagger;
2302 dx -= FastVol.LX;
2303 dy -= FastVol.YStagger;
2304 } else if ((dx > FastVol.LX) && (dx <= 2.0 * FastVol.LX) && (dy >= 0.0) &&
2305 (dy < FastVol.YStagger)) {
2306 // point lies in sector 4, move basic volume one step down and consider
2307 // staggered fast volume
2308 sector = 4;
2309 --NbFastVolY;
2310 CornerX += FastVol.LX; // in the staggered part of the repeated volume
2311 CornerY -= (FastVol.LY - FastVol.YStagger);
2312 dx -= FastVol.LX;
2313 dy += (FastVol.LY - FastVol.YStagger);
2314 } else {
2315 neBEMMessage("FastPFAtPoint: point in none of the sectors!\n");
2316 }
2317 if (dbgFn) printf("stagger modified dx, dy, dz: %g, %g, %g\n", dx, dy, dz);
2318 }
2319
2320 // Take care of possible trouble-makers - once more
2321 if (dx < MINDIST) dx = MINDIST; // -ve dx has already been made equal to 0
2322 if (dy < MINDIST) dy = MINDIST;
2323 if (dz < MINDIST) dz = MINDIST;
2324 if ((RptVolLX - dx) < MINDIST)
2325 dx = RptVolLX - MINDIST; // dx > RptVolLX taken care of
2326 if ((RptVolLY - dy) < MINDIST) dy = RptVolLY - MINDIST;
2327 if ((RptVolLZ - dz) < MINDIST) dz = RptVolLZ - MINDIST;
2328 // For staggered volumes, there is another plane where difficulties may occur
2329 if ((dx <= FastVol.LX) && (FastVol.LX - dx) < MINDIST)
2330 dx = FastVol.LX - MINDIST;
2331 // else if((dx > FastVol.LX) && (fabs(FastVol.LX-dx) < MINDIST))
2332 else if ((dx > FastVol.LX) && (dx - FastVol.LX) < MINDIST) // more intuitive
2333 dx = FastVol.LX + MINDIST;
2334 if (dbgFn)
2335 printf("equivalent dist adjusted for staggered: %g, %g, %g\n", dx, dy, dz);
2336
2337 // Check whether the point falls within a volume that is omitted
2338 for(int omit = 1; omit <= FastVol.NbOmitVols; ++omit) {
2339 if ((dx >= (OmitVolCrnrX[omit]-FastVol.CrnrX)) &&
2340 (dx <= (OmitVolCrnrX[omit]+OmitVolLX[omit]-FastVol.CrnrX)) &&
2341 (dy >= (OmitVolCrnrY[omit]-FastVol.CrnrY)) &&
2342 (dy <= (OmitVolCrnrY[omit]+OmitVolLY[omit]-FastVol.CrnrY)) &&
2343 (dz >= (OmitVolCrnrZ[omit]-FastVol.CrnrZ)) &&
2344 (dz <= (OmitVolCrnrZ[omit]+OmitVolLZ[omit]-FastVol.CrnrZ))) {
2345 neBEMMessage("In FastPFAtPoint: point in an omitted volume!\n");
2346 *Potential = 0.0;
2347 globalF->X = 0.0; globalF->Y = 0.0; globalF->Z = 0.0;
2348 }
2349 } // loop over omitted volumes
2350
2351 // Find the block in which the point lies
2352 int thisBlock = 0;
2353 for (int block = 1; block <= FastVol.NbBlocks; ++block) {
2354 double blkBtmZ = BlkCrnrZ[block] - CornerZ; // since CornerZ has been
2355 double blkTopZ = blkBtmZ + BlkLZ[block]; // subtracted from dz already
2356 if (dbgFn) {
2357 printf("block, dz, blkBtmZ, blkTopZ: %d, %lg, %lg, %lg\n", block, dz,
2358 blkBtmZ, blkTopZ);
2359 }
2360
2361 // take care of difficult situations
2362 if ((dz <= blkBtmZ) && ((blkBtmZ - dz) < MINDIST)) dz = blkBtmZ - MINDIST;
2363 if ((dz >= blkBtmZ) && ((dz - blkBtmZ) < MINDIST)) dz = blkBtmZ + MINDIST;
2364 if ((dz <= blkTopZ) && ((blkTopZ - dz) < MINDIST)) dz = blkTopZ - MINDIST;
2365 if ((dz >= blkTopZ) && ((dz - blkTopZ) < MINDIST)) dz = blkTopZ + MINDIST;
2366
2367 if ((dz >= blkBtmZ) && (dz <= blkTopZ)) {
2368 thisBlock = block;
2369 break;
2370 }
2371 }
2372 if (!thisBlock) {
2373 neBEMMessage("FastPFAtPoint: point in none of the blocks!\n");
2374 }
2375
2376 int nbXCells = BlkNbXCells[thisBlock];
2377 int nbYCells = BlkNbYCells[thisBlock];
2378 int nbZCells = BlkNbZCells[thisBlock];
2379 double delX = FastVol.LX / nbXCells;
2380 double delY = FastVol.LY / nbYCells;
2381 double delZ = BlkLZ[thisBlock] / nbZCells;
2382 dz -= (BlkCrnrZ[thisBlock] - CornerZ); // distance from the block corner
2383
2384 if (dbgFn) {
2385 printf("thisBlock: %d\n", thisBlock);
2386 printf("nbXCells, nbYCells, nbZCells: %d, %d, %d\n", nbXCells, nbYCells,
2387 nbZCells);
2388 printf("BlkCrnrZ: %lg\n", BlkCrnrZ[thisBlock]);
2389 printf("delX, delY, delZ: %le, %le, %le\n", delX, delY, delZ);
2390 printf("dz: %lg\n", dz);
2391 fflush(stdout);
2392 }
2393
2394 // Find cell in block of basic / staggered volume within which the point lies
2395 int celli = (int)(dx / delX) + 1; // Find cell in which the point lies
2396 if (celli < 1) {
2397 celli = 1;
2398 dx = 0.5 * delX;
2399 neBEMMessage("FastPFAtPoint - celli < 1\n");
2400 }
2401 if (celli > nbXCells) {
2402 celli = nbXCells;
2403 dx = FastVol.LX - 0.5 * delX;
2404 neBEMMessage("FastPFAtPoint - celli > nbXCells\n");
2405 }
2406 int cellj = (int)(dy / delY) + 1;
2407 if (cellj < 1) {
2408 cellj = 1;
2409 dy = 0.5 * delY;
2410 neBEMMessage("FastPFAtPoint - cellj < 1\n");
2411 }
2412 if (cellj > nbYCells) {
2413 cellj = nbYCells;
2414 dy = FastVol.LY - 0.5 * delY;
2415 neBEMMessage("FastPFAtPoint - cellj > nbYCells\n");
2416 }
2417 int cellk = (int)(dz / delZ) + 1;
2418 if (cellk < 1) {
2419 cellk = 1;
2420 dz = 0.5 * delX;
2421 neBEMMessage("FastPFAtPoint - cellk < 1\n");
2422 }
2423 if (cellk > nbZCells) {
2424 cellk = nbZCells;
2425 dz = FastVol.LZ - 0.5 * delZ;
2426 neBEMMessage("FastPFAtPoint - cellk > nbZCells\n");
2427 }
2428 if (dbgFn) printf("Cells in x, y, z: %d, %d, %d\n", celli, cellj, cellk);
2429
2430 // Interpolate potential and field at the point using the corner values of
2431 // of the cell and, if necessary, of the neighbouring cells
2432 // These gradients can also be calculated while computing the potential and
2433 // field at the cells and stored in memory, provided enough memory is
2434 // available
2435
2436 // distances from cell corner
2437 double dxcellcrnr = dx - (double)(celli - 1) * delX;
2438 double dycellcrnr = dy - (double)(cellj - 1) * delY;
2439 double dzcellcrnr = dz - (double)(cellk - 1) * delZ;
2440 if (dbgFn)
2441 printf("cell crnr dx, dy, dz: %g, %g, %g\n", dxcellcrnr, dycellcrnr,
2442 dzcellcrnr);
2443
2444 // normalized distances
2445 double xd = dxcellcrnr / delX; // xd = (x-x0)/(x1-x0)
2446 double yd = dycellcrnr / delY; // etc
2447 double zd = dzcellcrnr / delZ;
2448 if (xd <= 0.0) xd = 0.0;
2449 if (yd <= 0.0) yd = 0.0;
2450 if (zd <= 0.0) zd = 0.0;
2451 if (xd >= 1.0) xd = 1.0;
2452 if (yd >= 1.0) yd = 1.0;
2453 if (zd >= 1.0) zd = 1.0;
2454
2455 // corner values of potential and field
2456 double P000 = FastPot[thisBlock][celli][cellj][cellk]; // lowest corner
2457 double FX000 = FastFX[thisBlock][celli][cellj][cellk];
2458 double FY000 = FastFY[thisBlock][celli][cellj][cellk];
2459 double FZ000 = FastFZ[thisBlock][celli][cellj][cellk];
2460 double P100 = FastPot[thisBlock][celli + 1][cellj][cellk];
2461 double FX100 = FastFX[thisBlock][celli + 1][cellj][cellk];
2462 double FY100 = FastFY[thisBlock][celli + 1][cellj][cellk];
2463 double FZ100 = FastFZ[thisBlock][celli + 1][cellj][cellk];
2464 double P010 = FastPot[thisBlock][celli][cellj + 1][cellk];
2465 double FX010 = FastFX[thisBlock][celli][cellj + 1][cellk];
2466 double FY010 = FastFY[thisBlock][celli][cellj + 1][cellk];
2467 double FZ010 = FastFZ[thisBlock][celli][cellj + 1][cellk];
2468 double P001 = FastPot[thisBlock][celli][cellj][cellk + 1];
2469 double FX001 = FastFX[thisBlock][celli][cellj][cellk + 1];
2470 double FY001 = FastFY[thisBlock][celli][cellj][cellk + 1];
2471 double FZ001 = FastFZ[thisBlock][celli][cellj][cellk + 1];
2472 double P110 = FastPot[thisBlock][celli + 1][cellj + 1][cellk];
2473 double FX110 = FastFX[thisBlock][celli + 1][cellj + 1][cellk];
2474 double FY110 = FastFY[thisBlock][celli + 1][cellj + 1][cellk];
2475 double FZ110 = FastFZ[thisBlock][celli + 1][cellj + 1][cellk];
2476 double P101 = FastPot[thisBlock][celli + 1][cellj][cellk + 1];
2477 double FX101 = FastFX[thisBlock][celli + 1][cellj][cellk + 1];
2478 double FY101 = FastFY[thisBlock][celli + 1][cellj][cellk + 1];
2479 double FZ101 = FastFZ[thisBlock][celli + 1][cellj][cellk + 1];
2480 double P011 = FastPot[thisBlock][celli][cellj + 1][cellk + 1];
2481 double FX011 = FastFX[thisBlock][celli][cellj + 1][cellk + 1];
2482 double FY011 = FastFY[thisBlock][celli][cellj + 1][cellk + 1];
2483 double FZ011 = FastFZ[thisBlock][celli][cellj + 1][cellk + 1];
2484 double P111 = FastPot[thisBlock][celli + 1][cellj + 1][cellk + 1];
2485 double FX111 = FastFX[thisBlock][celli + 1][cellj + 1][cellk + 1];
2486 double FY111 = FastFY[thisBlock][celli + 1][cellj + 1][cellk + 1];
2487 double FZ111 = FastFZ[thisBlock][celli + 1][cellj + 1][cellk + 1];
2488 if (OptStaggerFastVol) {
2489 if (sector == 1) { // nothing to be done
2490 }
2491 if (sector == 2) { // volume shifted up but point not in the staggered part
2492 }
2493 if (sector == 3) { // staggered volume
2494 P000 = StgFastPot[thisBlock][celli][cellj][cellk];
2495 FX000 = StgFastFX[thisBlock][celli][cellj][cellk];
2496 FY000 = StgFastFY[thisBlock][celli][cellj][cellk];
2497 FZ000 = StgFastFZ[thisBlock][celli][cellj][cellk];
2498 P100 = StgFastPot[thisBlock][celli + 1][cellj][cellk];
2499 FX100 = StgFastFX[thisBlock][celli + 1][cellj][cellk];
2500 FY100 = StgFastFY[thisBlock][celli + 1][cellj][cellk];
2501 FZ100 = StgFastFZ[thisBlock][celli + 1][cellj][cellk];
2502 P010 = StgFastPot[thisBlock][celli][cellj + 1][cellk];
2503 FX010 = StgFastFX[thisBlock][celli][cellj + 1][cellk];
2504 FY010 = StgFastFY[thisBlock][celli][cellj + 1][cellk];
2505 FZ010 = StgFastFZ[thisBlock][celli][cellj + 1][cellk];
2506 P001 = StgFastPot[thisBlock][celli][cellj][cellk + 1];
2507 FX001 = StgFastFX[thisBlock][celli][cellj][cellk + 1];
2508 FY001 = StgFastFY[thisBlock][celli][cellj][cellk + 1];
2509 FZ001 = StgFastFZ[thisBlock][celli][cellj][cellk + 1];
2510 P110 = StgFastPot[thisBlock][celli + 1][cellj + 1][cellk];
2511 FX110 = StgFastFX[thisBlock][celli + 1][cellj + 1][cellk];
2512 FY110 = StgFastFY[thisBlock][celli + 1][cellj + 1][cellk];
2513 FZ110 = StgFastFZ[thisBlock][celli + 1][cellj + 1][cellk];
2514 P101 = StgFastPot[thisBlock][celli + 1][cellj][cellk + 1];
2515 FX101 = StgFastFX[thisBlock][celli + 1][cellj][cellk + 1];
2516 FY101 = StgFastFY[thisBlock][celli + 1][cellj][cellk + 1];
2517 FZ101 = StgFastFZ[thisBlock][celli + 1][cellj][cellk + 1];
2518 P011 = StgFastPot[thisBlock][celli][cellj + 1][cellk + 1];
2519 FX011 = StgFastFX[thisBlock][celli][cellj + 1][cellk + 1];
2520 FY011 = StgFastFY[thisBlock][celli][cellj + 1][cellk + 1];
2521 FZ011 = StgFastFZ[thisBlock][celli][cellj + 1][cellk + 1];
2522 P111 = StgFastPot[thisBlock][celli + 1][cellj + 1][cellk + 1];
2523 FX111 = StgFastFX[thisBlock][celli + 1][cellj + 1][cellk + 1];
2524 FY111 = StgFastFY[thisBlock][celli + 1][cellj + 1][cellk + 1];
2525 FZ111 = StgFastFZ[thisBlock][celli + 1][cellj + 1][cellk + 1];
2526 }
2527 if (sector == 4) { // volume shifted down and point in the staggered part
2528 P000 = StgFastPot[thisBlock][celli][cellj][cellk];
2529 FX000 = StgFastFX[thisBlock][celli][cellj][cellk];
2530 FY000 = StgFastFY[thisBlock][celli][cellj][cellk];
2531 FZ000 = StgFastFZ[thisBlock][celli][cellj][cellk];
2532 P100 = StgFastPot[thisBlock][celli + 1][cellj][cellk];
2533 FX100 = StgFastFX[thisBlock][celli + 1][cellj][cellk];
2534 FY100 = StgFastFY[thisBlock][celli + 1][cellj][cellk];
2535 FZ100 = StgFastFZ[thisBlock][celli + 1][cellj][cellk];
2536 P010 = StgFastPot[thisBlock][celli][cellj + 1][cellk];
2537 FX010 = StgFastFX[thisBlock][celli][cellj + 1][cellk];
2538 FY010 = StgFastFY[thisBlock][celli][cellj + 1][cellk];
2539 FZ010 = StgFastFZ[thisBlock][celli][cellj + 1][cellk];
2540 P001 = StgFastPot[thisBlock][celli][cellj][cellk + 1];
2541 FX001 = StgFastFX[thisBlock][celli][cellj][cellk + 1];
2542 FY001 = StgFastFY[thisBlock][celli][cellj][cellk + 1];
2543 FZ001 = StgFastFZ[thisBlock][celli][cellj][cellk + 1];
2544 P110 = StgFastPot[thisBlock][celli + 1][cellj + 1][cellk];
2545 FX110 = StgFastFX[thisBlock][celli + 1][cellj + 1][cellk];
2546 FY110 = StgFastFY[thisBlock][celli + 1][cellj + 1][cellk];
2547 FZ110 = StgFastFZ[thisBlock][celli + 1][cellj + 1][cellk];
2548 P101 = StgFastPot[thisBlock][celli + 1][cellj][cellk + 1];
2549 FX101 = StgFastFX[thisBlock][celli + 1][cellj][cellk + 1];
2550 FY101 = StgFastFY[thisBlock][celli + 1][cellj][cellk + 1];
2551 FZ101 = StgFastFZ[thisBlock][celli + 1][cellj][cellk + 1];
2552 P011 = StgFastPot[thisBlock][celli][cellj + 1][cellk + 1];
2553 FX011 = StgFastFX[thisBlock][celli][cellj + 1][cellk + 1];
2554 FY011 = StgFastFY[thisBlock][celli][cellj + 1][cellk + 1];
2555 FZ011 = StgFastFZ[thisBlock][celli][cellj + 1][cellk + 1];
2556 P111 = StgFastPot[thisBlock][celli + 1][cellj + 1][cellk + 1];
2557 FX111 = StgFastFX[thisBlock][celli + 1][cellj + 1][cellk + 1];
2558 FY111 = StgFastFY[thisBlock][celli + 1][cellj + 1][cellk + 1];
2559 FZ111 = StgFastFZ[thisBlock][celli + 1][cellj + 1][cellk + 1];
2560 }
2561 } // if OptStaggerFastVol
2562
2563 double intP =
2564 TriLin(xd, yd, zd, P000, P100, P010, P001, P110, P101, P011, P111);
2565 double intFX = TriLin(xd, yd, zd, FX000, FX100, FX010, FX001, FX110, FX101,
2566 FX011, FX111);
2567 double intFY = TriLin(xd, yd, zd, FY000, FY100, FY010, FY001, FY110, FY101,
2568 FY011, FY111);
2569 double intFZ = TriLin(xd, yd, zd, FZ000, FZ100, FZ010, FZ001, FZ110, FZ101,
2570 FZ011, FZ111);
2571
2572 *Potential = intP;
2573 globalF->X = intFX;
2574 globalF->Y = intFY;
2575 globalF->Z = intFZ;
2576
2577 if (dbgFn) {
2578 printf("Cell corner values:\n");
2579 printf("Potential: %g, %g, %g, %g\n", P000, P100, P010, P001);
2580 printf("Potential: %g, %g, %g, %g\n", P110, P101, P011, P111);
2581 printf("FastFX: %g, %g, %g, %g\n", FX000, FX100, FX010, FX001);
2582 printf("FastFX: %g, %g, %g, %g\n", FX110, FX101, FX011, FX111);
2583 printf("FastFY: %g, %g, %g, %g\n", FY000, FY100, FY010, FY001);
2584 printf("FastFY: %g, %g, %g, %g\n", FY110, FY101, FY011, FY111);
2585 printf("FastFZ: %g, %g, %g, %g\n", FZ000, FZ100, FZ010, FZ001);
2586 printf("FastFZ: %g, %g, %g, %g\n", FZ110, FZ101, FZ011, FZ111);
2587 printf("Pot, FX, FY, FZ: %g, %g, %g, %g\n", *Potential, globalF->X,
2588 globalF->Y, globalF->Z);
2589 }
2590
2591 if (dbgFn) {
2592 printf("out FastPFAtPoint\n");
2593 fflush(stdout);
2594 }
2595
2596 return 0;
2597} // FastPFAtPoint ends

Referenced by MapFPR(), and neBEMPF().

◆ GetFlux()

void GetFlux ( int ele,
Point3D * localP,
Vector3D * localF )

Definition at line 204 of file ComputeProperties.c.

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

◆ GetFluxGCS()

void GetFluxGCS ( int ele,
Point3D * localP,
Vector3D * globalF )

Definition at line 180 of file ComputeProperties.c.

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

◆ GetPF()

void GetPF ( int type,
double a,
double b,
double x,
double y,
double z,
double * Potential,
Vector3D * localF )

Definition at line 4501 of file ComputeProperties.c.

4502 {
4503 switch (type) {
4504 case 4: // rectangular element
4505 RecPF(a, b, x, y, z, Potential, localF);
4506 break;
4507 case 3: // triangular element
4508 TriPF(a, b, x, y, z, Potential, localF);
4509 break;
4510 case 2: // linear (wire) element
4511 WirePF(a, b, x, y, z, Potential, localF);
4512 break;
4513 default:
4514 printf("Geometrical type out of range! ... exiting ...\n");
4515 exit(-1);
4516 break; // never comes here
4517 } // switch over gtsrc ends
4518} // 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 WtFldPFAtPoint().

◆ GetPFGCS()

void GetPFGCS ( int type,
double a,
double b,
Point3D * localP,
double * Potential,
Vector3D * globalF,
DirnCosn3D * DirCos )

Definition at line 4474 of file ComputeProperties.c.

4475 {
4476 Vector3D localF;
4477 const double x = localP->X;
4478 const double y = localP->Y;
4479 const double z = localP->Z;
4480 switch (type) {
4481 case 4: // rectangular element
4482 RecPF(a, b, x, y, z, Potential, &localF);
4483 break;
4484 case 3: // triangular element
4485 TriPF(a, b, x, y, z, Potential, &localF);
4486 break;
4487 case 2: // linear (wire) element
4488 WirePF(a, b, x, y, z, Potential, &localF);
4489 break;
4490 default:
4491 printf("Geometrical type out of range! ... exiting ...\n");
4492 exit(-1);
4493 break; // never comes here
4494 } // switch over gtsrc ends
4495
4496 (*globalF) = RotateVector3D(&localF, DirCos, local2global);
4497} // end of GetPFGCS

Referenced by ElePFAtPoint().

◆ GetPotential()

double GetPotential ( int ele,
Point3D * localP )

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()

void GetPrimPF ( int prim,
Point3D * localP,
double * Potential,
Vector3D * localF )

Definition at line 4625 of file ComputeProperties.c.

4625 {
4626 switch (PrimType[prim]) {
4627 case 4: // rectangular primitive
4628 RecPrimPF(prim, localP, Potential, localF);
4629 break;
4630 case 3: // triangular primitive
4631 TriPrimPF(prim, localP, Potential, localF);
4632 break;
4633 case 2: // linear (wire) primitive
4634 WirePrimPF(prim, localP, Potential, localF);
4635 break;
4636 default:
4637 printf("Geometrical type out of range! ... exiting ...\n");
4638 exit(-1);
4639 break; // never comes here
4640 } // switch over gtsrc ends
4641} // 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)
neBEMGLOBAL int * PrimType
Definition neBEM.h:74

Referenced by ElePFAtPoint(), and WtFldPFAtPoint().

◆ GetPrimPFGCS()

void GetPrimPFGCS ( int prim,
Point3D * localP,
double * Potential,
Vector3D * globalF,
DirnCosn3D * DirCos )

Definition at line 4600 of file ComputeProperties.c.

4601 {
4602 Vector3D localF;
4603
4604 switch (PrimType[prim]) {
4605 case 4: // rectangular primitive
4606 RecPrimPF(prim, localP, Potential, &localF);
4607 break;
4608 case 3: // triangular primitive
4609 TriPrimPF(prim, localP, Potential, &localF);
4610 break;
4611 case 2: // linear (wire) primitive
4612 WirePrimPF(prim, localP, Potential, &localF);
4613 break;
4614 default:
4615 printf("Geometrical type out of range! ... exiting ...\n");
4616 exit(-1);
4617 break; // never comes here
4618 } // switch over gtsrc ends
4619
4620 (*globalF) = RotateVector3D(&localF, DirCos, local2global);
4621} // end of GetPrimPFGCS

Referenced by ElePFAtPoint().

◆ KnChPFAtPoint()

int KnChPFAtPoint ( Point3D * globalP,
double * Potential,
Vector3D * globalF )

Definition at line 1069 of file ComputeProperties.c.

1069 {
1070 int dbgFn = 0;
1071 double tmpPot;
1072 Point3D fldPt;
1073 fldPt.X = globalP->X;
1074 fldPt.Y = globalP->Y;
1075 fldPt.Z = globalP->Z;
1076 Vector3D tmpF;
1077
1078 // initialize the values for each point being evaluated.
1079 *Potential = 0.0;
1080 globalF->X = globalF->Y = globalF->Z = 0.0;
1081
1082 for (int point = 1; point <= NbPointsKnCh; ++point) {
1083 Point3D srcPt;
1084 srcPt.X = PointKnChArr[point].P.X;
1085 srcPt.Y = PointKnChArr[point].P.Y;
1086 srcPt.Z = PointKnChArr[point].P.Z;
1087
1088 tmpPot = PointKnChPF(srcPt, fldPt, &tmpF);
1089 (*Potential) += PointKnChArr[point].Assigned * tmpPot;
1090 globalF->X += PointKnChArr[point].Assigned * tmpF.X;
1091 globalF->Y += PointKnChArr[point].Assigned * tmpF.Y;
1092 globalF->Z += PointKnChArr[point].Assigned * tmpF.Z;
1093 }
1094
1095 if (dbgFn) {
1096 printf("Final values due to all known point charges (*MyFACTOR): ");
1097 // printf("xfld\tyfld\tzfld\tPot\tFx\tFy\tFz\n"); // refer, do not uncomment
1098 printf("%lg\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n\n", fldPt.X, fldPt.Y, fldPt.Z,
1099 (*Potential), globalF->X, globalF->Y, globalF->Z);
1100 fflush(stdout);
1101 }
1102
1103 for (int line = 1; line <= NbLinesKnCh; ++line) {
1104 Point3D startPt, stopPt;
1105 startPt.X = LineKnChArr[line].Start.X;
1106 startPt.Y = LineKnChArr[line].Start.Y;
1107 startPt.Z = LineKnChArr[line].Start.Z;
1108 stopPt.X = LineKnChArr[line].Stop.X;
1109 stopPt.Y = LineKnChArr[line].Stop.Y;
1110 stopPt.Z = LineKnChArr[line].Stop.Z;
1111 tmpPot = LineKnChPF(startPt, stopPt, fldPt, &tmpF);
1112 (*Potential) += LineKnChArr[line].Assigned * tmpPot;
1113 globalF->X += LineKnChArr[line].Assigned * tmpF.X;
1114 globalF->Y += LineKnChArr[line].Assigned * tmpF.Y;
1115 globalF->Z += LineKnChArr[line].Assigned * tmpF.Z;
1116 }
1117
1118 if (dbgFn) {
1119 printf("Final values due to all known line charges (*MyFACTOR): ");
1120 // printf("xfld\tyfld\tzfld\tPot\tFx\tFy\tFz\n"); // refer, do not uncomment
1121 printf("%lg\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n\n", fldPt.X, fldPt.Y, fldPt.Z,
1122 (*Potential), globalF->X, globalF->Y, globalF->Z);
1123 fflush(stdout);
1124 }
1125
1126 // Conversion to simpler structure may be necessary, as done for points and
1127 // lines, above.
1128 for (int area = 1; area <= NbAreasKnCh; ++area) {
1129 tmpPot = AreaKnChPF((AreaKnChArr + area - 1)->NbVertices,
1130 ((AreaKnChArr + area - 1)->Vertex), fldPt, &tmpF);
1131 (*Potential) += (AreaKnChArr + area - 1)->Assigned * tmpPot;
1132 globalF->X += (AreaKnChArr + area - 1)->Assigned * tmpF.X;
1133 globalF->Y += (AreaKnChArr + area - 1)->Assigned * tmpF.Y;
1134 globalF->Z += (AreaKnChArr + area - 1)->Assigned * tmpF.Z;
1135 }
1136
1137 if (dbgFn) {
1138 printf("Final values due to all known area charges (*MyFACTOR): ");
1139 // printf("xfld\tyfld\tzfld\tPot\tFx\tFy\tFz\n"); // refer, do not uncomment
1140 printf("%lg\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n\n", fldPt.X, fldPt.Y, fldPt.Z,
1141 (*Potential), globalF->X, globalF->Y, globalF->Z);
1142 fflush(stdout);
1143 }
1144
1145 for (int vol = 1; vol <= NbVolumesKnCh; ++vol) {
1146 tmpPot = VolumeKnChPF((VolumeKnChArr + vol - 1)->NbVertices,
1147 ((VolumeKnChArr + vol - 1)->Vertex), fldPt, &tmpF);
1148 (*Potential) += (VolumeKnChArr + vol - 1)->Assigned * tmpPot;
1149 globalF->X += (VolumeKnChArr + vol - 1)->Assigned * tmpF.X;
1150 globalF->Y += (VolumeKnChArr + vol - 1)->Assigned * tmpF.Y;
1151 globalF->Z += (VolumeKnChArr + vol - 1)->Assigned * tmpF.Z;
1152 }
1153
1154 if (dbgFn) {
1155 printf("Final values due to all known volume charges (*MyFACTOR): ");
1156 // printf("xfld\tyfld\tzfld\tPot\tFx\tFy\tFz\n"); // for reference, do not
1157 // uncomment
1158 printf("%lg\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n\n", fldPt.X, fldPt.Y, fldPt.Z,
1159 (*Potential), globalF->X, globalF->Y, globalF->Z);
1160 fflush(stdout);
1161 }
1162
1163 (*Potential) /= MyFACTOR;
1164 globalF->X /= MyFACTOR;
1165 globalF->Y /= MyFACTOR;
1166 globalF->Z /= MyFACTOR;
1167
1168 return 0;
1169} // KnChPFAtPoint ends
double LineKnChPF(Point3D LineStart, Point3D LineStop, Point3D FieldPt, Vector3D *globalF)
Definition Isles.c:2271
double AreaKnChPF(int NbVertices, Point3D *Vertex, Point3D FieldPt, Vector3D *globalF)
Definition Isles.c:2694
double PointKnChPF(Point3D SourcePt, Point3D FieldPt, Vector3D *globalF)
Definition Isles.c:2249
double VolumeKnChPF(int, Point3D *, Point3D, Vector3D *globalF)
Definition Isles.c:2841
neBEMGLOBAL PointKnCh * PointKnChArr
Definition neBEM.h:253
neBEMGLOBAL VolumeKnCh * VolumeKnChArr
Definition neBEM.h:288
neBEMGLOBAL int * NbVertices
Definition neBEM.h:77
neBEMGLOBAL int NbPointsKnCh
Definition neBEM.h:244
neBEMGLOBAL AreaKnCh * AreaKnChArr
Definition neBEM.h:276
neBEMGLOBAL int NbLinesKnCh
Definition neBEM.h:244
neBEMGLOBAL int NbVolumesKnCh
Definition neBEM.h:244
neBEMGLOBAL int NbAreasKnCh
Definition neBEM.h:244
neBEMGLOBAL LineKnCh * LineKnChArr
Definition neBEM.h:264

Referenced by FastKnChPFAtPoint(), and PFAtPoint().

◆ MapFPR()

int MapFPR ( void )

Definition at line 1331 of file ComputeProperties.c.

1331 {
1332 int dbgFn = 0;
1333
1334 printf("\nPhysical potential and field computation for 3dMap data export\n");
1335
1336 char MapInfoFile[256];
1337 strcpy(MapInfoFile, BCOutDir);
1338 strcat(MapInfoFile, "/MapInfo.out");
1339 FILE *fMapInfo = fopen(MapInfoFile, "w");
1340 if (fMapInfo == NULL) {
1341 neBEMMessage("MapFPR - MapInfoFile");
1342 return -1;
1343 }
1344 if (dbgFn) {
1345 printf("MapInfoFile.out created ...\n");
1346 fflush(stdout);
1347 }
1348
1349 // In certain versions, we may have only the version number in the header and
1350 // nothing more. In that case, it is unsafe to assume that OptMap or
1351 // OptStaggerMap will be at all present in the output file. This decision
1352 // may need to be taken immediately after reading the MapVersion value.
1353 fprintf(fMapInfo, "%s\n", MapVersion);
1354 fprintf(fMapInfo, "%d\n", OptMap);
1355 fprintf(fMapInfo, "%d\n", OptStaggerMap);
1356 fprintf(fMapInfo, "%d\n", Map.NbXCells + 1);
1357 fprintf(fMapInfo, "%d\n", Map.NbYCells + 1);
1358 fprintf(fMapInfo, "%d\n", Map.NbZCells + 1);
1359 fprintf(fMapInfo, "%le %le\n", Map.Xmin * 100.0, Map.Xmax * 100.0);
1360 fprintf(fMapInfo, "%le %le\n", Map.Ymin * 100.0, Map.Ymax * 100.0);
1361 fprintf(fMapInfo, "%le %le\n", Map.Zmin * 100.0, Map.Zmax * 100.0);
1362 fprintf(fMapInfo, "%le\n", Map.XStagger * 100.0);
1363 fprintf(fMapInfo, "%le\n", Map.YStagger * 100.0);
1364 fprintf(fMapInfo, "%le\n", Map.ZStagger * 100.0);
1365 fprintf(fMapInfo, "MapFPR.out\n");
1366 // if (OptStaggerMap) fprintf(fMapInfo, "StgrMapFPR.out\n"); /// not being
1367 // read
1368 fclose(fMapInfo);
1369
1370 char MapFile[256];
1371 strcpy(MapFile, BCOutDir);
1372 strcat(MapFile, "/MapFPR.out");
1373 FILE *fMap = fopen(MapFile, "w");
1374 if (fMap == NULL) {
1375 neBEMMessage("MapFPR - MapFile");
1376 return -1;
1377 }
1378 if (dbgFn) {
1379 printf("MapFPR.out created ...\n");
1380 fflush(stdout);
1381 }
1382
1383 fprintf(
1384 fMap,
1385 "# X(cm)\tY(cm)\tZ(cm)\tFX(V/cm)\tFY(V/cm)\tFZ(V/cm)\tPot(V)\tRegion\n");
1386
1387 int nbXCells = Map.NbXCells;
1388 int nbYCells = Map.NbYCells;
1389 int nbZCells = Map.NbZCells;
1390 double startX = Map.Xmin;
1391 double startY = Map.Ymin;
1392 double startZ = Map.Zmin;
1393 double delX = (Map.Xmax - Map.Xmin) / nbXCells;
1394 double delY = (Map.Ymax - Map.Ymin) / nbYCells;
1395 double delZ = (Map.Zmax - Map.Zmin) / nbZCells;
1396
1397 double *MapFX = dvector(0, nbZCells + 1);
1398 double *MapFY = dvector(0, nbZCells + 1);
1399 double *MapFZ = dvector(0, nbZCells + 1);
1400 double *MapP = dvector(0, nbZCells + 1);
1401
1402 if (dbgFn) {
1403 printf("nbXCells, nbYCells, nbZCells: %d, %d, %d\n", nbXCells, nbYCells,
1404 nbZCells);
1405 printf("startX, startY, startZ: %le, %le, %le\n", startX, startY, startZ);
1406 printf("delX, delY, delZ: %le, %le, %le\n", delX, delY, delZ);
1407 fflush(stdout);
1408 }
1409
1410 for (int i = 1; i <= nbXCells + 1; ++i) {
1411 for (int j = 1; j <= nbYCells + 1; ++j) {
1412 if (dbgFn) {
1413 printf("MapFPR => i: %4d, j: %4d", i, j);
1414 fflush(stdout);
1415 }
1416
1417 Point3D point;
1418#ifdef _OPENMP
1419 int nthreads = 1, tid = 0;
1420#pragma omp parallel private(nthreads, tid)
1421#endif
1422 {
1423#ifdef _OPENMP
1424 if (dbgFn) {
1425 tid = omp_get_thread_num();
1426 if (tid == 0) {
1427 nthreads = omp_get_num_threads();
1428 printf("Starting voxel computation with %d threads\n", nthreads);
1429 }
1430 }
1431#endif
1432 int k;
1433 Vector3D field;
1434 double potential;
1435#ifdef _OPENMP
1436#pragma omp for private(k, point, potential, field)
1437#endif
1438 for (k = 1; k <= nbZCells + 1; ++k) {
1439 point.X = startX + (i - 1) * delX; // all 3 components need to be
1440 point.Y = startY + (j - 1) * delY; // evaluated after pragma omp
1441 point.Z = startZ + (k - 1) * delZ;
1442
1443 if (dbgFn) {
1444 printf("i, j, k: %d, %d, %d\n", i, j, k);
1445 printf("point X, Y, Z: %.8lg\t%.8lg\t%.8lg\n",
1446 point.X / LengthScale, point.Y / LengthScale,
1447 point.Z / LengthScale);
1448 fflush(stdout);
1449 }
1450
1451 if (OptReadFastPF) {
1452 int fstatus = FastPFAtPoint(&point, &potential, &field);
1453 if (fstatus != 0) {
1454 neBEMMessage("wrong FastPFAtPoint return value in MapFPR\n");
1455 // return -1;
1456 }
1457 } else {
1459 "Suggestion: Use of FastVol can expedite generation of Map.\n");
1460 int fstatus = PFAtPoint(&point, &potential, &field);
1461 if (fstatus != 0) {
1462 neBEMMessage("wrong PFAtPoint return value in MapFPR\n");
1463 // return -1;
1464 }
1465 }
1466
1467 if (dbgFn) {
1468 printf("%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\n",
1469 point.X / LengthScale, point.Y / LengthScale,
1470 point.Z / LengthScale, field.X, field.Y, field.Z,
1471 potential / LengthScale);
1472 fflush(stdout);
1473 }
1474
1475 MapFX[k] = field.X;
1476 MapFY[k] = field.Y;
1477 MapFZ[k] = field.Z;
1478 MapP[k] = potential;
1479 } // loop k
1480 } // pragma omp parallel
1481
1482 for (int k = 1; k <= nbZCells + 1; ++k) {
1483 // file output
1484 point.X = startX + (i - 1) * delX;
1485 point.Y = startY + (j - 1) * delY;
1486 point.Z = startZ + (k - 1) * delZ;
1487
1488 int ivol = neBEMVolumePoint(point.X, point.Y, point.Z);
1489 /*
1490 volMaterial[ivol]; // region linked to material
1491 neBEMVolumeDescription(ivol, &vshp, &vmat, &veps, &vpot, &vq, &vtype);
1492 if (dbgFn) {
1493 printf("volref: %d\n", ivol);
1494 printf("shape: %d, material: %d\n", volShape[ivol],
1495 volMaterial[ivol]); printf("eps: %d, pot: %d\n", volEpsilon[ivol],
1496 volPotential[ivol]); printf("q: %d, type: %d\n", volCharge[ivol],
1497 volBoundaryType[ivol]); printf("shape: %d, material: %d\n", vshp,
1498 vmat); printf("eps: %d, pot: %d\n", veps, vpot); printf("q: %d, type:
1499 %d\n", vq, vtype);
1500 }
1501 */
1502
1503 fprintf(fMap, "%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%4d\n",
1504 100.0 * point.X / LengthScale, 100.0 * point.Y / LengthScale,
1505 100.0 * point.Z / LengthScale, MapFX[k] / 100.0,
1506 MapFY[k] / 100.0, MapFZ[k] / 100.0, MapP[k] / LengthScale,
1507 ivol + 1);
1508 }
1509 fflush(fMap); // file output over
1510 } // loop j
1511 } // loop i
1512
1513 fclose(fMap);
1514
1515 free_dvector(MapFX, 0, nbZCells + 1);
1516 free_dvector(MapFY, 0, nbZCells + 1);
1517 free_dvector(MapFZ, 0, nbZCells + 1);
1518 free_dvector(MapP, 0, nbZCells + 1);
1519
1520 // If staggered map
1521 if (OptStaggerMap) {
1522 char StgrMapFile[256];
1523 strcpy(StgrMapFile, BCOutDir);
1524 strcat(StgrMapFile, "/StgrMapFPR.out");
1525 fMap = fopen(StgrMapFile, "w");
1526 if (fMap == NULL) {
1527 neBEMMessage("StgrMapFPR - Staggered MapFile");
1528 return -1;
1529 }
1530 if (dbgFn) {
1531 printf("StgrMapFPR.out created ...\n");
1532 fflush(stdout);
1533 }
1534
1535 fprintf(
1536 fMap,
1537 "# "
1538 "X(cm)\tY(cm)\tZ(cm)\tFX(V/cm)\tFY(V/cm)\tFZ(V/cm)\tPot(V)\tRegion\n");
1539 // Very static stagger where X-shift is one map long
1540 double LX = (Map.Xmax - Map.Xmin);
1541 Map.Xmin = Map.Xmax;
1542 Map.Xmax = Map.Xmin + LX;
1543 double LY = (Map.Ymax - Map.Ymin);
1544 Map.Ymin = Map.Ymin + Map.YStagger;
1545 Map.Ymax = Map.Ymin + LY;
1546 nbXCells = Map.NbXCells;
1547 nbYCells = Map.NbYCells;
1548 nbZCells = Map.NbZCells;
1549 startX = Map.Xmin;
1550 // and y-shift is of the presecribed amount
1551 startY = Map.Ymin + Map.YStagger;
1552 startZ = Map.Zmin;
1553 delX = (Map.Xmax - Map.Xmin) / nbXCells;
1554 delY = (Map.Ymax - Map.Ymin) / nbYCells;
1555 delZ = (Map.Zmax - Map.Zmin) / nbZCells;
1556
1557 MapFX = dvector(0, nbZCells + 1);
1558 MapFY = dvector(0, nbZCells + 1);
1559 MapFZ = dvector(0, nbZCells + 1);
1560 MapP = dvector(0, nbZCells + 1);
1561
1562 if (dbgFn) {
1563 printf("nbXCells, nbYCells, nbZCells: %d, %d, %d\n", nbXCells, nbYCells,
1564 nbZCells);
1565 printf("startX, startY, startZ: %le, %le, %le\n", startX, startY, startZ);
1566 printf("delX, delY, delZ: %le, %le, %le\n", delX, delY, delZ);
1567 fflush(stdout);
1568 }
1569
1570 for (int i = 1; i <= nbXCells + 1; ++i) {
1571 for (int j = 1; j <= nbYCells + 1; ++j) {
1572 if (dbgFn) {
1573 printf("StgrMapFPR => i: %4d, j: %4d", i, j);
1574 fflush(stdout);
1575 }
1576
1577 Point3D point;
1578#ifdef _OPENMP
1579 int nthreads = 1, tid = 0;
1580#pragma omp parallel private(nthreads, tid)
1581#endif
1582 {
1583#ifdef _OPENMP
1584 if (dbgFn) {
1585 tid = omp_get_thread_num();
1586 if (tid == 0) {
1587 nthreads = omp_get_num_threads();
1588 printf("Starting voxel computation with %d threads\n", nthreads);
1589 }
1590 } // if dbgFn
1591#endif
1592 int k;
1593 Vector3D field;
1594 double potential;
1595#ifdef _OPENMP
1596#pragma omp for private(k, point, potential, field)
1597#endif
1598 for (k = 1; k <= nbZCells + 1; ++k) {
1599 point.X = startX + (i - 1) * delX; // all 3 components need to be
1600 point.Y = startY + (j - 1) * delY; // evaluated after pragma omp
1601 point.Z = startZ + (k - 1) * delZ;
1602
1603 if (dbgFn) {
1604 printf("i, j, k: %d, %d, %d\n", i, j, k);
1605 printf("point X, Y, Z: %.8lg\t%.8lg\t%.8lg\n",
1606 point.X / LengthScale, point.Y / LengthScale,
1607 point.Z / LengthScale);
1608 fflush(stdout);
1609 }
1610
1611 if (OptReadFastPF) {
1612 int fstatus = FastPFAtPoint(&point, &potential, &field);
1613 if (fstatus != 0) {
1614 neBEMMessage("wrong FastPFAtPoint return value in MapFPR\n");
1615 // return -1;
1616 }
1617 } else {
1619 "Suggestion: Use of FastVol can expedite generation of "
1620 "Map.\n");
1621 int fstatus = PFAtPoint(&point, &potential, &field);
1622 if (fstatus != 0) {
1623 neBEMMessage("wrong PFAtPoint return value in MapFPR\n");
1624 // return -1;
1625 }
1626 }
1627
1628 if (dbgFn) {
1629 printf("%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\n",
1630 point.X / LengthScale, point.Y / LengthScale,
1631 point.Z / LengthScale, field.X, field.Y, field.Z,
1632 potential / LengthScale);
1633 fflush(stdout);
1634 }
1635
1636 MapFX[k] = field.X;
1637 MapFY[k] = field.Y;
1638 MapFZ[k] = field.Z;
1639 MapP[k] = potential;
1640 } // loop k
1641 } // pragma omp parallel
1642
1643 for (int k = 1; k <= nbZCells + 1; ++k) {
1644 // file output
1645 point.X = startX + (i - 1) * delX;
1646 point.Y = startY + (j - 1) * delY;
1647 point.Z = startZ + (k - 1) * delZ;
1648
1649 int ivol = neBEMVolumePoint(point.X, point.Y, point.Z);
1650 /*
1651 volMaterial[ivol]; // region linked to material
1652 neBEMVolumeDescription(ivol, &vshp, &vmat, &veps, &vpot, &vq, &vtype);
1653 if (dbgFn) {
1654 printf("volref: %d\n", ivol);
1655 printf("shape: %d, material: %d\n", volShape[ivol], volMaterial[ivol]);
1656 printf("eps: %d, pot: %d\n", volEpsilon[ivol], volPotential[ivol]);
1657 printf("q: %d, type: %d\n", volCharge[ivol], volBoundaryType[ivol]);
1658 printf("shape: %d, material: %d\n", vshp, vmat);
1659 printf("eps: %d, pot: %d\n", veps, vpot);
1660 printf("q: %d, type: %d\n", vq, vtype);
1661 }
1662 */
1663
1664 fprintf(
1665 fMap, "%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%4d\n",
1666 100.0 * point.X / LengthScale, 100.0 * point.Y / LengthScale,
1667 100.0 * point.Z / LengthScale, MapFX[k] / 100.0, MapFY[k] / 100.0,
1668 MapFZ[k] / 100.0, MapP[k] / LengthScale, ivol + 1);
1669 } // for k <= nbZCells
1670 fflush(fMap); // file output over
1671
1672 } // loop j
1673 } // loop i
1674
1675 fclose(fMap);
1676
1677 free_dvector(MapFX, 0, nbZCells + 1);
1678 free_dvector(MapFY, 0, nbZCells + 1);
1679 free_dvector(MapFZ, 0, nbZCells + 1);
1680 free_dvector(MapP, 0, nbZCells + 1);
1681 } // If staggered map
1682
1683 return 0;
1684} // 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:410
neBEMGLOBAL int OptStaggerMap
Definition neBEM.h:393
neBEMGLOBAL char MapVersion[10]
Definition neBEM.h:394
neBEMGLOBAL int OptMap
Definition neBEM.h:392
neBEMGLOBAL int OptReadFastPF
Definition neBEM.h:421

Referenced by neBEMSolve().

◆ PFAtPoint()

int PFAtPoint ( Point3D * globalP,
double * Potential,
Vector3D * globalF )

Definition at line 366 of file ComputeProperties.c.

366 {
367 double ElePot;
368 Vector3D EleglobalF;
369 int fstatus = ElePFAtPoint(globalP, &ElePot, &EleglobalF);
370 if (fstatus) {
371 printf(
372 "Problem in ElePFAtPoint being called from PFAtPoint ... returning\n");
373 return (-1);
374 }
375 *Potential = ElePot;
376 globalF->X = EleglobalF.X;
377 globalF->Y = EleglobalF.Y;
378 globalF->Z = EleglobalF.Z;
379
380 if (OptKnCh) {
381 double KnChPot;
382 Vector3D KnChglobalF;
383 fstatus = KnChPFAtPoint(globalP, &KnChPot, &KnChglobalF);
384 if (fstatus) {
385 printf(
386 "Problem in KnChPFAtPoint being called from PFAtPoint ... "
387 "returning\n");
388 return (-1);
389 }
390 *Potential += KnChPot;
391 globalF->X += KnChglobalF.X;
392 globalF->Y += KnChglobalF.Y;
393 globalF->Z += KnChglobalF.Z;
394 }
395
396 return 0;
397} // PFAtPoint ends
int ElePFAtPoint(Point3D *globalP, double *Potential, Vector3D *globalF)
neBEMGLOBAL int OptKnCh
Definition neBEM.h:59

Referenced by CreateFastVolElePF(), FastPFAtPoint(), MapFPR(), neBEMPF(), Solve(), and VoxelFPR().

◆ RecFlux()

void RecFlux ( int ele,
Point3D * localP,
Vector3D * localF )

Definition at line 223 of file ComputeProperties.c.

223 {
224 if (DebugLevel == 301) {
225 printf("In RecFlux ...\n");
226 }
227
228 double xpt = localP->X;
229 double ypt = localP->Y;
230 double zpt = localP->Z;
231
232 double a = (EleArr + ele - 1)->G.LX;
233 double b = (EleArr + ele - 1)->G.LZ;
234 double diag = sqrt(a * a + b * b); // diagonal of the element
235
236 // distance of field point from element centroid
237 double dist = sqrt(xpt * xpt + ypt * ypt + zpt * zpt);
238
239 // no re-scaling necessary for `E'
240 if (dist >= FarField * diag) {
241 const double f = a * b / (dist * dist * dist);
242 localF->X = xpt * f;
243 localF->Y = ypt * f;
244 localF->Z = zpt * f;
245 } else {
246 double Pot;
247 int fstatus = ExactRecSurf(xpt / a, ypt / a, zpt / a, -0.5, -(b / a) / 2.0,
248 0.5, (b / a) / 2.0, &Pot, localF);
249 if (fstatus) { // non-zero
250 printf("problem in computing flux of rectangular element ... \n");
251 // printf("returning ...\n");
252 // return -1; void function at present
253 }
254 }
255
256#ifdef __cplusplus
257 localF->X *= InvFourPiEps0;
258 localF->Y *= InvFourPiEps0;
259 localF->Z *= InvFourPiEps0;
260#else
261 localF->X /= MyFACTOR;
262 localF->Y /= MyFACTOR;
263 localF->Z /= MyFACTOR;
264#endif
265} // 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:42
#define FarField
Definition Isles.h:22
DoubleAc sqrt(const DoubleAc &f)
Definition DoubleAc.cpp:314
neBEMGLOBAL int DebugLevel
Definition neBEM.h:195

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

◆ RecPF()

void RecPF ( double a,
double b,
double x,
double y,
double z,
double * Potential,
Vector3D * localF )

Definition at line 4522 of file ComputeProperties.c.

4523 {
4524 const double d2 = x * x + y * y + z * z;
4525 if (d2 >= FarField2 * (a * a + b * b)) {
4526 (*Potential) = a * b / sqrt(d2);
4527 const double f = (*Potential) / d2;
4528 localF->X = x * f;
4529 localF->Y = y * f;
4530 localF->Z = z * f;
4531 } else {
4532 int fstatus = ExactRecSurf(x / a, y / a, z / a, -0.5, -(b / a) / 2.0, 0.5,
4533 (b / a) / 2.0, Potential, localF);
4534 if (fstatus) { // non-zero
4535 printf("problem in RecPF ... \n");
4536 // printf("returning ...\n");
4537 // return -1; void function at present
4538 }
4539 (*Potential) *= a; // rescale - cannot be done outside because of the `if'
4540 }
4541
4542} // end of RecPF
#define FarField2
Definition Isles.h:23

Referenced by GetPF(), and GetPFGCS().

◆ RecPot()

double RecPot ( int ele,
Point3D * localP )

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) {
75 double dA = a * b;
76 Pot = dA / dist;
77 } else {
78 // normalize distances by `a' while sending - likely to improve accuracy
79 int fstatus = ExactRecSurf(xpt / a, ypt / a, zpt / a, -0.5, -(b / a) / 2.0,
80 0.5, (b / a) / 2.0, &Pot, &Field);
81 if (fstatus) { // non-zero
82 printf("problem in computing Potential of rectangular element ... \n");
83 printf("a: %lg, b: %lg, X: %lg, Y: %lg, Z: %lg\n", a, b, xpt, ypt, zpt);
84 // printf("returning ...\n");
85 // return -1; void function at present
86 }
87 Pot *= a; // rescale Potential - cannot be done outside because of the `if'
88 }
89
90#ifdef __cplusplus
91 return Pot * InvFourPiEps0;
92#else
93 return (Pot / MyFACTOR);
94#endif
95} // end of RecPot

Referenced by GetPotential(), SatisfyValue(), ValueChUp(), and ValueKnCh().

◆ RecPrimPF()

void RecPrimPF ( int prim,
Point3D * localP,
double * Potential,
Vector3D * localF )

Definition at line 4644 of file ComputeProperties.c.

4644 {
4645 double xpt = localP->X;
4646 double ypt = localP->Y;
4647 double zpt = localP->Z;
4648 double dist = sqrt(xpt * xpt + ypt * ypt + zpt * zpt);
4649
4650 double a = PrimLX[prim];
4651 double b = PrimLZ[prim];
4652 double diag = sqrt(a * a + b * b); // diagonal
4653
4654 if (dist >= FarField * diag) {
4655 double dA = a * b; // area
4656 (*Potential) = dA / dist;
4657 const double f = dA / (dist * dist * dist);
4658 localF->X = xpt * f;
4659 localF->Y = ypt * f;
4660 localF->Z = zpt * f;
4661 } else {
4662 int fstatus = ExactRecSurf(xpt / a, ypt / a, zpt / a, -0.5, -(b / a) / 2.0,
4663 0.5, (b / a) / 2.0, Potential, localF);
4664 if (fstatus) { // non-zero
4665 printf("problem in RecPrimPF ... \n");
4666 // printf("returning ...\n");
4667 // return -1; void function at present
4668 }
4669 (*Potential) *= a; // rescale - cannot be done outside because of the `if'
4670 }
4671
4672} // end of RecPrimPF
neBEMGLOBAL double * PrimLX
Definition neBEM.h:79
neBEMGLOBAL double * PrimLZ
Definition neBEM.h:79

Referenced by GetPrimPF(), and GetPrimPFGCS().

◆ TriFlux()

void TriFlux ( int ele,
Point3D * localP,
Vector3D * localF )

Definition at line 268 of file ComputeProperties.c.

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

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

◆ TriLin()

double TriLin ( double xd,
double yd,
double zd,
double c000,
double c100,
double c010,
double c001,
double c110,
double c101,
double c011,
double c111 )

Definition at line 4739 of file ComputeProperties.c.

4741 {
4742 double c00 = c000 * (1.0 - xd) + c100 * xd;
4743 double c10 = c010 * (1.0 - xd) + c110 * xd;
4744 double c01 = c001 * (1.0 - xd) + c101 * xd;
4745 double c11 = c011 * (1.0 - xd) + c111 * xd;
4746 double c0 = c00 * (1.0 - yd) + c10 * yd;
4747 double c1 = c01 * (1.0 - yd) + c11 * yd;
4748 return (c0 * (1.0 - zd) + c1 * zd);
4749}

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

◆ TriPF()

void TriPF ( double a,
double b,
double x,
double y,
double z,
double * Potential,
Vector3D * localF )

Definition at line 4545 of file ComputeProperties.c.

4546 {
4547 // printf("In TriPF\n");
4548 const double xm = x - a / 3.;
4549 const double zm = z - b / 3.;
4550 const double d2 = xm * xm + y * y + zm * zm;
4551
4552 if (d2 >= FarField2 * (a * a + b * b)) {
4553 (*Potential) = 0.5 * a * b / sqrt(d2);
4554 const double f = (*Potential) / d2;
4555 localF->X = x * f;
4556 localF->Y = y * f;
4557 localF->Z = z * f;
4558 } else {
4559 int fstatus = ExactTriSurf(b / a, x / a, y / a, z / a, Potential, localF);
4560 if (fstatus) { // non-zero
4561 printf("problem in TriPF ... \n");
4562 // printf("returning ...\n");
4563 // return -1; void function at present
4564 }
4565 (*Potential) *= a; // rescale - cannot be done outside because of the `if'
4566 }
4567 // printf("Out of TriPF\n");
4568} // end of TriPF

Referenced by GetPF(), and GetPFGCS().

◆ TriPot()

double TriPot ( int ele,
Point3D * localP )

Definition at line 98 of file ComputeProperties.c.

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

Referenced by GetPotential(), SatisfyValue(), ValueChUp(), and ValueKnCh().

◆ TriPrimPF()

void TriPrimPF ( int prim,
Point3D * localP,
double * Potential,
Vector3D * localF )

Definition at line 4676 of file ComputeProperties.c.

4676 {
4677 double xpt = localP->X;
4678 double ypt = localP->Y;
4679 double zpt = localP->Z;
4680 double a = PrimLX[prim];
4681 double b = PrimLZ[prim];
4682 // longest side (hypotenuse)
4683 double diag = sqrt(a * a + b * b);
4684 const double xm = xpt - a / 3.;
4685 const double zm = zpt - b / 3.;
4686 double dist = sqrt(xm * xm + ypt * ypt + zm * zm);
4687
4688 if (dist >= FarField * diag) {
4689 double dA = 0.5 * a * b; // area
4690 (*Potential) = dA / dist;
4691 double f = dA / (dist * dist * dist);
4692 localF->X = xpt * f;
4693 localF->Y = ypt * f;
4694 localF->Z = zpt * f;
4695 } else {
4696 int fstatus =
4697 ExactTriSurf(b / a, xpt / a, ypt / a, zpt / a, Potential, localF);
4698 if (fstatus) { // non-zero
4699 printf("problem in TriPrimPF ... \n");
4700 }
4701 (*Potential) *= a; // rescale - cannot be done outside because of the `if'
4702 }
4703
4704 // printf("Out of TriPrimPF\n");
4705} // end of TriPrimPF

Referenced by GetPrimPF(), and GetPrimPFGCS().

◆ VoxelFPR()

int VoxelFPR ( void )

Definition at line 1172 of file ComputeProperties.c.

1172 {
1173 int dbgFn = 0;
1174
1175 printf(
1176 "\nPhysical potential and field computation for voxelized data export\n");
1177
1178 char VoxelFile[256];
1179 strcpy(VoxelFile, BCOutDir);
1180 strcat(VoxelFile, "/VoxelFPR.out");
1181 FILE *fVoxel = fopen(VoxelFile, "w");
1182 if (fVoxel == NULL) {
1183 neBEMMessage("VoxelFPR - VoxelFile");
1184 return -1;
1185 }
1186 fprintf(
1187 fVoxel,
1188 "# X(cm)\tY(cm)\tZ(cm)\tFX(V/cm)\tFY(V/cm)\tFZ(V/cm)\tPot(V)\tRegion\n");
1189
1190 if (dbgFn) {
1191 printf("VoxelFPR.out created ...\n");
1192 fflush(stdout);
1193 }
1194
1195 int nbXCells = Voxel.NbXCells;
1196 int nbYCells = Voxel.NbYCells;
1197 int nbZCells = Voxel.NbZCells;
1198 double startX = Voxel.Xmin;
1199 double startY = Voxel.Ymin;
1200 double startZ = Voxel.Zmin;
1201 double delX = (Voxel.Xmax - Voxel.Xmin) / nbXCells;
1202 double delY = (Voxel.Ymax - Voxel.Ymin) / nbYCells;
1203 double delZ = (Voxel.Zmax - Voxel.Zmin) / nbZCells;
1204
1205 int ivol; // relates XYZ position to volume number
1206 double *VoxelFX = dvector(0, nbZCells + 1);
1207 double *VoxelFY = dvector(0, nbZCells + 1);
1208 double *VoxelFZ = dvector(0, nbZCells + 1);
1209 double *VoxelP = dvector(0, nbZCells + 1);
1210
1211 if (dbgFn) {
1212 printf("nbXCells, nbYCells, nbZCells: %d, %d, %d\n", nbXCells, nbYCells,
1213 nbZCells);
1214 printf("startX, startY, startZ: %le, %le, %le\n", startX, startY, startZ);
1215 printf("delX, delY, delZ: %le, %le, %le\n", delX, delY, delZ);
1216 fflush(stdout);
1217 }
1218
1219 for (int i = 1; i <= nbXCells + 1; ++i) {
1220 for (int j = 1; j <= nbYCells + 1; ++j) {
1221 if (dbgFn) {
1222 printf("VoxelFPR => i: %4d, j: %4d", i, j);
1223 fflush(stdout);
1224 }
1225
1226 Point3D point;
1227#ifdef _OPENMP
1228 int nthreads = 1, tid = 0;
1229#pragma omp parallel private(nthreads, tid)
1230#endif
1231 {
1232#ifdef _OPENMP
1233 if (dbgFn) {
1234 tid = omp_get_thread_num();
1235 if (tid == 0) {
1236 nthreads = omp_get_num_threads();
1237 printf("Starting voxel computation with %d threads\n", nthreads);
1238 }
1239 }
1240#endif
1241 int k;
1242 Vector3D field;
1243 double potential;
1244#ifdef _OPENMP
1245#pragma omp for private(k, point, potential, field)
1246#endif
1247 for (k = 1; k <= nbZCells + 1; ++k) {
1248 potential = 0.0;
1249 field.X = field.Y = field.Z = 0.0;
1250
1251 point.X = startX + (i - 1) * delX; // all 3 components need to be
1252 point.Y = startY + (j - 1) * delY; // evaluated after pragma omp
1253 point.Z = startZ + (k - 1) * delZ;
1254
1255 if (dbgFn) {
1256 printf("i, j, k: %d, %d, %d\n", i, j, k);
1257 printf("point X, Y, Z: %.8lg\t%.8lg\t%.8lg\n",
1258 point.X / LengthScale, point.Y / LengthScale,
1259 point.Z / LengthScale);
1260 fflush(stdout);
1261 }
1262
1263 int fstatus = PFAtPoint(&point, &potential, &field);
1264 if (fstatus != 0) {
1265 neBEMMessage("wrong PFAtPoint return value in VoxelFPR\n");
1266 // return -1;
1267 }
1268
1269 if (dbgFn) {
1270 printf("%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\n",
1271 point.X / LengthScale, point.Y / LengthScale,
1272 point.Z / LengthScale, field.X, field.Y, field.Z,
1273 potential / LengthScale);
1274 fflush(stdout);
1275 }
1276
1277 VoxelFX[k] = field.X;
1278 VoxelFY[k] = field.Y;
1279 VoxelFZ[k] = field.Z;
1280 VoxelP[k] = potential;
1281 } // loop k
1282 } // pragma omp parallel
1283
1284 for (int k = 1; k <= nbZCells + 1; ++k) { // file output
1285 point.X = startX + (i - 1) * delX;
1286 point.Y = startY + (j - 1) * delY;
1287 point.Z = startZ + (k - 1) * delZ;
1288
1289 ivol = neBEMVolumePoint(point.X, point.Y, point.Z);
1290 /*
1291 volMaterial[ivol]; // region linked to material
1292 neBEMVolumeDescription(ivol, &vshp, &vmat, &veps, &vpot, &vq, &vtype);
1293 if (dbgFn) {
1294 printf("volref: %d\n", ivol);
1295 printf("shape: %d, material: %d\n", volShape[ivol], volMaterial[ivol]);
1296 printf("eps: %d, pot: %d\n", volEpsilon[ivol], volPotential[ivol]);
1297 printf("q: %d, type: %d\n", volCharge[ivol], volBoundaryType[ivol]);
1298 printf("shape: %d, material: %d\n", vshp, vmat);
1299 printf("eps: %d, pot: %d\n", veps, vpot);
1300 printf("q: %d, type: %d\n", vq, vtype);
1301 }
1302 */
1303
1304 fprintf(fVoxel,
1305 "%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%.8lg\t%4d\n",
1306 100.0 * point.X / LengthScale, 100.0 * point.Y / LengthScale,
1307 100.0 * point.Z / LengthScale, VoxelFX[k] / 100.0,
1308 VoxelFY[k] / 100.0, VoxelFZ[k] / 100.0, VoxelP[k] / LengthScale,
1309 ivol + 1);
1310 }
1311 fflush(fVoxel); // file output over
1312
1313 // 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");
1314 } // loop j
1315 } // loop i
1316
1317 fclose(fVoxel);
1318
1319 free_dvector(VoxelFX, 0, nbZCells + 1);
1320 free_dvector(VoxelFY, 0, nbZCells + 1);
1321 free_dvector(VoxelFZ, 0, nbZCells + 1);
1322 free_dvector(VoxelP, 0, nbZCells + 1);
1323
1324 return 0;
1325} // end of VoxelFPR
neBEMGLOBAL VoxelVol Voxel
Definition neBEM.h:385

Referenced by neBEMSolve().

◆ WireFlux()

void WireFlux ( int ele,
Point3D * localP,
Vector3D * localF )

Definition at line 320 of file ComputeProperties.c.

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

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

◆ WirePF()

void WirePF ( double rW,
double lW,
double x,
double y,
double z,
double * Potential,
Vector3D * localF )

Definition at line 4571 of file ComputeProperties.c.

4572 {
4573 const double d2 = x * x + y * y + z * z;
4574 if (d2 >= FarField2 * lW * lW) {
4575 double dA = 2.0 * ST_PI * rW * lW;
4576 const double dist = sqrt(d2);
4577 (*Potential) = dA / dist;
4578 double f = dA / (dist * d2);
4579 localF->X = x * f;
4580 localF->Y = y * f;
4581 localF->Z = z * f;
4582 } else {
4583 if ((fabs(x) < MINDIST) && (fabs(y) < MINDIST)) {
4584 if (fabs(z) < MINDIST)
4585 (*Potential) = ExactCentroidalP_W(rW, lW);
4586 else
4587 (*Potential) = ExactAxialP_W(rW, lW, z);
4588
4589 localF->X = localF->Y = 0.0;
4590 localF->Z = ExactThinFZ_W(rW, lW, x, y, z);
4591 } else {
4592 ExactThinWire(rW, lW, x, y, z, Potential, localF);
4593 }
4594 }
4595} // end of WirePF
double ExactCentroidalP_W(double rW, double lW)
Definition Isles.c:1782
double ExactAxialP_W(double rW, double lW, double Z)
Definition Isles.c:1792
int ExactThinWire(double rW, double lW, double X, double Y, double Z, double *potential, Vector3D *Flux)
Definition Isles.c:2164

Referenced by GetPF(), and GetPFGCS().

◆ WirePot()

double WirePot ( int ele,
Point3D * localP )

Definition at line 142 of file ComputeProperties.c.

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

Referenced by GetPotential(), SatisfyValue(), ValueChUp(), and ValueKnCh().

◆ WirePrimPF()

void WirePrimPF ( int prim,
Point3D * localP,
double * Potential,
Vector3D * localF )

Definition at line 4708 of file ComputeProperties.c.

4709 {
4710 double xpt = localP->X;
4711 double ypt = localP->Y;
4712 double zpt = localP->Z;
4713 double rW = Radius[prim];
4714 double lW = PrimLZ[prim];
4715 double dist = sqrt(xpt * xpt + ypt * ypt + zpt * zpt);
4716
4717 if (dist >= FarField * lW) {
4718 double dA = 2.0 * ST_PI * rW * lW;
4719 (*Potential) = dA / dist;
4720 double f = dA / (dist * dist * dist);
4721 localF->X = xpt * f;
4722 localF->Y = ypt * f;
4723 localF->Z = zpt * f;
4724 } else {
4725 if ((fabs(xpt) < MINDIST) && (fabs(ypt) < MINDIST)) {
4726 if (fabs(zpt) < MINDIST)
4727 (*Potential) = ExactCentroidalP_W(rW, lW);
4728 else
4729 (*Potential) = ExactAxialP_W(rW, lW, zpt);
4730
4731 localF->X = localF->Y = 0.0;
4732 localF->Z = ExactThinFZ_W(rW, lW, xpt, ypt, zpt);
4733 } else {
4734 ExactThinWire(rW, lW, xpt, ypt, zpt, Potential, localF);
4735 }
4736 }
4737} // end of WirePrimPF
neBEMGLOBAL double * Radius
Definition neBEM.h:79

Referenced by GetPrimPF(), and GetPrimPFGCS().

◆ WtFldFastPFAtPoint()

int WtFldFastPFAtPoint ( Point3D * globalP,
double * Potential,
Vector3D * globalF,
int IdWtField )

Definition at line 3980 of file ComputeProperties.c.

3981 {
3982 if (IdWtField >= MAXWtFld) {
3983 printf(
3984 "neBEMPrepareWeightingField: reached MaxWtField (%d) weighting "
3985 "fields.\n",
3986 MAXWtFld);
3987 return -1;
3988 }
3989
3990 int dbgFn = 0;
3991 double Xpt = globalP->X;
3992 double Ypt = globalP->Y;
3993 double Zpt = globalP->Z;
3994 double RptVolLX = WtFldFastVol[IdWtField].LX;
3995 double RptVolLY = WtFldFastVol[IdWtField].LY;
3996 double RptVolLZ = WtFldFastVol[IdWtField].LZ;
3997 double CornerX = WtFldFastVol[IdWtField].CrnrX;
3998 double CornerY = WtFldFastVol[IdWtField].CrnrY;
3999 double CornerZ = WtFldFastVol[IdWtField].CrnrZ;
4000 double TriLin(double xd, double yd, double zd, double c000, double c100,
4001 double c010, double c001, double c110, double c101, double c011,
4002 double c111);
4003
4004 // First of all, check how the point in question should be treated ...
4005
4006 // Check whether the point falls within a volume that is not regarded as
4007 // FastVol
4008 for (int ignore = 1; ignore <= WtFldFastVol[IdWtField].NbIgnoreVols;
4009 ++ignore) {
4010 if ((Xpt >= (WtFldIgnoreVolCrnrX[IdWtField][ignore])) &&
4011 (Xpt <= (WtFldIgnoreVolCrnrX[IdWtField][ignore] +
4012 WtFldIgnoreVolLX[IdWtField][ignore])) &&
4013 (Ypt >= (WtFldIgnoreVolCrnrY[IdWtField][ignore])) &&
4014 (Ypt <= (WtFldIgnoreVolCrnrY[IdWtField][ignore] +
4015 WtFldIgnoreVolLY[IdWtField][ignore])) &&
4016 (Zpt >= (WtFldIgnoreVolCrnrZ[IdWtField][ignore])) &&
4017 (Zpt <= (WtFldIgnoreVolCrnrZ[IdWtField][ignore] +
4018 WtFldIgnoreVolLZ[IdWtField][ignore]))) {
4019 if (dbgFn)
4020 neBEMMessage("In WtFldFastPFAtPoint: point in an ignored volume!\n");
4021
4022 // KnCh does not have any effect
4023 int fstatus = ElePFAtPoint(globalP, Potential, globalF);
4024 if (fstatus != 0) {
4025 neBEMMessage("wrong WtFldPFAtPoint return value in FastVolPF.\n");
4026 return -1;
4027 } else
4028 return 0;
4029 }
4030 } // loop over ignored volumes
4031
4032 // If not ignored, the point qualifies for FastVol evaluation ...
4033
4034 // for a staggered fast volume, the volume repeated in X is larger
4035 if (OptStaggerWtFldFastVol[IdWtField]) {
4036 RptVolLX += WtFldFastVol[IdWtField].LX;
4037 }
4038 if (dbgFn) {
4039 printf("\nin WtFldFastPFAtPoint\n");
4040 printf("x, y, z: %g, %g, %g\n", Xpt, Ypt, Zpt);
4041 printf("RptVolLX, RptVolLY, RptVolLZ: %g, %g, %g\n", RptVolLX, RptVolLY,
4042 RptVolLZ);
4043 printf("CornerX, CornerY, CornerZ: %g, %g, %g\n", CornerX, CornerY,
4044 CornerZ);
4045 printf("Nb of blocks: %d\n", WtFldFastVol[IdWtField].NbBlocks);
4046 for (int block = 1; block <= WtFldFastVol[IdWtField].NbBlocks; ++block) {
4047 printf("NbOfXCells: %d\n", WtFldBlkNbXCells[IdWtField][block]);
4048 printf("NbOfYCells: %d\n", WtFldBlkNbYCells[IdWtField][block]);
4049 printf("NbOfZCells: %d\n", WtFldBlkNbZCells[IdWtField][block]);
4050 printf("LZ: %le\n", WtFldBlkLZ[IdWtField][block]);
4051 printf("CornerZ: %le\n", WtFldBlkCrnrZ[IdWtField][block]);
4052 }
4053 }
4054
4055 // Find equivalent position inside the basic / staggered volume.
4056 // real distance from volume corner
4057 double dx = Xpt - CornerX;
4058 double dy = Ypt - CornerY;
4059 double dz = Zpt - CornerZ;
4060 if (dbgFn)
4061 printf("real dx, dy, dz from volume corner: %g, %g, %g\n", dx, dy, dz);
4062
4063 int NbFastVolX = (int)(dx / RptVolLX);
4064 if (dx < 0.0) --NbFastVolX;
4065 int NbFastVolY = (int)(dy / RptVolLY);
4066 if (dy < 0.0) --NbFastVolY;
4067 int NbFastVolZ = (int)(dz / RptVolLZ);
4068 if (dz < 0.0) --NbFastVolZ;
4069 if (dbgFn)
4070 printf("Volumes in x, y, z: %d, %d, %d\n", NbFastVolX, NbFastVolY,
4071 NbFastVolZ);
4072
4073 // equivalent distances from fast volume corner
4074 dx -= NbFastVolX * RptVolLX;
4075 dy -= NbFastVolY * RptVolLY;
4076 dz -= NbFastVolZ * RptVolLZ;
4077 // The following conditions should never happen - generate an error message
4078 if (dx < 0.0) {
4079 dx = 0.0;
4080 neBEMMessage("equiv dx < 0.0 - not correct!\n");
4081 }
4082 if (dy < 0.0) {
4083 dy = 0.0;
4084 neBEMMessage("equiv dy < 0.0 - not correct!\n");
4085 }
4086 if (dz < 0.0) {
4087 dz = 0.0;
4088 neBEMMessage("equiv dz < 0.0 - not correct!\n");
4089 }
4090 if (dx > RptVolLX) {
4091 dx = RptVolLX;
4092 neBEMMessage("equiv dx > RptVolLX - not correct!\n");
4093 }
4094 if (dy > RptVolLY) {
4095 dy = RptVolLY;
4096 neBEMMessage("equiv dy > RptVolLY - not correct!\n");
4097 }
4098 if (dz > RptVolLZ) {
4099 dz = RptVolLZ;
4100 neBEMMessage("equiv dz > RptVolLZ - not correct!\n");
4101 }
4102 if (dbgFn)
4103 printf("equivalent dist from corner - dx, dy, dz: %g, %g, %g\n", dx, dy,
4104 dz);
4105
4106 // Take care of possible trouble-makers
4107 if (dx < MINDIST) dx = MINDIST; // -ve dx has already been made equal to 0
4108 if (dy < MINDIST) dy = MINDIST;
4109 if (dz < MINDIST) dz = MINDIST;
4110 if ((RptVolLX - dx) < MINDIST)
4111 dx = RptVolLX - MINDIST; // dx > RptVolLX taken care of
4112 if ((RptVolLY - dy) < MINDIST) dy = RptVolLY - MINDIST;
4113 if ((RptVolLZ - dz) < MINDIST) dz = RptVolLZ - MINDIST;
4114 // For staggered volumes, there is another plane where difficulties may occur
4115 if ((dx <= WtFldFastVol[IdWtField].LX) &&
4116 (WtFldFastVol[IdWtField].LX - dx) < MINDIST)
4117 dx = WtFldFastVol[IdWtField].LX - MINDIST;
4118 else if ((dx > WtFldFastVol[IdWtField].LX) &&
4119 (fabs(WtFldFastVol[IdWtField].LX - dx) < MINDIST))
4120 dx = WtFldFastVol[IdWtField].LX + MINDIST;
4121 if (dbgFn)
4122 printf("equivalent dist adjusted - dx, dy, dz: %g, %g, %g\n", dx, dy, dz);
4123
4124 // If volume is staggered, we have a few more things to do before finalizing
4125 // the values of equivalent distance
4126 // sector identification
4127 // _................__________________
4128 // | . . | Sector 3 |
4129 // | . . | |
4130 // | . | . |
4131 // | | . . |
4132 // | Sector 2 | . . |
4133 // |----------------| . . |
4134 // | | . |
4135 // | . | |
4136 // | . . | |
4137 // | . . |----------------|
4138 // | . . | Sector 4 |
4139 // | . | . |
4140 // | | . . |
4141 // | Sector 1 | . . |
4142 // |----------------|................|
4143
4144 int sector = 1; // kept outside `if' since this is necessary further below
4145 if (OptStaggerWtFldFastVol[IdWtField]) {
4146 if ((dx >= 0.0) && (dx <= WtFldFastVol[IdWtField].LX) && (dy >= 0.0) &&
4147 (dy <= WtFldFastVol[IdWtField].LY)) {
4148 // point lies in sector 1, everything remains unchanged
4149 sector = 1;
4150 } else if ((dx >= 0.0) && (dx <= WtFldFastVol[IdWtField].LX) &&
4151 (dy > WtFldFastVol[IdWtField].LY) &&
4152 (dy <= WtFldFastVol[IdWtField].LY +
4153 WtFldFastVol[IdWtField].YStagger)) {
4154 // point lies in sector 2, move basic volume one step up
4155 sector = 2;
4156 ++NbFastVolY;
4157 CornerY += WtFldFastVol[IdWtField].LY; // repeat length in Y is LY
4158 dy -= WtFldFastVol[IdWtField].LY;
4159 } else if ((dx > WtFldFastVol[IdWtField].LX) &&
4160 (dx <= 2.0 * WtFldFastVol[IdWtField].LX) &&
4161 (dy >= WtFldFastVol[IdWtField].YStagger) &&
4162 (dy <= WtFldFastVol[IdWtField].LY +
4163 WtFldFastVol[IdWtField].YStagger)) {
4164 // point lies in sector 3, pt in staggered vol, change corner coords
4165 sector = 3;
4166 CornerX += WtFldFastVol[IdWtField].LX;
4167 CornerY += WtFldFastVol[IdWtField].YStagger;
4168 dx -= WtFldFastVol[IdWtField].LX;
4169 dy -= WtFldFastVol[IdWtField].YStagger;
4170 } else if ((dx > WtFldFastVol[IdWtField].LX) &&
4171 (dx <= 2.0 * WtFldFastVol[IdWtField].LX) && (dy >= 0.0) &&
4172 (dy < WtFldFastVol[IdWtField].YStagger)) {
4173 // point lies in sector 4, move basic volume one step down and consider
4174 // staggered fast volume
4175 sector = 4;
4176 --NbFastVolY;
4177 CornerX += WtFldFastVol[IdWtField]
4178 .LX; // in the staggered part of the repeated volume
4179 CornerY -=
4180 (WtFldFastVol[IdWtField].LY - WtFldFastVol[IdWtField].YStagger);
4181 dx -= WtFldFastVol[IdWtField].LX;
4182 dy += (WtFldFastVol[IdWtField].LY - WtFldFastVol[IdWtField].YStagger);
4183 } else {
4184 neBEMMessage("WtFldFastPFAtPoint: point in none of the sectors!\n");
4185 }
4186 if (dbgFn) printf("stagger modified dx, dy, dz: %g, %g, %g\n", dx, dy, dz);
4187 }
4188
4189 // Take care of possible trouble-makers - once more
4190 if (dx < MINDIST) dx = MINDIST; // -ve dx has already been made equal to 0
4191 if (dy < MINDIST) dy = MINDIST;
4192 if (dz < MINDIST) dz = MINDIST;
4193 if ((RptVolLX - dx) < MINDIST)
4194 dx = RptVolLX - MINDIST; // dx > RptVolLX taken care of
4195 if ((RptVolLY - dy) < MINDIST) dy = RptVolLY - MINDIST;
4196 if ((RptVolLZ - dz) < MINDIST) dz = RptVolLZ - MINDIST;
4197 // For staggered volumes, there is another plane where difficulties may occur
4198 if ((dx <= WtFldFastVol[IdWtField].LX) &&
4199 (WtFldFastVol[IdWtField].LX - dx) < MINDIST)
4200 dx = WtFldFastVol[IdWtField].LX - MINDIST;
4201 else if ((dx > WtFldFastVol[IdWtField].LX) &&
4202 (fabs(WtFldFastVol[IdWtField].LX - dx) < MINDIST))
4203 dx = WtFldFastVol[IdWtField].LX + MINDIST;
4204 if (dbgFn)
4205 printf("equivalent dist adjusted for staggered: %g, %g, %g\n", dx, dy, dz);
4206
4207 // Find the block in which the point lies
4208 int thisBlock = 0;
4209 for (int block = 1; block <= WtFldFastVol[IdWtField].NbBlocks; ++block) {
4210 double blkBtmZ =
4211 WtFldBlkCrnrZ[IdWtField][block] - CornerZ; // since CornerZ has been
4212 double blkTopZ =
4213 blkBtmZ + WtFldBlkLZ[IdWtField][block]; // subtracted from dz already
4214 if (dbgFn) {
4215 printf("block, dz, blkBtmZ, blkTopZ: %d, %lg, %lg, %lg\n", block, dz,
4216 blkBtmZ, blkTopZ);
4217 }
4218
4219 // take care of difficult situations
4220 if ((dz <= blkBtmZ) && ((blkBtmZ - dz) < MINDIST)) dz = blkBtmZ - MINDIST;
4221 if ((dz >= blkBtmZ) && ((dz - blkBtmZ) < MINDIST)) dz = blkBtmZ + MINDIST;
4222 if ((dz <= blkTopZ) && ((blkTopZ - dz) < MINDIST)) dz = blkTopZ - MINDIST;
4223 if ((dz >= blkTopZ) && ((dz - blkTopZ) < MINDIST)) dz = blkTopZ + MINDIST;
4224
4225 if ((dz >= blkBtmZ) && (dz <= blkTopZ)) {
4226 thisBlock = block;
4227 break;
4228 }
4229 }
4230 if (!thisBlock) {
4231 neBEMMessage("WtFldFastPFAtPoint: point in none of the blocks!\n");
4232 }
4233
4234 int nbXCells = WtFldBlkNbXCells[IdWtField][thisBlock];
4235 int nbYCells = WtFldBlkNbYCells[IdWtField][thisBlock];
4236 int nbZCells = WtFldBlkNbZCells[IdWtField][thisBlock];
4237 double delX = WtFldFastVol[IdWtField].LX / nbXCells;
4238 double delY = WtFldFastVol[IdWtField].LY / nbYCells;
4239 double delZ = WtFldBlkLZ[IdWtField][thisBlock] / nbZCells;
4240 dz -= (WtFldBlkCrnrZ[IdWtField][thisBlock] -
4241 CornerZ); // distance from the block corner
4242
4243 if (dbgFn) {
4244 printf("thisBlock: %d\n", thisBlock);
4245 printf("nbXCells, nbYCells, nbZCells: %d, %d, %d\n", nbXCells, nbYCells,
4246 nbZCells);
4247 printf("WtFldBlkCrnrZ: %lg\n", WtFldBlkCrnrZ[IdWtField][thisBlock]);
4248 printf("delX, delY, delZ: %le, %le, %le\n", delX, delY, delZ);
4249 printf("dz: %lg\n", dz);
4250 fflush(stdout);
4251 }
4252
4253 // Find cell in block of basic / staggered volume within which the point lies
4254 int celli = (int)(dx / delX) + 1; // Find cell in which the point lies
4255 if (celli < 1) {
4256 celli = 1;
4257 dx = 0.5 * delX;
4258 neBEMMessage("WtFldFastPFAtPoint - celli < 1\n");
4259 }
4260 if (celli > nbXCells) {
4261 celli = nbXCells;
4262 dx = WtFldFastVol[IdWtField].LX - 0.5 * delX;
4263 neBEMMessage("WtFldFastPFAtPoint - celli > nbXCells\n");
4264 }
4265 int cellj = (int)(dy / delY) + 1;
4266 if (cellj < 1) {
4267 cellj = 1;
4268 dy = 0.5 * delY;
4269 neBEMMessage("WtFldFastPFAtPoint - cellj < 1\n");
4270 }
4271 if (cellj > nbYCells) {
4272 cellj = nbYCells;
4273 dy = WtFldFastVol[IdWtField].LY - 0.5 * delY;
4274 neBEMMessage("WtFldFastPFAtPoint - cellj > nbYCells\n");
4275 }
4276 int cellk = (int)(dz / delZ) + 1;
4277 if (cellk < 1) {
4278 cellk = 1;
4279 dz = 0.5 * delX;
4280 neBEMMessage("WtFldFastPFAtPoint - cellk < 1\n");
4281 }
4282 if (cellk > nbZCells) {
4283 cellk = nbZCells;
4284 dz = WtFldFastVol[IdWtField].LZ - 0.5 * delZ;
4285 neBEMMessage("WtFldFastPFAtPoint - cellk > nbZCells\n");
4286 }
4287 if (dbgFn) printf("Cells in x, y, z: %d, %d, %d\n", celli, cellj, cellk);
4288
4289 // Interpolate potential and field at the point using the corner values of
4290 // of the cell and, if necessary, of the neighbouring cells
4291 // These gradients can also be calculated while computing the potential and
4292 // field at the cells and stored in memory, provided enough memory is
4293 // available
4294
4295 // distances from cell corner
4296 double dxcellcrnr = dx - (double)(celli - 1) * delX;
4297 double dycellcrnr = dy - (double)(cellj - 1) * delY;
4298 double dzcellcrnr = dz - (double)(cellk - 1) * delZ;
4299 if (dbgFn)
4300 printf("cell crnr dx, dy, dz: %g, %g, %g\n", dxcellcrnr, dycellcrnr,
4301 dzcellcrnr);
4302
4303 // normalized distances
4304 double xd = dxcellcrnr / delX; // xd = (x-x0)/(x1-x0)
4305 double yd = dycellcrnr / delY; // etc
4306 double zd = dzcellcrnr / delZ;
4307 if (xd <= 0.0) xd = 0.0;
4308 if (yd <= 0.0) yd = 0.0;
4309 if (zd <= 0.0) zd = 0.0;
4310 if (xd >= 1.0) xd = 1.0;
4311 if (yd >= 1.0) yd = 1.0;
4312 if (zd >= 1.0) zd = 1.0;
4313
4314 // corner values of potential and field
4315 double P000 =
4316 WtFldFastPot[IdWtField][thisBlock][celli][cellj][cellk]; // lowest corner
4317 double FX000 = WtFldFastFX[IdWtField][thisBlock][celli][cellj][cellk];
4318 double FY000 = WtFldFastFY[IdWtField][thisBlock][celli][cellj][cellk];
4319 double FZ000 = WtFldFastFZ[IdWtField][thisBlock][celli][cellj][cellk];
4320 double P100 = WtFldFastPot[IdWtField][thisBlock][celli + 1][cellj][cellk];
4321 double FX100 = WtFldFastFX[IdWtField][thisBlock][celli + 1][cellj][cellk];
4322 double FY100 = WtFldFastFY[IdWtField][thisBlock][celli + 1][cellj][cellk];
4323 double FZ100 = WtFldFastFZ[IdWtField][thisBlock][celli + 1][cellj][cellk];
4324 double P010 = WtFldFastPot[IdWtField][thisBlock][celli][cellj + 1][cellk];
4325 double FX010 = WtFldFastFX[IdWtField][thisBlock][celli][cellj + 1][cellk];
4326 double FY010 = WtFldFastFY[IdWtField][thisBlock][celli][cellj + 1][cellk];
4327 double FZ010 = WtFldFastFZ[IdWtField][thisBlock][celli][cellj + 1][cellk];
4328 double P001 = WtFldFastPot[IdWtField][thisBlock][celli][cellj][cellk + 1];
4329 double FX001 = WtFldFastFX[IdWtField][thisBlock][celli][cellj][cellk + 1];
4330 double FY001 = WtFldFastFY[IdWtField][thisBlock][celli][cellj][cellk + 1];
4331 double FZ001 = WtFldFastFZ[IdWtField][thisBlock][celli][cellj][cellk + 1];
4332 double P110 = WtFldFastPot[IdWtField][thisBlock][celli + 1][cellj + 1][cellk];
4333 double FX110 = WtFldFastFX[IdWtField][thisBlock][celli + 1][cellj + 1][cellk];
4334 double FY110 = WtFldFastFY[IdWtField][thisBlock][celli + 1][cellj + 1][cellk];
4335 double FZ110 = WtFldFastFZ[IdWtField][thisBlock][celli + 1][cellj + 1][cellk];
4336 double P101 = WtFldFastPot[IdWtField][thisBlock][celli + 1][cellj][cellk + 1];
4337 double FX101 = WtFldFastFX[IdWtField][thisBlock][celli + 1][cellj][cellk + 1];
4338 double FY101 = WtFldFastFY[IdWtField][thisBlock][celli + 1][cellj][cellk + 1];
4339 double FZ101 = WtFldFastFZ[IdWtField][thisBlock][celli + 1][cellj][cellk + 1];
4340 double P011 = WtFldFastPot[IdWtField][thisBlock][celli][cellj + 1][cellk + 1];
4341 double FX011 = WtFldFastFX[IdWtField][thisBlock][celli][cellj + 1][cellk + 1];
4342 double FY011 = WtFldFastFY[IdWtField][thisBlock][celli][cellj + 1][cellk + 1];
4343 double FZ011 = WtFldFastFZ[IdWtField][thisBlock][celli][cellj + 1][cellk + 1];
4344 double P111 =
4345 WtFldFastPot[IdWtField][thisBlock][celli + 1][cellj + 1][cellk + 1];
4346 double FX111 =
4347 WtFldFastFX[IdWtField][thisBlock][celli + 1][cellj + 1][cellk + 1];
4348 double FY111 =
4349 WtFldFastFY[IdWtField][thisBlock][celli + 1][cellj + 1][cellk + 1];
4350 double FZ111 =
4351 WtFldFastFZ[IdWtField][thisBlock][celli + 1][cellj + 1][cellk + 1];
4352 if (OptStaggerWtFldFastVol[IdWtField]) {
4353 if (sector == 1) { // nothing to be done
4354 }
4355 if (sector == 2) { // volume shifted up but point not in the staggered part
4356 }
4357 if (sector == 3) { // staggered volume
4358 P000 = StgWtFldFastPot[IdWtField][thisBlock][celli][cellj][cellk];
4359 FX000 = StgWtFldFastFX[IdWtField][thisBlock][celli][cellj][cellk];
4360 FY000 = StgWtFldFastFY[IdWtField][thisBlock][celli][cellj][cellk];
4361 FZ000 = StgWtFldFastFZ[IdWtField][thisBlock][celli][cellj][cellk];
4362 P100 = StgWtFldFastPot[IdWtField][thisBlock][celli + 1][cellj][cellk];
4363 FX100 = StgWtFldFastFX[IdWtField][thisBlock][celli + 1][cellj][cellk];
4364 FY100 = StgWtFldFastFY[IdWtField][thisBlock][celli + 1][cellj][cellk];
4365 FZ100 = StgWtFldFastFZ[IdWtField][thisBlock][celli + 1][cellj][cellk];
4366 P010 = StgWtFldFastPot[IdWtField][thisBlock][celli][cellj + 1][cellk];
4367 FX010 = StgWtFldFastFX[IdWtField][thisBlock][celli][cellj + 1][cellk];
4368 FY010 = StgWtFldFastFY[IdWtField][thisBlock][celli][cellj + 1][cellk];
4369 FZ010 = StgWtFldFastFZ[IdWtField][thisBlock][celli][cellj + 1][cellk];
4370 P001 = StgWtFldFastPot[IdWtField][thisBlock][celli][cellj][cellk + 1];
4371 FX001 = StgWtFldFastFX[IdWtField][thisBlock][celli][cellj][cellk + 1];
4372 FY001 = StgWtFldFastFY[IdWtField][thisBlock][celli][cellj][cellk + 1];
4373 FZ001 = StgWtFldFastFZ[IdWtField][thisBlock][celli][cellj][cellk + 1];
4374 P110 = StgWtFldFastPot[IdWtField][thisBlock][celli + 1][cellj + 1][cellk];
4375 FX110 = StgWtFldFastFX[IdWtField][thisBlock][celli + 1][cellj + 1][cellk];
4376 FY110 = StgWtFldFastFY[IdWtField][thisBlock][celli + 1][cellj + 1][cellk];
4377 FZ110 = StgWtFldFastFZ[IdWtField][thisBlock][celli + 1][cellj + 1][cellk];
4378 P101 = StgWtFldFastPot[IdWtField][thisBlock][celli + 1][cellj][cellk + 1];
4379 FX101 = StgWtFldFastFX[IdWtField][thisBlock][celli + 1][cellj][cellk + 1];
4380 FY101 = StgWtFldFastFY[IdWtField][thisBlock][celli + 1][cellj][cellk + 1];
4381 FZ101 = StgWtFldFastFZ[IdWtField][thisBlock][celli + 1][cellj][cellk + 1];
4382 P011 = StgWtFldFastPot[IdWtField][thisBlock][celli][cellj + 1][cellk + 1];
4383 FX011 = StgWtFldFastFX[IdWtField][thisBlock][celli][cellj + 1][cellk + 1];
4384 FY011 = StgWtFldFastFY[IdWtField][thisBlock][celli][cellj + 1][cellk + 1];
4385 FZ011 = StgWtFldFastFZ[IdWtField][thisBlock][celli][cellj + 1][cellk + 1];
4386 P111 = StgWtFldFastPot[IdWtField][thisBlock][celli + 1][cellj + 1]
4387 [cellk + 1];
4388 FX111 =
4389 StgWtFldFastFX[IdWtField][thisBlock][celli + 1][cellj + 1][cellk + 1];
4390 FY111 =
4391 StgWtFldFastFY[IdWtField][thisBlock][celli + 1][cellj + 1][cellk + 1];
4392 FZ111 =
4393 StgWtFldFastFZ[IdWtField][thisBlock][celli + 1][cellj + 1][cellk + 1];
4394 }
4395 if (sector == 4) { // volume shifted down and point in the staggered part
4396 P000 = StgWtFldFastPot[IdWtField][thisBlock][celli][cellj][cellk];
4397 FX000 = StgWtFldFastFX[IdWtField][thisBlock][celli][cellj][cellk];
4398 FY000 = StgWtFldFastFY[IdWtField][thisBlock][celli][cellj][cellk];
4399 FZ000 = StgWtFldFastFZ[IdWtField][thisBlock][celli][cellj][cellk];
4400 P100 = StgWtFldFastPot[IdWtField][thisBlock][celli + 1][cellj][cellk];
4401 FX100 = StgWtFldFastFX[IdWtField][thisBlock][celli + 1][cellj][cellk];
4402 FY100 = StgWtFldFastFY[IdWtField][thisBlock][celli + 1][cellj][cellk];
4403 FZ100 = StgWtFldFastFZ[IdWtField][thisBlock][celli + 1][cellj][cellk];
4404 P010 = StgWtFldFastPot[IdWtField][thisBlock][celli][cellj + 1][cellk];
4405 FX010 = StgWtFldFastFX[IdWtField][thisBlock][celli][cellj + 1][cellk];
4406 FY010 = StgWtFldFastFY[IdWtField][thisBlock][celli][cellj + 1][cellk];
4407 FZ010 = StgWtFldFastFZ[IdWtField][thisBlock][celli][cellj + 1][cellk];
4408 P001 = StgWtFldFastPot[IdWtField][thisBlock][celli][cellj][cellk + 1];
4409 FX001 = StgWtFldFastFX[IdWtField][thisBlock][celli][cellj][cellk + 1];
4410 FY001 = StgWtFldFastFY[IdWtField][thisBlock][celli][cellj][cellk + 1];
4411 FZ001 = StgWtFldFastFZ[IdWtField][thisBlock][celli][cellj][cellk + 1];
4412 P110 = StgWtFldFastPot[IdWtField][thisBlock][celli + 1][cellj + 1][cellk];
4413 FX110 = StgWtFldFastFX[IdWtField][thisBlock][celli + 1][cellj + 1][cellk];
4414 FY110 = StgWtFldFastFY[IdWtField][thisBlock][celli + 1][cellj + 1][cellk];
4415 FZ110 = StgWtFldFastFZ[IdWtField][thisBlock][celli + 1][cellj + 1][cellk];
4416 P101 = StgWtFldFastPot[IdWtField][thisBlock][celli + 1][cellj][cellk + 1];
4417 FX101 = StgWtFldFastFX[IdWtField][thisBlock][celli + 1][cellj][cellk + 1];
4418 FY101 = StgWtFldFastFY[IdWtField][thisBlock][celli + 1][cellj][cellk + 1];
4419 FZ101 = StgWtFldFastFZ[IdWtField][thisBlock][celli + 1][cellj][cellk + 1];
4420 P011 = StgWtFldFastPot[IdWtField][thisBlock][celli][cellj + 1][cellk + 1];
4421 FX011 = StgWtFldFastFX[IdWtField][thisBlock][celli][cellj + 1][cellk + 1];
4422 FY011 = StgWtFldFastFY[IdWtField][thisBlock][celli][cellj + 1][cellk + 1];
4423 FZ011 = StgWtFldFastFZ[IdWtField][thisBlock][celli][cellj + 1][cellk + 1];
4424 P111 = StgWtFldFastPot[IdWtField][thisBlock][celli + 1][cellj + 1]
4425 [cellk + 1];
4426 FX111 =
4427 StgWtFldFastFX[IdWtField][thisBlock][celli + 1][cellj + 1][cellk + 1];
4428 FY111 =
4429 StgWtFldFastFY[IdWtField][thisBlock][celli + 1][cellj + 1][cellk + 1];
4430 FZ111 =
4431 StgWtFldFastFZ[IdWtField][thisBlock][celli + 1][cellj + 1][cellk + 1];
4432 }
4433 }
4434
4435 double intP =
4436 TriLin(xd, yd, zd, P000, P100, P010, P001, P110, P101, P011, P111);
4437 double intFX = TriLin(xd, yd, zd, FX000, FX100, FX010, FX001, FX110, FX101,
4438 FX011, FX111);
4439 double intFY = TriLin(xd, yd, zd, FY000, FY100, FY010, FY001, FY110, FY101,
4440 FY011, FY111);
4441 double intFZ = TriLin(xd, yd, zd, FZ000, FZ100, FZ010, FZ001, FZ110, FZ101,
4442 FZ011, FZ111);
4443
4444 *Potential = intP;
4445 globalF->X = intFX;
4446 globalF->Y = intFY;
4447 globalF->Z = intFZ;
4448
4449 if (dbgFn) {
4450 printf("WtFldCell corner values:\n");
4451 printf("Potential: %g, %g, %g, %g\n", P000, P100, P010, P001);
4452 printf("Potential: %g, %g, %g, %g\n", P110, P101, P011, P111);
4453 printf("FastFX: %g, %g, %g, %g\n", FX000, FX100, FX010, FX001);
4454 printf("FastFX: %g, %g, %g, %g\n", FX110, FX101, FX011, FX111);
4455 printf("FastFY: %g, %g, %g, %g\n", FY000, FY100, FY010, FY001);
4456 printf("FastFY: %g, %g, %g, %g\n", FY110, FY101, FY011, FY111);
4457 printf("FastFZ: %g, %g, %g, %g\n", FZ000, FZ100, FZ010, FZ001);
4458 printf("FastFZ: %g, %g, %g, %g\n", FZ110, FZ101, FZ011, FZ111);
4459 printf("Pot, FX, FY, FZ: %g, %g, %g, %g\n", *Potential, globalF->X,
4460 globalF->Y, globalF->Z);
4461 }
4462
4463 if (dbgFn) {
4464 printf("out WtFldFastPFAtPoint\n");
4465 fflush(stdout);
4466 }
4467
4468 return 0;
4469} // WtFldFastPFAtPoint ends
neBEMGLOBAL double * WtFldIgnoreVolCrnrZ[MAXWtFld]
Definition neBEM.h:531
neBEMGLOBAL double * WtFldIgnoreVolCrnrY[MAXWtFld]
Definition neBEM.h:530
neBEMGLOBAL double * WtFldIgnoreVolCrnrX[MAXWtFld]
Definition neBEM.h:529
neBEMGLOBAL double * WtFldIgnoreVolLY[MAXWtFld]
Definition neBEM.h:527
neBEMGLOBAL double * WtFldIgnoreVolLZ[MAXWtFld]
Definition neBEM.h:528
neBEMGLOBAL double * WtFldIgnoreVolLX[MAXWtFld]
Definition neBEM.h:526

Referenced by neBEMWeightingField().

◆ WtFldPFAtPoint()

int WtFldPFAtPoint ( Point3D * globalP,
double * Potential,
Vector3D * globalF,
int IdWtField )

Definition at line 3085 of file ComputeProperties.c.

3086 {
3087 int dbgFn = 0;
3088
3089 const double xfld = globalP->X;
3090 const double yfld = globalP->Y;
3091 const double zfld = globalP->Z;
3092
3093 // Compute Potential and field at different locations
3094 *Potential = globalF->X = globalF->Y = globalF->Z = 0.0;
3095
3096 // Effects due to base primitives and their repetitions are considered in the
3097 // local coordinate system of the primitive (or element), while effects due to
3098 // mirror elements and their repetitions are considered in the global
3099 // coordinate system (GCS). This works because the direction cosines of a
3100 // primitive (and its elements) and those of its repetitions are the same.
3101 // As a result, we can do just one transformation from local to global at the
3102 // end of calculations related to a primitive. This can save substantial
3103 // computation if a discretized version of the primitive is being used since
3104 // we avoid one unnecessary transformation for each element that comprises a
3105 // primitive.
3106 // Begin with primitive description of the device
3107
3108 // Scope in OpenMP: Variables in the global data space are accessible to all
3109 // threads, while variables in a thread's private space is accessible to the
3110 // thread only (there are several variations - copying outside region etc)
3111 // Field point remains the same - kept outside private
3112 // source point changes with change in primitive - private
3113 // TransformationMatrix changes - kept within private (Note: matrices with
3114 // fixed dimensions can be maintained, but those with dynamic allocation
3115 // can not).
3116 double *pPot = dvector(1, NbPrimitives);
3117 double *plFx = dvector(1, NbPrimitives); // field components in LCS
3118 double *plFy = dvector(1, NbPrimitives); // for a primitive
3119 double *plFz = dvector(1, NbPrimitives); // and its other incarnations
3120
3121 for (int prim = 1; prim <= NbPrimitives; ++prim) {
3122 pPot[prim] = plFx[prim] = plFy[prim] = plFz[prim] = 0.0;
3123 }
3124
3125#ifdef _OPENMP
3126 int tid = 0, nthreads = 1;
3127#pragma omp parallel private(tid, nthreads)
3128#endif
3129 {
3130#ifdef _OPENMP
3131 if (dbgFn) {
3132 tid = omp_get_thread_num();
3133 if (tid == 0) {
3134 nthreads = omp_get_num_threads();
3135 printf("PFAtPoint computation with %d threads\n", nthreads);
3136 }
3137 }
3138#endif
3139// by default, nested parallelization is off in C
3140#ifdef _OPENMP
3141#pragma omp for
3142#endif
3143 for (int primsrc = 1; primsrc <= NbPrimitives; ++primsrc) {
3144 if (dbgFn) {
3145 printf("Evaluating effect of primsrc %d using on %lg, %lg, %lg\n",
3146 primsrc, xfld, yfld, zfld);
3147 fflush(stdout);
3148 }
3149
3150 const double xpsrc = PrimOriginX[primsrc];
3151 const double ypsrc = PrimOriginY[primsrc];
3152 const double zpsrc = PrimOriginZ[primsrc];
3153
3154 // Field in the local frame.
3155 double lFx = 0.;
3156 double lFy = 0.;
3157 double lFz = 0.;
3158
3159 // Set up transform matrix for this primitive, which is also the same
3160 // for all the elements belonging to this primitive.
3161 double TransformationMatrix[3][3];
3162 TransformationMatrix[0][0] = PrimDC[primsrc].XUnit.X;
3163 TransformationMatrix[0][1] = PrimDC[primsrc].XUnit.Y;
3164 TransformationMatrix[0][2] = PrimDC[primsrc].XUnit.Z;
3165 TransformationMatrix[1][0] = PrimDC[primsrc].YUnit.X;
3166 TransformationMatrix[1][1] = PrimDC[primsrc].YUnit.Y;
3167 TransformationMatrix[1][2] = PrimDC[primsrc].YUnit.Z;
3168 TransformationMatrix[2][0] = PrimDC[primsrc].ZUnit.X;
3169 TransformationMatrix[2][1] = PrimDC[primsrc].ZUnit.Y;
3170 TransformationMatrix[2][2] = PrimDC[primsrc].ZUnit.Z;
3171
3172 // The total influence is due to primitives on the basic device and due to
3173 // virtual primitives arising out of repetition, reflection etc and not
3174 // residing on the basic device
3175
3176 { // basic primitive
3177 // point translated to the ECS origin, but axes direction global
3178 Point3D localPP;
3179 { // Rotate point from global to local system
3180 double InitialVector[3] = {xfld - xpsrc, yfld - ypsrc, zfld - zpsrc};
3181 double FinalVector[3] = {0., 0., 0.};
3182 for (int i = 0; i < 3; ++i) {
3183 for (int j = 0; j < 3; ++j) {
3184 FinalVector[i] += TransformationMatrix[i][j] * InitialVector[j];
3185 }
3186 }
3187 localPP.X = FinalVector[0];
3188 localPP.Y = FinalVector[1];
3189 localPP.Z = FinalVector[2];
3190 } // Point3D rotated
3191
3192 // evaluate possibility whether primitive influence is accurate enough
3193 // This could be based on localPP and the subtended solid angle
3194 // If 1, then only primitive influence will be considered
3195 int PrimOK = 0;
3196 // consider primitive representation accurate enough if it is
3197 // repeated and beyond WtFldPrimAfter repetitions.
3198 if (WtFldPrimAfter < 0) { // If WtFldPrimAfter <0, PrimOK is zero
3199 PrimOK = 0;
3200 } else if (WtFldPrimAfter == 0) { // only this is necessary
3201 PrimOK = 1;
3202 } else if (WtFldPrimAfter > 0) {
3203 PrimOK = 1;
3204 }
3205 if (PrimOK) {
3206 // Potential and flux (local system) due to base primitive
3207 double tmpPot;
3208 Vector3D tmpF;
3209 GetPrimPF(primsrc, &localPP, &tmpPot, &tmpF);
3210 const double qpr = AvWtChDen[IdWtField][primsrc];
3211 pPot[primsrc] += qpr * tmpPot;
3212 lFx += qpr * tmpF.X;
3213 lFy += qpr * tmpF.Y;
3214 lFz += qpr * tmpF.Z;
3215 // if(DebugLevel == 301)
3216 if (dbgFn) {
3217 printf("PFAtPoint base primitive =>\n");
3218 printf("primsrc: %d, xlocal: %lg, ylocal: %lg, zlocal %lg\n",
3219 primsrc, localPP.X, localPP.Y, localPP.Z);
3220 printf("primsrc: %d, Pot: %lg, Fx: %lg, Fx: %lg, Fz: %lg\n",
3221 primsrc, tmpPot, tmpF.X, tmpF.Y, tmpF.Z);
3222 printf("primsrc: %d, pPot: %lg, lFx: %lg, lFy: %lg, lFz: %lg\n",
3223 primsrc, pPot[primsrc], lFx, lFy, lFz);
3224 fflush(stdout);
3225 // exit(-1);
3226 }
3227 } else {
3228 // element influence
3229 double tPot;
3230 Vector3D tF;
3231 double ePot = 0.;
3232 Vector3D eF;
3233 eF.X = 0.0;
3234 eF.Y = 0.0;
3235 eF.Z = 0.0;
3236
3237 const int eleMin = ElementBgn[primsrc];
3238 const int eleMax = ElementEnd[primsrc];
3239 for (int ele = eleMin; ele <= eleMax; ++ele) {
3240 const double xsrc = (EleArr + ele - 1)->G.Origin.X;
3241 const double ysrc = (EleArr + ele - 1)->G.Origin.Y;
3242 const double zsrc = (EleArr + ele - 1)->G.Origin.Z;
3243 // Rotate vector from global to local system; matrix as for
3244 // primitive
3245 double vG[3] = {xfld - xsrc, yfld - ysrc, zfld - zsrc};
3246 double vL[3] = {0., 0., 0.};
3247 for (int i = 0; i < 3; ++i) {
3248 for (int j = 0; j < 3; ++j) {
3249 vL[i] += TransformationMatrix[i][j] * vG[j];
3250 }
3251 }
3252 // Potential and flux (local system) due to base primitive
3253 const int type = (EleArr + ele - 1)->G.Type;
3254 const double a = (EleArr + ele - 1)->G.LX;
3255 const double b = (EleArr + ele - 1)->G.LZ;
3256 GetPF(type, a, b, vL[0], vL[1], vL[2], &tPot, &tF);
3257 const double qel = WtFieldChDen[IdWtField][ele];
3258 ePot += qel * tPot;
3259 eF.X += qel * tF.X;
3260 eF.Y += qel * tF.Y;
3261 eF.Z += qel * tF.Z;
3262 // if(DebugLevel == 301)
3263 if (dbgFn) {
3264 printf("PFAtPoint base primitive:%d\n", primsrc);
3265 printf("ele: %d, xlocal: %lg, ylocal: %lg, zlocal %lg\n", ele,
3266 vL[0], vL[1], vL[2]);
3267 printf(
3268 "ele: %d, tPot: %lg, tFx: %lg, tFy: %lg, tFz: %lg, Solution: "
3269 "%g\n",
3270 ele, tPot, tF.X, tF.Y, tF.Z, qel);
3271 printf("ele: %d, ePot: %lg, eFx: %lg, eFy: %lg, eFz: %lg\n", ele,
3272 ePot, eF.X, eF.Y, eF.Z);
3273 fflush(stdout);
3274 }
3275 } // for all the elements on this primsrc primitive
3276
3277 pPot[primsrc] += ePot;
3278 lFx += eF.X;
3279 lFy += eF.Y;
3280 lFz += eF.Z;
3281 if (dbgFn) {
3282 printf("prim%d, ePot: %lg, eFx: %lg, eFy: %lg, eFz: %lg\n", primsrc,
3283 ePot, eF.X, eF.Y, eF.Z);
3284 printf("prim%d, pPot: %lg, lFx: %lg, lFy: %lg, lFz: %lg\n", primsrc,
3285 pPot[primsrc], lFx, lFy, lFz);
3286 fflush(stdout);
3287 }
3288 } // else elements influence
3289
3290 // if(DebugLevel == 301)
3291 if (dbgFn) {
3292 printf("basic primtive\n");
3293 printf("primsrc: %d, pPot: %lg, lFx: %lg, lFy: %lg, lFz: %lg\n",
3294 primsrc, pPot[primsrc], lFx, lFy, lFz);
3295 fflush(stdout);
3296 }
3297 } // basic primitive ends
3298
3299 if (MirrorTypeX[primsrc] || MirrorTypeY[primsrc] ||
3300 MirrorTypeZ[primsrc]) { // Mirror effect of base primitives
3301 printf("Mirror may not be correctly implemented ...\n");
3302 exit(0);
3303 } // Mirror effect ends
3304
3305 // Flux due to repeated primitives
3306 if ((PeriodicTypeX[primsrc] == 1) || (PeriodicTypeY[primsrc] == 1) ||
3307 (PeriodicTypeZ[primsrc] == 1)) {
3308 const int perx = PeriodicInX[primsrc];
3309 const int pery = PeriodicInY[primsrc];
3310 const int perz = PeriodicInZ[primsrc];
3311 if (perx || pery || perz) {
3312 for (int xrpt = -perx; xrpt <= perx; ++xrpt) {
3313 const double xShift = XPeriod[primsrc] * (double)xrpt;
3314 double XPOfRpt = xpsrc + xShift;
3315 for (int yrpt = -pery; yrpt <= pery; ++yrpt) {
3316 const double yShift = YPeriod[primsrc] * (double)yrpt;
3317 double YPOfRpt = ypsrc + yShift;
3318 for (int zrpt = -perz; zrpt <= perz; ++zrpt) {
3319 const double zShift = ZPeriod[primsrc] * (double)zrpt;
3320 double ZPOfRpt = zpsrc + zShift;
3321 // Skip the base device.
3322 if ((xrpt == 0) && (yrpt == 0) && (zrpt == 0)) continue;
3323 { // basic primitive repeated
3324 Point3D localPPR;
3325 { // Rotate point from global to local system
3326 double InitialVector[3] = {xfld - XPOfRpt, yfld - YPOfRpt,
3327 zfld - ZPOfRpt};
3328 double FinalVector[3] = {0., 0., 0.};
3329 for (int i = 0; i < 3; ++i) {
3330 for (int j = 0; j < 3; ++j) {
3331 FinalVector[i] +=
3332 TransformationMatrix[i][j] * InitialVector[j];
3333 }
3334 }
3335 localPPR.X = FinalVector[0];
3336 localPPR.Y = FinalVector[1];
3337 localPPR.Z = FinalVector[2];
3338 } // Point3D rotated
3339
3340 int repPrimOK = 0;
3341
3342 // consider primitive representation accurate enough if it is
3343 // repeated and beyond WtFldPrimAfter repetitions.
3344 if (WtFldPrimAfter < 0) {//WtFldPrimAfter <0 => repPrimOK = 0
3345 repPrimOK = 0;
3346 } else if ((abs(xrpt) >= WtFldPrimAfter) &&
3347 (abs(yrpt) >= WtFldPrimAfter)) {
3348 repPrimOK = 1;
3349 }
3350 // enforce primitive representation since it is unlikely
3351 // that the weighting field will be modified much due to
3352 // such an approximation for the repeated primitives.
3353 if (repPrimOK) { // use primitive representation
3354 // Potential and flux (local system) due to repeated
3355 // primitive
3356 double tmpPot;
3357 Vector3D tmpF;
3358 GetPrimPF(primsrc, &localPPR, &tmpPot, &tmpF);
3359 const double qpr = AvWtChDen[IdWtField][primsrc];
3360 pPot[primsrc] += qpr * tmpPot;
3361 lFx += qpr * tmpF.X;
3362 lFy += qpr * tmpF.Y;
3363 lFz += qpr * tmpF.Z;
3364 // if(DebugLevel == 301)
3365 if (dbgFn) {
3366 printf(
3367 "primsrc: %d, xlocal: %lg, ylocal: %lg, zlocal: "
3368 "%lg\n",
3369 primsrc, localPPR.X, localPPR.Y, localPPR.Z);
3370 printf(
3371 "primsrc: %d, Pot: %lg, Fx: %lg, Fy: %lg, Fz: %lg\n",
3372 primsrc, tmpPot * qpr, tmpF.X * qpr, tmpF.Y * qpr,
3373 tmpF.Z * qpr);
3374 printf(
3375 "primsrc: %d, pPot: %lg, lFx: %lg, lFy: %lg, lFz: "
3376 "%lg\n",
3377 primsrc, pPot[primsrc], lFx, lFy, lFz);
3378 fflush(stdout);
3379 }
3380 } else {
3381 // use discretized representation of a repeated primitive
3382 double tPot;
3383 Vector3D tF;
3384 double erPot = 0.;
3385 Vector3D erF;
3386 erF.X = 0.0;
3387 erF.Y = 0.0;
3388 erF.Z = 0.0;
3389
3390 const int eleMin = ElementBgn[primsrc];
3391 const int eleMax = ElementEnd[primsrc];
3392 for (int ele = eleMin; ele <= eleMax; ++ele) {
3393 const double xrsrc = (EleArr + ele - 1)->G.Origin.X;
3394 const double yrsrc = (EleArr + ele - 1)->G.Origin.Y;
3395 const double zrsrc = (EleArr + ele - 1)->G.Origin.Z;
3396
3397 const double XEOfRpt = xrsrc + xShift;
3398 const double YEOfRpt = yrsrc + yShift;
3399 const double ZEOfRpt = zrsrc + zShift;
3400
3401 // Rotate point from global to local system.
3402 double vG[3] = {xfld - XEOfRpt, yfld - YEOfRpt,
3403 zfld - ZEOfRpt};
3404 double vL[3] = {0., 0., 0.};
3405 for (int i = 0; i < 3; ++i) {
3406 for (int j = 0; j < 3; ++j) {
3407 vL[i] += TransformationMatrix[i][j] * vG[j];
3408 }
3409 }
3410 // Allowed, because all the local coordinates have the
3411 // same orientations. Only the origins are mutually
3412 // displaced along a line.
3413 const int type = (EleArr + ele - 1)->G.Type;
3414 const double a = (EleArr + ele - 1)->G.LX;
3415 const double b = (EleArr + ele - 1)->G.LZ;
3416 GetPF(type, a, b, vL[0], vL[1], vL[2], &tPot, &tF);
3417 const double qel = WtFieldChDen[IdWtField][ele];
3418 erPot += qel * tPot;
3419 erF.X += qel * tF.X;
3420 erF.Y += qel * tF.Y;
3421 erF.Z += qel * tF.Z;
3422 // if(DebugLevel == 301)
3423 if (dbgFn) {
3424 printf("PFAtPoint base primitive:%d\n", primsrc);
3425 printf(
3426 "ele: %d, xlocal: %lg, ylocal: %lg, zlocal %lg\n",
3427 ele, vL[0], vL[1], vL[2]);
3428 printf(
3429 "ele: %d, tPot: %lg, tFx: %lg, tFy: %lg, tFz: %lg, "
3430 "Solution: %g\n",
3431 ele, tPot, tF.X, tF.Y, tF.Z, qel);
3432 printf(
3433 "ele: %d, ePot: %lg, eFx: %lg, eFy: %lg, eFz: "
3434 "%lg\n",
3435 ele, erPot, erF.X, erF.Y, erF.Z);
3436 fflush(stdout);
3437 }
3438 } // for all the elements on this primsrc repeated
3439 // primitive
3440
3441 pPot[primsrc] += erPot;
3442 lFx += erF.X;
3443 lFy += erF.Y;
3444 lFz += erF.Z;
3445 } // else discretized representation of this primitive
3446
3447 // if(DebugLevel == 301)
3448 if (dbgFn) {
3449 printf("basic repeated xrpt: %d. yrpt: %d, zrpt: %d\n",
3450 xrpt, yrpt, zrpt);
3451 printf(
3452 "primsrc: %d, pPot: %lg, lFx: %lg, lFy: %lg, lFz: "
3453 "%lg\n",
3454 primsrc, pPot[primsrc], lFx, lFy, lFz);
3455 fflush(stdout);
3456 }
3457 } // repetition of basic primitive
3458
3459 if (MirrorTypeX[primsrc] || MirrorTypeY[primsrc] ||
3460 MirrorTypeZ[primsrc]) {
3461 // Mirror effect of repeated primitives - not parallelized
3462 printf(
3463 "Mirror not correctly implemented in this version of "
3464 "neBEM ...\n");
3465 exit(0);
3466 } // Mirror effect for repeated primitives ends
3467
3468 } // for zrpt
3469 } // for yrpt
3470 } // for xrpt
3471 } // PeriodicInX || PeriodicInY || PeriodicInZ
3472 } // PeriodicType == 1
3473 Vector3D localF;
3474 localF.X = lFx;
3475 localF.Y = lFy;
3476 localF.Z = lFz;
3477 Vector3D tmpF = RotateVector3D(&localF, &PrimDC[primsrc], local2global);
3478 plFx[primsrc] = tmpF.X; // local fluxes lFx, lFy, lFz in GCS
3479 plFy[primsrc] = tmpF.Y;
3480 plFz[primsrc] = tmpF.Z;
3481 } // for all primitives: basic device, mirror reflections and repetitions
3482 } // pragma omp parallel
3483
3484 double totPot = 0.0;
3485 Vector3D totF;
3486 totF.X = totF.Y = totF.Z = 0.0;
3487 for (int prim = 1; prim <= NbPrimitives; ++prim) {
3488 totPot += pPot[prim];
3489 totF.X += plFx[prim];
3490 totF.Y += plFy[prim];
3491 totF.Z += plFz[prim];
3492 }
3493
3494 // This should be done at the end of the function - before freeing memory
3495#ifdef __cplusplus
3496 *Potential = totPot * InvFourPiEps0;
3497 globalF->X = totF.X * InvFourPiEps0;
3498 globalF->Y = totF.Y * InvFourPiEps0;
3499 globalF->Z = totF.Z * InvFourPiEps0;
3500#else
3501 *Potential = totPot / MyFACTOR;
3502 globalF->X = totF.X / MyFACTOR;
3503 globalF->Y = totF.Y / MyFACTOR;
3504 globalF->Z = totF.Z / MyFACTOR;
3505#endif
3506
3507 if (OptSystemChargeZero) {
3508 // Respect total system charge constraint.
3509 (*Potential) += WtFieldChDen[IdWtField][NbSystemChargeZero];
3510 }
3511
3512 /*
3513 For weighting field, effect of KnCh is possibly zero.
3514 Similarly, there is no reason to respect constraint on total system charge.
3515 */
3516
3517 if (dbgFn) {
3518 printf("Final values due to all primitives and other influences: ");
3519 // printf("xfld\tyfld\tzfld\tPot\tFx\tFy\tFz\n"); // refer, do not
3520 // uncomment
3521 printf("%lg\t%lg\t%lg\t%lg\t%lg\t%lg\t%lg\n\n", xfld, yfld, zfld,
3522 (*Potential), globalF->X, globalF->Y, globalF->Z);
3523 fflush(stdout);
3524 }
3525
3526 free_dvector(pPot, 1, NbPrimitives);
3527 free_dvector(plFx, 1, NbPrimitives);
3528 free_dvector(plFy, 1, NbPrimitives);
3529 free_dvector(plFz, 1, NbPrimitives);
3530
3531 return (0);
3532} // end of WtFldPFAtPoint
neBEMGLOBAL int WtFldPrimAfter
Definition neBEM.h:365
neBEMGLOBAL int OptSystemChargeZero
Definition neBEM.h:125
neBEMGLOBAL double ** AvWtChDen
Definition neBEM.h:346
neBEMGLOBAL double ** WtFieldChDen
Definition neBEM.h:346
neBEMGLOBAL int NbSystemChargeZero
Definition neBEM.h:127

Referenced by CreateWtFldFastVolPF(), and neBEMWeightingField().