/* * 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); } double nf2ff::GetTotalRadPower(size_t f_idx) const { return m_nf2ff.at(f_idx)->GetTotalRadPower(); } double nf2ff::GetMaxDirectivity(size_t f_idx) const { return m_nf2ff.at(f_idx)->GetMaxDirectivity(); } complex** nf2ff::GetETheta(size_t f_idx) const { return m_nf2ff.at(f_idx)->GetETheta(); } complex** nf2ff::GetEPhi(size_t f_idx) const { return m_nf2ff.at(f_idx)->GetEPhi(); } double** nf2ff::GetRadPower(size_t f_idx) const { return m_nf2ff.at(f_idx)->GetRadPower(); } 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