/* * Copyright (C) 2010 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 #include #include "tools/global.h" #include "processfields.h" ProcessFields::ProcessFields(Operator* op, Engine* eng) : Processing(op, eng) { m_DumpMode = NO_INTERPOLATION; m_DumpType = E_FIELD_DUMP; // vtk-file is default m_fileType = VTK_FILETYPE; m_Mesh_Type = CARTESIAN_MESH; SetSubSampling(1); SetPrecision(6); for (int n=0;n<3;++n) { numLines[n]=0; discDLines[n]=NULL; discLines[n]=NULL; } } ProcessFields::~ProcessFields() { for (int n=0;n<3;++n) { delete[] discDLines[n]; discDLines[n]=NULL; delete[] discLines[n]; discLines[n]=NULL; } } void ProcessFields::InitProcess() { if (Enabled==false) return; //get the correct direction names for all coordinate systems string names[] = {Op->GetDirName(0),Op->GetDirName(1),Op->GetDirName(2)}; if (m_fileType==HDF5_FILETYPE) { unsigned int* NrLines; double** Lines; if (m_DumpMode==NO_INTERPOLATION) { NrLines = numLines; Lines = discLines; } else if (m_DumpMode==NODE_INTERPOLATE) { NrLines = numLines; Lines = discLines; } else if (m_DumpMode==CELL_INTERPOLATE) { NrLines = numDLines; Lines = discDLines; } else return; m_filename+= ".h5"; H5::H5File* file = new H5::H5File( m_filename , H5F_ACC_TRUNC ); H5::Group* group = new H5::Group( file->createGroup( "/Mesh" )); for (int n=0;n<3;++n) { hsize_t dimsf[1]; // dataset dimensions dimsf[0] = NrLines[n]; H5::DataSpace dataspace( 1, dimsf ); H5::FloatType datatype( H5::PredType::NATIVE_FLOAT ); H5::DataSet dataset = group->createDataSet( names[n].c_str(), datatype, dataspace ); //convert to float... float* array = new float[NrLines[n]]; for (unsigned int i=0;iGetGridDelta(); #endif } //write to dataset dataset.write( array, H5::PredType::NATIVE_FLOAT ); } delete group; group = new H5::Group( file->createGroup( "/FieldData" )); delete group; delete file; } } string ProcessFields::GetFieldNameByType(DumpType type) { switch (type) { case E_FIELD_DUMP: return "E-Field"; case H_FIELD_DUMP: return "H-Field"; } return "unknown field"; } string ProcessFields::GetInterpolationNameByType(DumpMode mode) { switch (mode) { case NO_INTERPOLATION: return string("Interpolation: None"); case NODE_INTERPOLATE: return string("Interpolation: Node"); case CELL_INTERPOLATE: return string("Interpolation: Cell"); } return string(); } void ProcessFields::DefineStartStopCoord(double* dstart, double* dstop) { vector lines; if (m_DumpMode==NO_INTERPOLATION) { if (Op->SnapToMesh(dstart,start)==false) cerr << "ProcessFields::DefineStartStopCoord: Warning: Snapping problem, check start value!!" << endl; if (Op->SnapToMesh(dstop,stop)==false) cerr << "ProcessFields::DefineStartStopCoord: Warning: Snapping problem, check stop value!!" << endl; //create dual mesh for (int n=0;n<3;++n) { // cerr << "start " << start[n] << "stop " << stop[n]; if (start[n]>stop[n]) { unsigned int help = start[n]; start[n]=stop[n]; stop[n]=help; } lines.clear(); for (unsigned int i=start[n];i<=stop[n];i+=subSample[n]) { lines.push_back(Op->GetDiscLine(n,i));//Op->discLines[n][i]); } numLines[n] = lines.size(); delete[] discLines[n]; discLines[n] = new double[numLines[n]]; for (unsigned int i=0;iSnapToMesh(dstart,start)==false) cerr << "ProcessFields::DefineStartStopCoord: Warning: Snapping problem, check start value!!" << endl; if (Op->SnapToMesh(dstop,stop)==false) cerr << "ProcessFields::DefineStartStopCoord: Warning: Snapping problem, check stop value!!" << endl; //create mesh for (int n=0;n<3;++n) { if (start[n]>stop[n]) { unsigned int help = start[n]; start[n]=stop[n]; stop[n]=help; } if (stop[n]==Op->GetNumberOfLines(n)-1) --stop[n]; // cerr << "start " << start[n] << "stop " << stop[n]; lines.clear(); for (unsigned int i=start[n];i<=stop[n];i+=subSample[n]) { lines.push_back(Op->GetDiscLine(n,i));//0.5*(Op->discLines[n][i+1] + Op->discLines[n][i])); } numLines[n] = lines.size(); delete[] discLines[n]; discLines[n] = new double[numLines[n]]; for (unsigned int i=0;iSnapToMesh(dstart,start,true)==false) cerr << "ProcessFields::DefineStartStopCoord: Warning: Snapping problem, check start value!!" << endl; if (Op->SnapToMesh(dstop,stop,true)==false) cerr << "ProcessFields::DefineStartStopCoord: Warning: Snapping problem, check stop value!!" << endl; //create dual mesh for (int n=0;n<3;++n) { // cerr << "start " << start[n] << "stop " << stop[n]; if (start[n]>stop[n]) { unsigned int help = start[n]; start[n]=stop[n]; stop[n]=help; } ++stop[n]; lines.clear(); for (unsigned int i=start[n];iGetDiscLine(n,i,true));//0.5*(Op->discLines[n][i+1] + Op->discLines[n][i])); } numDLines[n] = lines.size(); delete[] discDLines[n]; discDLines[n] = new double[numDLines[n]]; for (unsigned int i=0;iGetDiscLine( 0, start[0], dualMesh ) << "," << Op->GetDiscLine( 1, start[1], dualMesh ) << "," << Op->GetDiscLine( 2, start[2], dualMesh ) << ") -> (" << Op->GetDiscLine( 0, stop[0], dualMesh ) << ","<< Op->GetDiscLine( 1, stop[1], dualMesh ) << "," << Op->GetDiscLine( 2, stop[2], dualMesh ) << ")"; cerr << " [" << start[0] << "," << start[1] << "," << start[2] << "] -> [" << stop[0] << "," << stop[1] << "," << stop[2] << "]" << endl; } } double ProcessFields::CalcTotalEnergy() const { if (!Eng) return 0; double energy=0; unsigned int pos[3]; for (pos[0]=0;pos[0]GetNumberOfLines(0);++pos[0]) { for (pos[1]=0;pos[1]GetNumberOfLines(1);++pos[1]) { for (pos[2]=0;pos[2]GetNumberOfLines(2);++pos[2]) { energy+=fabs(Eng->GetVolt(0,pos[0],pos[1],pos[2]) * Eng->GetCurr(1,pos[0],pos[1],pos[2])); energy+=fabs(Eng->GetVolt(0,pos[0],pos[1],pos[2]) * Eng->GetCurr(2,pos[0],pos[1],pos[2])); energy+=fabs(Eng->GetVolt(1,pos[0],pos[1],pos[2]) * Eng->GetCurr(0,pos[0],pos[1],pos[2])); energy+=fabs(Eng->GetVolt(1,pos[0],pos[1],pos[2]) * Eng->GetCurr(2,pos[0],pos[1],pos[2])); energy+=fabs(Eng->GetVolt(2,pos[0],pos[1],pos[2]) * Eng->GetCurr(0,pos[0],pos[1],pos[2])); energy+=fabs(Eng->GetVolt(2,pos[0],pos[1],pos[2]) * Eng->GetCurr(1,pos[0],pos[1],pos[2])); } } } return energy*0.5; } void ProcessFields::SetSubSampling(unsigned int subSampleRate, int dir) { if (dir>2) return; if (dir<0) { subSample[0]=subSampleRate; subSample[1]=subSampleRate; subSample[2]=subSampleRate; } else subSample[dir]=subSampleRate; } void ProcessFields::WriteVTKHeader(ofstream &file, double const* const* discLines, unsigned int const* numLines, unsigned int precision, string header_info, MeshType meshT, double discLines_scaling) { if (meshT==CARTESIAN_MESH) WriteVTKCartesianGridHeader(file, discLines, numLines, precision, header_info, discLines_scaling); else if (meshT==CYLINDRICAL_MESH) WriteVTKCylindricalGridHeader(file, discLines, numLines, precision, header_info, discLines_scaling); else cerr << "ProcessFields::WriteVTKHeader: Warning: unknown mesh type, skipping header -> file will be invalid..." << endl; } void ProcessFields::WriteVTKCartesianGridHeader(ofstream &file, double const* const* discLines, unsigned int const* numLines, unsigned int precision, string header_info, double discLines_scaling) { file << "# vtk DataFile Version 2.0" << endl; file << "Rectilinear Grid openEMS_ProcessFields"; if (!header_info.empty()) file << " " << header_info; file << endl; file << "ASCII" << endl; file << "DATASET RECTILINEAR_GRID " << endl; file << "DIMENSIONS " << numLines[0] << " " << numLines[1] << " " << numLines[2] << endl; file << "X_COORDINATES " << numLines[0] << " float" << endl; for (unsigned int i=0;i