RCS Computation Toolkit This repository provides C++ and Python tools for computing radar cross section (RCS) from surface currents or analytical models
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

#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();
}