/*
* Copyright (C) 2012-2014 Thorsten Liebig (Thorsten.Liebig@gmx.de)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "nf2ff.h"
#include "nf2ff_calc.h"
#include "../tools/array_ops.h"
#include "../tools/useful.h"
#include "../tools/hdf5_file_reader.h"
#include "../tools/hdf5_file_writer.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
//external libs
#include "tinyxml.h"
using namespace std;
nf2ff::nf2ff(vector freq, vector theta, vector phi, vector center, unsigned int numThreads)
{
m_freq = freq;
m_numTheta = theta.size();
m_theta = new float[m_numTheta];
for (size_t n=0;nSetNumThreads(numThreads);
}
m_radius = 1;
m_Verbose = 0;
}
nf2ff::~nf2ff()
{
m_freq.clear();
for (size_t fn=0;fnSetRadius(radius);
}
void nf2ff::SetPermittivity(vector permittivity)
{
if (permittivity.size()==0)
return;
m_permittivity = permittivity;
if (permittivity.size()==1)
{
for (size_t fn=0;fnSetPermittivity(permittivity.at(0));
return;
}
if (permittivity.size()!=m_freq.size())
{
cerr << __func__ << ": Error, permittivity vector size must match number of set frequencies! skipping!" << endl;
return;
}
for (size_t fn=0;fnSetPermittivity(permittivity.at(fn));
}
void nf2ff::SetPermeability(vector permeability)
{
if (permeability.size()==0)
return;
m_permeability = permeability;
if (permeability.size()==1)
{
for (size_t fn=0;fnSetPermeability(permeability.at(0));
return;
}
if (permeability.size()!=m_freq.size())
{
cerr << __func__ << ": Error, permeability vector size must match number of set frequencies! skipping!" << endl;
return;
}
for (size_t fn=0;fnSetPermeability(permeability.at(fn));
}
void nf2ff::SetMirror(int type, int dir, float pos)
{
if (m_Verbose>0)
cerr << "Enable mirror of type: "<< type << " in direction: " << dir << " at: " << pos << endl;
for (size_t fn=0;fnSetMirror(type, dir, pos);
}
bool nf2ff::AnalyseXMLNode(TiXmlElement* ti_nf2ff)
{
if (ti_nf2ff==NULL)
return false;
unsigned int numThreads=0;
int ihelp=0;
if (ti_nf2ff->QueryIntAttribute("NumThreads",&ihelp) == TIXML_SUCCESS)
{
numThreads = ihelp;
cerr << "nf2ff: Set number of threads to: " << numThreads << endl;
}
int Verbose=0;
if (ti_nf2ff->QueryIntAttribute("Verbose",&Verbose) == TIXML_SUCCESS)
cerr << "nf2ff: Set verbose level to " << Verbose << endl;
else
Verbose = 0;
const char* attr = NULL;
attr = ti_nf2ff->Attribute("freq");
if (attr==NULL)
{
cerr << "nf2ff::AnalyseXMLNode: Can't read frequency inforamtions ... " << endl;
return false;
}
vector freq = SplitString2Float(attr);
vector center;
attr = ti_nf2ff->Attribute("Center");
if (attr!=NULL)
center = SplitString2Float(attr);
attr = ti_nf2ff->Attribute("Outfile");
if (attr==NULL)
{
cerr << "nf2ff::AnalyseXMLNode: Can't read frequency inforamtions ... " << endl;
return false;
}
string outfile = string(attr);
if (outfile.empty())
{
cerr << "nf2ff::AnalyseXMLNode: outfile is empty, skipping nf2ff... " << endl;
return false;
}
TiXmlElement* ti_theta = ti_nf2ff->FirstChildElement("theta");
if (ti_theta==NULL)
{
cerr << "nf2ff::AnalyseXMLNode: Can't read theta values ... " << endl;
return false;
}
TiXmlNode* ti_theta_node = ti_theta->FirstChild();
if (ti_theta_node==NULL)
{
cerr << "nf2ff::AnalyseXMLNode: Can't read theta text child ... " << endl;
return false;
}
TiXmlText* ti_theta_text = ti_theta_node->ToText();
if (ti_theta_text==NULL)
{
cerr << "nf2ff::AnalyseXMLNode: Can't read theta text values ... " << endl;
return false;
}
vector theta = SplitString2Float(ti_theta_text->Value());
TiXmlElement* ti_phi = ti_nf2ff->FirstChildElement("phi");
if (ti_phi==NULL)
{
cerr << "nf2ff::AnalyseXMLNode: Can't read phi values ... " << endl;
return false;
}
TiXmlNode* ti_phi_node = ti_phi->FirstChild();
if (ti_phi_node==NULL)
{
cerr << "nf2ff::AnalyseXMLNode: Can't read phi text child ... " << endl;
return false;
}
TiXmlText* ti_phi_text = ti_phi_node->ToText();
if (ti_phi_text==NULL)
{
cerr << "nf2ff::AnalyseXMLNode: Can't read phi text values ... " << endl;
return false;
}
vector phi = SplitString2Float(ti_phi_text->Value());
nf2ff* l_nf2ff = new nf2ff(freq,theta,phi,center,numThreads);
l_nf2ff->SetVerboseLevel(Verbose);
attr = ti_nf2ff->Attribute("Eps_r");
if (attr!=NULL)
l_nf2ff->SetPermittivity(SplitString2Float(attr));
attr = ti_nf2ff->Attribute("Mue_r");
if (attr!=NULL)
l_nf2ff->SetPermeability(SplitString2Float(attr));
float radius = 1;
if (ti_nf2ff->QueryFloatAttribute("Radius",&radius) == TIXML_SUCCESS)
l_nf2ff->SetRadius(radius);
// read mirrors
TiXmlElement* ti_Mirros = ti_nf2ff->FirstChildElement("Mirror");
int dir=-1;
string type;
float pos=0.0;
while (ti_Mirros!=NULL)
{
type = string(ti_Mirros->Attribute("Type"));
if (ti_Mirros->QueryIntAttribute("Dir",&dir) != TIXML_SUCCESS)
dir = -1;
if (ti_Mirros->QueryFloatAttribute("Pos",&pos) != TIXML_SUCCESS)
dir = -1;
if ((dir>=0) && (strcmp(type.c_str(),"PEC")==0))
l_nf2ff->SetMirror(MIRROR_PEC, dir, pos);
else if ((dir>=0) && (strcmp(type.c_str(),"PMC")==0))
l_nf2ff->SetMirror(MIRROR_PMC, dir, pos);
ti_Mirros = ti_Mirros->NextSiblingElement("Mirror");
}
TiXmlElement* ti_Planes = ti_nf2ff->FirstChildElement("Planes");
string E_name;
string H_name;
while (ti_Planes!=NULL)
{
E_name = string(ti_Planes->Attribute("E_Field"));
H_name = string(ti_Planes->Attribute("H_Field"));
if ((!E_name.empty()) && (!H_name.empty()))
{
if (l_nf2ff->AnalyseFile(E_name,H_name)==false)
{
cerr << "nf2ff::AnalyseXMLNode: Error, analysing Plane ... " << endl;
return false;
}
}
else
{
cerr << "nf2ff::AnalyseXMLNode: Error, invalid plane entry ... " << endl;
return false;
}
ti_Planes = ti_Planes->NextSiblingElement("Planes");
}
l_nf2ff->Write2HDF5(outfile);
delete l_nf2ff;
return true;
}
bool nf2ff::AnalyseXMLFile(string filename)
{
TiXmlDocument doc(filename.c_str());
if (!doc.LoadFile())
{
cerr << "nf2ff::AnalyseXMLFile: Error loading xml-file failed!!! File: " << filename << endl;
return false;
}
TiXmlElement* ti_nf2ff = doc.FirstChildElement("nf2ff");
if (ti_nf2ff==NULL)
{
cerr << "nf2ff::AnalyseXMLFile: Can't read nf2ff ... " << endl;
return false;
}
return AnalyseXMLNode(ti_nf2ff);
}
bool nf2ff::AnalyseFile(string E_Field_file, string H_Field_file)
{
HDF5_File_Reader E_file(E_Field_file);
HDF5_File_Reader H_file(H_Field_file);
if (m_Verbose>0)
cerr << "nf2ff: Reading planes: " << E_Field_file << " & " << H_Field_file << endl;
// read E-mesh
float* E_lines[3]={NULL,NULL,NULL};
unsigned int E_numLines[3];
int E_meshType;
if (E_file.ReadMesh(E_lines, E_numLines, E_meshType) == false)
{
cerr << "nf2ff::AnalyseFile: Error reading E-field mesh..." << endl;
return false;
}
// read H-mesh
float* H_lines[3]={NULL,NULL,NULL};
unsigned int H_numLines[3];
int H_meshType;
if (H_file.ReadMesh(H_lines, H_numLines, H_meshType) == false)
{
cerr << "nf2ff::AnalyseFile: Error reading H-Field mesh..." << endl;
for (int n=0;n<3;++n)
delete[] E_lines[n];
return false;
}
// compare E/H meshs
if (E_meshType!=H_meshType)
{
cerr << "nf2ff::AnalyseFile: Error mesh types don't agree" << endl;
for (int n=0;n<3;++n)
{
delete[] H_lines[n];
delete[] E_lines[n];
}
return false;
}
if ((E_numLines[0]!=H_numLines[0]) || (E_numLines[1]!=H_numLines[1]) || (E_numLines[2]!=H_numLines[2]))
{
cerr << "nf2ff::AnalyseFile: Error mesh dimensions don't agree" << endl;
for (int n=0;n<3;++n)
{
delete[] H_lines[n];
delete[] E_lines[n];
}
return false;
}
for (int n=0;n<3;++n)
for (unsigned int m=0;m0)
cerr << "nf2ff: Data-Size: " << E_numLines[0] << "x" << E_numLines[1] << "x" << E_numLines[2] << endl;
// test if FD data available or fallback to TD is necessary
bool fallBack_TD=false;
vector FD_freq;
if (E_file.ReadFrequencies(FD_freq)==false)
fallBack_TD = true;
if (FD_freq.size()>0)
{
vector H_freq;
if (H_file.ReadFrequencies(H_freq)==false)
{
cerr << "nf2ff::AnalyseFile: Error, number of FD data mismatch, fallback to TD data..." << endl;
fallBack_TD = true;
}
else
{
for (size_t nf=0;nf FD_index;
if (fallBack_TD==false)
{
FD_index.resize(FD_freq.size(),-1);
for (size_t n=0;n****> E_fd_data;
vector****> H_fd_data;
if (m_Verbose>1)
cerr << "nf2ff: calculate dft..." << endl;
unsigned int data_size[4];
if (E_file.CalcFDVectorData(m_freq,E_fd_data,data_size)==false)
{
for (int n=0;n<3;++n)
delete[] E_lines[n];
return false;
}
if ((data_size[0]!=E_numLines[0]) || (data_size[1]!=E_numLines[1]) || (data_size[2]!=E_numLines[2]) )
{
for (size_t fn=0;fn >(E_fd_data.at(fn),data_size);
}
for (int n=0;n<3;++n)
delete[] E_lines[n];
return false;
}
if (H_file.CalcFDVectorData(m_freq,H_fd_data,data_size)==false)
{
for (size_t fn=0;fn >(E_fd_data.at(fn),data_size);
for (int n=0;n<3;++n)
delete[] E_lines[n];
return false;
}
if ((data_size[0]!=E_numLines[0]) || (data_size[1]!=E_numLines[1]) || (data_size[2]!=E_numLines[2]) )
{
for (size_t fn=0;fn >(E_fd_data.at(fn),data_size);
Delete_N_3DArray >(H_fd_data.at(fn),data_size);
}
for (int n=0;n<3;++n)
delete[] E_lines[n];
return false;
}
if (m_Verbose>0)
cerr << "nf2ff: Analysing far-field for " << m_nf2ff.size() << " frequencies. " << endl;
for (size_t fn=0;fn1)
cerr << "nf2ff: f = " << m_freq.at(fn) << "Hz (" << fn+1 << "/" << m_freq.size() << ") ...";
m_nf2ff.at(fn)->AddPlane(E_lines, E_numLines, E_fd_data.at(fn), H_fd_data.at(fn),E_meshType);
if (m_Verbose>1)
cerr << " done." << endl;
}
}
else
{
complex**** E_fd_data;
complex**** H_fd_data;
unsigned int data_size[4];
for (size_t n=0;n >(E_fd_data,data_size);
for (int n=0;n<3;++n)
delete[] E_lines[n];
return false;
}
H_fd_data = H_file.GetFDVectorData(FD_index.at(n),data_size);
if ((data_size[0]!=E_numLines[0]) || (data_size[1]!=E_numLines[1]) || (data_size[2]!=E_numLines[2]) )
{
cerr << data_size[0] << "," << data_size[1] << "," << data_size[2] << endl;
cerr << "nf2ff::AnalyseFile: FD data size mismatch... " << endl;
Delete_N_3DArray >(H_fd_data,data_size);
Delete_N_3DArray >(E_fd_data,data_size);
for (int n=0;n<3;++n)
delete[] E_lines[n];
return false;
}
if ((E_fd_data==NULL) || (H_fd_data==NULL))
{
cerr << "nf2ff::AnalyseFile: Reaing FD data failed... " << endl;
Delete_N_3DArray >(E_fd_data,data_size);
Delete_N_3DArray >(H_fd_data,data_size);
for (int n=0;n<3;++n)
delete[] E_lines[n];
return false;
}
if (m_Verbose>1)
cerr << "nf2ff: f = " << m_freq.at(n) << "Hz (" << n+1 << "/" << m_freq.size() << ") ...";
m_nf2ff.at(n)->AddPlane(E_lines, E_numLines, E_fd_data, H_fd_data,E_meshType);
if (m_Verbose>1)
cerr << " done." << endl;
}
}
for (int n=0;n<3;++n)
delete[] E_lines[n];
return true;
}
bool nf2ff::Write2HDF5(string filename)
{
HDF5_File_Writer hdf_file(filename);
//write mesh information
hdf_file.SetCurrentGroup("/Mesh");
size_t meshsize[1]={m_numTheta};
if (hdf_file.WriteData(string("theta"),m_theta,1,meshsize)==false)
return false;
meshsize[0]=m_numPhi;
if (hdf_file.WriteData(string("phi"),m_phi,1,meshsize)==false)
return false;
meshsize[0]=1;
float rad[1]={m_radius};
if (hdf_file.WriteData(string("r"),rad,1,meshsize)==false)
return false;
float attr_value = 2;
hdf_file.WriteAtrribute("/Mesh", "MeshType", &attr_value, 1);
//write field data
size_t dim = 2;
size_t pos = 0;
size_t datasize[2]={m_numPhi,m_numTheta};
size_t size = datasize[0]*datasize[1];
double* buffer = new double[size];
complex** field_data;
string field_names[2]={"E_theta", "E_phi"};
for (int n=0;n<2;++n)
{
hdf_file.SetCurrentGroup("/nf2ff/" + field_names[n] + "/FD");
for (size_t fn=0;fn0)
{
buffer = new double[m_permittivity.size()];
for (size_t n=0;n0)
{
buffer = new double[m_permeability.size()];
for (size_t n=0;n