You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
335 lines
9.8 KiB
335 lines
9.8 KiB
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <iomanip>
|
|
#include <math.h>
|
|
#include <string>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/times.h>
|
|
#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<tri3d> **top = new group<tri3d> *[regions];
|
|
group<tri3d> ***SVDgroup = new group<tri3d> **[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<double>((tmsEnd.tms_utime + tmsEnd.tms_cutime) -
|
|
(tmsStart.tms_utime + tmsStart.tms_cutime)) /
|
|
static_cast<double>(sysconf(_SC_CLK_TCK));
|
|
int cpuTIME = static_cast<int>(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();
|
|
}
|
|
|