#include #include #include #include #include #include #include #include #include #include #include #include #include "global.h" #include "proc.h" #include "Constants.h" #include "float_regcvtr.h" #include "group.h" #include "MultiLevelSVD.h" #include "n2f_dd.h" #include "transform.h" #include "integral.h" using namespace std; // global variables // command line parameters double const static ZERO_7 = 1.e-7; vtr O; double unitConv; tri3d **groupTriArray; regcvtr *groupRegJ, *groupRegM; fftwf_complex *workspace, *field, *out; fftwf_complex *tmp_x, *tmp_y, *tmp_z; cVtr *Epart; double MagE( Complex eTheta, Complex ePhi ) { double mag = norm(eTheta) + norm(ePhi); return sqrt(mag); } int main(int argc, char *argv[]) { tms tmsStart, tmsEnd; times(&tmsStart); int i, j; int numTheta, numPhi, OPT = 1; char prjName[180]; double freq; // Read in input parameters if ( argc == 8 ) { strcpy( prjName, argv[1] ); freq = atof( argv[2] ); O.setvtr( atof(argv[3]), atof(argv[4]), atof(argv[5]) ); numTheta = atoi( argv[6] ); numPhi = atoi( argv[7] ); } else if ( argc == 9 ) { strcpy( prjName, argv[1] ); freq = atof( argv[2] ); O.setvtr( atof(argv[3]), atof(argv[4]), atof(argv[5]) ); numTheta = atoi( argv[6] ); numPhi = atoi( argv[7] ); OPT = atoi(argv[8]); } else { cout << "Input Project Name: "; cin >> prjName; cout << "Input Frequency (in MHz): "; cin >> freq; double Ox, Oy, Oz; cout << "Input Coordinate System Center X (meters): "; cin >> Ox; cout << "Input Coordinate System Center Y (meters): "; cin >> Oy; cout << "Input Coordinate System Center Z (meters): "; cin >> Oz; O.setvtr( Ox, Oy, Oz ); cout << "Input Number of Sample Points along Theta: "; cin >> numTheta; cout << "Input Number of Sample Points along Phi: "; cin >> numPhi; cout << "Option for file format: 0(magnitude), 1(real and imaginary) "; cin >> OPT; } // scattering int n; double EincMag; double theta, phi, thetaInc, phiInc, theta_in_rad, phi_in_rad; cVtr Einc, Hinc, einc, hinc; vtr k; double ko = TwoPi * freq * MEGA / Vo; double deltaTheta = 180.0 / double(numTheta); double deltaPhi = 360.0 / double(numPhi); Complex eTheta[numTheta + 1][numPhi + 1], ePhi[numTheta + 1][numPhi + 1]; vtr thetaVtr, phiVtr; int regions = 0, *FEM; ReadRegions(prjName, &FEM, regions); bool Pec[regions]; for (i = 0; i < regions; i ++) { Pec[i] = false; if (FEM[i] == 0 || FEM[i] == 2) Pec[i] = true; } // read tri and currents int numAbcTri[regions]; tri3d ***abcTriArray = new tri3d **[regions]; regcvtr **regJ = new regcvtr *[regions], **regM = new regcvtr *[regions]; char grpName[180], meshName[180], JcurName[180], McurName[180]; int np; for (i = 0; i < regions; i ++) { if (i == 0) sprintf(grpName, "%s", prjName); else sprintf(grpName, "%s%d", prjName, i); np = 6; if (FEM[i] != 1) np = 3; sprintf(meshName, "%s", grpName); makeTriArray(numAbcTri[i], &(abcTriArray[i]), meshName); sprintf(JcurName, "%s.curJ", grpName); setRegister(&(regJ[i]), numAbcTri[i], abcTriArray[i], JcurName, np ); if (!Pec[i]) { sprintf(McurName, "%s.curM", grpName); setRegister(&(regM[i]), numAbcTri[i], abcTriArray[i], McurName, np ); } } // partition the meshing group **top = new group *[regions]; group ***SVDgroup = new group **[regions]; int NumSVDgroup[regions], grpSize[regions]; for (i = 0; i < regions; i ++) { top[i] = InitilizeTopGroup( abcTriArray[i], numAbcTri[i] ); grpSize[i] = int(1.5 * sqrt(double(numAbcTri[i]))); SVDgroup[i] = MeshPartition(top[i], grpSize[i], NumSVDgroup[i]); } int maxTriNum = 0; int maxSizePhi = 0, maxSizeTheta = 0; int sizeTheta, sizePhi; for (i = 0; i < regions; i ++) { for ( j = 0; j < NumSVDgroup[i]; j ++ ) { int nTri = SVDgroup[i][j]->GetnElement(); if (nTri > maxTriNum) maxTriNum = nTri; SVDgroup[i][j]->ComputeGroupRadius(); double d = 2.0 * SVDgroup[i][j]->GetRadius(); int Lp = int( ko * d + 5.0 * log(ko * d + Pi) ); sizeTheta = 2 * Lp + 1; sizePhi = 2 * Lp; sizePhi = (sizePhi > numPhi) ? numPhi : sizePhi; sizeTheta = (Lp > numTheta) ? 2*numTheta : sizeTheta; if (sizePhi > maxSizePhi) maxSizePhi = sizePhi; if (sizeTheta > maxSizeTheta) maxSizeTheta = sizeTheta; } } groupTriArray = new tri3d*[maxTriNum]; groupRegJ = new regcvtr [maxTriNum]; groupRegM = new regcvtr [maxTriNum]; for (i = 0; i < maxTriNum; i ++) { groupRegJ[i].init(6); groupRegM[i].init(6); } int coeffSize = maxSizeTheta * maxSizePhi; Epart = new cVtr [coeffSize]; tmp_x = new fftwf_complex [coeffSize]; tmp_y = new fftwf_complex [coeffSize]; tmp_z = new fftwf_complex [coeffSize]; // allocate storage space sizeTheta = 2 * numTheta; sizePhi = numPhi; coeffSize = sizeTheta * sizePhi; out = new fftwf_complex [coeffSize]; field = new fftwf_complex [coeffSize]; workspace = new fftwf_complex [coeffSize]; cVtr **MainField = new cVtr *[regions]; for (i = 0; i < regions; i ++) { MainField[i] = new cVtr[coeffSize]; // calculate far field for ( j = 0; j < NumSVDgroup[i]; j ++ ) { if (j % 5 == 0) cout << "group = " << j << " / " << NumSVDgroup[i] << endl; FastFarField( SVDgroup[i], j, ko, regJ[i], regM[i], numTheta, numPhi, MainField[i], Pec[i] ); } } delete [] out; delete [] field; delete [] workspace; delete [] groupTriArray; delete [] Epart; delete [] tmp_x; delete [] tmp_y; delete [] tmp_z; for (i = 0; i < maxTriNum; i ++) { groupRegJ[i].del(); groupRegM[i].del(); } delete [] groupRegJ; delete [] groupRegM; // split far field into theta and phi components int idx = 0; cVtr E; for ( i = 0; i <= numTheta; i ++ ) { theta = double(i) * deltaTheta; for ( j = 0; j < numPhi; j ++ ) { phi = double(j) * deltaPhi; thetaVtr = ThetaDirection(theta, phi); phiVtr = PhiDirection(theta, phi); E.reset(); for (n = 0; n < regions; n ++) E = E + MainField[n][idx]; eTheta[i][j] = dotP( E, thetaVtr ); ePhi[i][j] = dotP( E, phiVtr ); idx ++; } eTheta[i][numPhi] = eTheta[i][0]; ePhi[i][numPhi] = ePhi[i][0]; } for (i = 0; i < regions; i ++) delete [] MainField[i]; delete [] MainField; double Gmax = 0.0; for (i = 0; i <= numTheta; i ++) { for (j = 0; j <= numPhi; j ++) { double eMag = MagE(eTheta[i][j], ePhi[i][j]); Gmax = (eMag > Gmax) ? eMag : Gmax; } } for (i = 0; i <= numTheta; i ++) { for (j = 0; j <= numPhi; j ++) { eTheta[i][j] /= Gmax; ePhi[i][j] /= Gmax; } } // Compute the beam solid angle double omegaA = 0.0; for (i = 0; i < numTheta; i ++) { double theta_in_rad = (deltaTheta * (double)(i) + 0.5 * deltaTheta) * Pi / 180.0; for (j = 0; j < numPhi; j ++) { Complex thetaValue = (eTheta[i][j] + eTheta[i][j + 1] + eTheta[i + 1][j] + eTheta[i + 1][j + 1]) * 0.25f; Complex phiValue = (ePhi[i][j] + ePhi[i][j + 1] + ePhi[i + 1][j] + ePhi[i + 1][j + 1]) * 0.25f; omegaA += (norm(thetaValue) + norm(phiValue)) * sin(theta_in_rad); } } omegaA = omegaA * (deltaTheta * Pi / 180.0) * (deltaPhi * Pi / 180.0); cout << "Omega " << omegaA << endl; double Prad = omegaA * Gmax; cout << "total power = " << Prad << endl; double Pavg = Prad / 4.0 / Pi; cout << "average power = " << sqrt(Pavg) << endl; char antName[180]; sprintf(antName, "%s.ap", prjName); ofstream fap(antName, ios::out); fap << freq << " " << numTheta << " " << numPhi << endl; int index1 = 0, index2 = 0; for (i = 0; i <= numTheta; i ++) { double theta = deltaTheta * (double)(i); if (theta < 29.99 || theta > 150.1) continue; index1 ++; index2 = 0; for (j = 0; j <= numPhi; j ++) { double phi = deltaPhi * (double)(j); if (phi > 60.1 && phi < 299.99) continue; index2 ++; eTheta[i][j] *= Gmax / Pavg; ePhi[i][j] *= Gmax / Pavg; if (OPT == 0) { fap << theta << " " << phi << " " << norm(eTheta[i][j]) << " " << norm(ePhi[i][j]) << endl; } else { fap << theta << " " << phi << " " << (eTheta[i][j]).real() << " " << (eTheta[i][j]).imag() << " " << (ePhi[i][j]).real() << " " << (ePhi[i][j]).imag() << endl; } } } fap.close(); cout << index1-1 << " " << index2-1 << endl; times(&tmsEnd); double cpuTime; cpuTime = static_cast((tmsEnd.tms_utime + tmsEnd.tms_cutime) - (tmsStart.tms_utime + tmsStart.tms_cutime)) / static_cast(sysconf(_SC_CLK_TCK)); int cpuTIME = static_cast(floor(cpuTime + 0.5)); int hh = cpuTIME / 3600; int mm = (cpuTIME - hh * 3600) / 60; int ss = (cpuTIME - hh * 3600 - mm * 60); cout << "Farfield Time(hh:mm:ss) = " << hh << ":" << mm << ":" << ss << endl; } void ReadRegions(char *fname, int **FEM, int &numRegions) { char fileName[180]; sprintf(fileName, "%s.region", fname); ifstream foo; foo.open(fileName); if (foo == NULL) { cout << "could not find file: " << fileName << endl; exit(0); } foo >> numRegions; (*FEM) = new int [numRegions]; int i, id; char solverType[180]; for (i = 0; i < numRegions; i ++) { int id; foo >> id; foo >> solverType;; if (strcmp(solverType, "DDM") == 0) (*FEM)[id] = 1; else if (strcmp(solverType, "FEM") == 0) (*FEM)[id] = 1; else if (strcmp(solverType, "MOM") == 0) (*FEM)[id] = 0; else if (strcmp(solverType, "BEM") == 0) (*FEM)[id] = 0; else if (strcmp(solverType, "IE") == 0) (*FEM)[id] = 0; else if (strcmp(solverType, "PO") == 0) (*FEM)[id] = 2; else { cout << "unidentified solver type: " << solverType << endl; exit(0); } } foo.close(); }