Skip to content

Commit c757b45

Browse files
committed
SAR: refactor and improve SAR calculations
* new range limit with auto range option to reduce required computation * averaging done only once for all frequencies (massive speedup) * split read and write hdf5 into separate functions * use the (now separate) hdf5 write in the openEMS field proc to reduce redundancy Signed-off-by: Thorsten Liebig <Thorsten.Liebig@gmx.de>
1 parent 52c688d commit c757b45

9 files changed

Lines changed: 594 additions & 285 deletions

Common/processfields_sar.cpp

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -272,46 +272,36 @@ void ProcessFieldsSAR::DumpFDData()
272272
SAR_Calc.SetCellDensities(&cell_density);
273273
SAR_Calc.SetCellWidth(cellWidth);
274274
SAR_Calc.SetCellVolumes(&cell_volume);
275-
SAR_Calc.SetCellCondictivity(&cell_kappa); // cell_kappa will be NULL if m_UseCellKappa is false
276-
double mass = SAR_Calc.CalcTotalMass();
277275

278276
for (size_t n = 0; n<m_FD_Samples.size(); ++n)
279277
{
280-
SAR_Calc.SetEField(m_E_FD_Fields.at(n));
281278
if (!m_UseCellKappa)
282-
SAR_Calc.SetJField(m_J_FD_Fields.at(n));
283-
power = SAR_Calc.CalcSARPower();
284-
SAR_Calc.SetCellVolumes(&cell_volume);
285-
power = SAR_Calc.CalcSARPower();
286-
SAR_Calc.CalcSAR(SAR);
279+
SAR_Calc.AddEFieldAndJField(m_FD_Samples.at(n), m_E_FD_Fields.at(n), m_J_FD_Fields.at(n));
280+
else
281+
SAR_Calc.AddEFieldAndCondictivity(m_FD_Samples.at(n), m_E_FD_Fields.at(n), &cell_kappa);
282+
}
283+
SAR_Calc.CalcSAR();
287284

288-
if (m_fileType==VTK_FILETYPE)
285+
if (m_fileType==VTK_FILETYPE)
286+
{
287+
for (size_t n = 0; n<m_FD_Samples.size(); ++n)
289288
{
290289
stringstream ss;
291290
ss << m_filename << fixed << "_f=" << m_FD_Samples.at(n);
292-
293291
m_Vtk_Dump_File->SetFilename(ss.str());
294292
m_Vtk_Dump_File->ClearAllFields();
295-
m_Vtk_Dump_File->AddScalarField(GetFieldNameByType(m_DumpType),SAR);
293+
m_Vtk_Dump_File->AddScalarField(GetFieldNameByType(m_DumpType), *SAR_Calc.GetSAR(n));
296294
if (m_Vtk_Dump_File->Write()==false)
297295
cerr << "ProcessFieldsSAR::DumpFDData: can't dump to file...! " << endl;
298296
}
299-
else if (m_fileType==HDF5_FILETYPE)
300-
{
301-
stringstream ss;
302-
ss << "f" << n;
303-
if (m_HDF5_Dump_File->WriteScalarField<float>(ss.str(), SAR, g_settings.GetLegacyHFD5Dumps())==false)
304-
cerr << "ProcessFieldsSAR::DumpFDData: can't dump to file...! " << endl;
305-
if (m_HDF5_Dump_File->WriteAtrribute("/FieldData/FD/"+ss.str(),"frequency",(float)m_FD_Samples.at(n))==false)
306-
cerr << "ProcessFieldsSAR::DumpFDData: can't dump to file...! " << endl;
307-
if (m_HDF5_Dump_File->WriteAtrribute("/FieldData/FD/"+ss.str(),"mass",mass)==false)
308-
cerr << "ProcessFieldsSAR::DumpFDData: can't dump mass to file...! " << endl;
309-
if (m_HDF5_Dump_File->WriteAtrribute("/FieldData/FD/"+ss.str(),"power",power)==false)
310-
cerr << "ProcessFieldsSAR::DumpFDData: can't dump power to file...! " << endl;
311-
}
312-
else
313-
cerr << "ProcessFieldsSAR::DumpFDData: unknown File-Type" << endl;
314297
}
298+
else if (m_fileType==HDF5_FILETYPE)
299+
{
300+
if (SAR_Calc.WriteToHDF5(*m_HDF5_Dump_File, g_settings.GetLegacyHFD5Dumps())==false)
301+
cerr << "ProcessFieldsSAR::DumpFDData: can't dump to file...! " << endl;
302+
}
303+
else
304+
cerr << "ProcessFieldsSAR::DumpFDData: unknown File-Type" << endl;
315305
}
316306
for (int n=0;n<3;++n)
317307
delete[] cellWidth[n];

python/openEMS/sar_calculation.pxd

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ cdef extern from "openEMS/sar_calculation.h":
2727
void EnableProgress(bool enable)
2828
void SetAveragingMass(float mass)
2929
bool SetAveragingMethod(string method, bool silent)
30-
bool CalcFromHDF5(string h5_fn, string out_name, bool export_cube_stats) nogil
30+
void EnableCubeStats()
31+
void EnableAutoRange(double dBmax)
32+
bool CalcFromHDF5(string h5_fn, string out_name) nogil
3133

3234

3335
cdef class SAR_Calculation:

python/openEMS/sar_calculation.pyx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ cdef class SAR_Calculation:
3131
self.SetDebugLevel(int(v))
3232
elif k=='debug':
3333
self.SetDebugLevel(int(v))
34+
elif k=='autoRange':
35+
self.EnableAutoRange(float(v))
36+
elif k=='EnableCubeStats':
37+
if v:
38+
self.EnableCubeStats()
3439
else:
3540
raise Exception('Unknown keyword argument: "{}"'.format(k))
3641

@@ -49,13 +54,20 @@ cdef class SAR_Calculation:
4954
#cdef string c_method = method.encode('UTF-8')
5055
return self.thisptr.SetAveragingMethod(method.encode('UTF-8'), silent)
5156

57+
def EnableAutoRange(self, dBmax):
58+
self.thisptr.EnableAutoRange(float(dBmax))
59+
60+
def EnableCubeStats(self):
61+
self.thisptr.EnableCubeStats()
62+
5263
def CalcFromHDF5(self, h5_fn, out_name, export_cube_stats=False):
5364
if not os.path.exists(h5_fn):
5465
raise Exception('File "{}" does not exist'.format(h5_fn))
5566
cdef string in_fn = h5_fn.encode('UTF-8')
5667
cdef string out_fn = out_name.encode('UTF-8')
57-
cdef bool ecs = export_cube_stats
68+
if export_cube_stats:
69+
self.EnableCubeStats()
5870
with nogil:
59-
ok = self.thisptr.CalcFromHDF5(in_fn, out_fn, ecs)
71+
ok = self.thisptr.CalcFromHDF5(in_fn, out_fn)
6072
return ok
6173

tools/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ ADD_EXECUTABLE( sar_bin sar_calc.cpp)
3535
SET_TARGET_PROPERTIES(sar_bin PROPERTIES OUTPUT_NAME sar_calc)
3636
TARGET_LINK_LIBRARIES(sar_bin openEMS)
3737

38-
INSTALL(FILES sar_calculation.h DESTINATION include/openEMS)
38+
INSTALL(FILES sar_calculation.h hdf5_file_reader.h hdf5_file_writer.h vtk_file_writer.h DESTINATION include/openEMS)
3939

4040
# not ideal, but no way around it?
4141
INSTALL(FILES arraylib/array_ij.h arraylib/array_ijk.h arraylib/array_nijk.h DESTINATION include/openEMS/arraylib)

tools/hdf5_file_writer.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -420,15 +420,15 @@ bool HDF5_File_Writer::WriteAtrribute(hid_t loc, std::string attr_name, void con
420420
hid_t attribute_id = H5Acreate(loc, attr_name.c_str(), mem_type, dataspace_id, H5P_DEFAULT, H5P_DEFAULT);
421421
if (attribute_id<0)
422422
{
423-
cerr << "HDF5_File_Writer::WriteAtrribute: Error, failed to create the attribute" << endl;
423+
cerr << "HDF5_File_Writer::WriteAtrribute: Error, failed to create the attribute: " << attr_name << endl;
424424
H5Sclose(dataspace_id);
425425
return false;
426426
}
427427

428428
/* Write the attribute data. */
429429
if (H5Awrite(attribute_id, mem_type, value)<0)
430430
{
431-
cerr << "HDF5_File_Writer::WriteAtrribute: Error, failed to write the attribute" << endl;
431+
cerr << "HDF5_File_Writer::WriteAtrribute: Error, failed to write the attribute" << attr_name << endl;
432432
H5Aclose(attribute_id);
433433
H5Sclose(dataspace_id);
434434
return false;
@@ -468,6 +468,26 @@ bool HDF5_File_Writer::WriteAtrribute(std::string locName, std::string attr_name
468468
return ok;
469469
}
470470

471+
bool HDF5_File_Writer::WriteAtrribute(std::string locName, std::string attr_name, vector<int> values)
472+
{
473+
int* val = new int[values.size()];
474+
for (size_t n=0;n<values.size();++n)
475+
val[n]=values.at(n);
476+
bool ok = HDF5_File_Writer::WriteAtrribute(locName, attr_name, val, values.size(), H5T_NATIVE_INT);
477+
delete[] val; val=NULL;
478+
return ok;
479+
}
480+
481+
bool HDF5_File_Writer::WriteAtrribute(std::string locName, std::string attr_name, vector<unsigned int> values)
482+
{
483+
unsigned int* val = new unsigned int[values.size()];
484+
for (size_t n=0;n<values.size();++n)
485+
val[n]=values.at(n);
486+
bool ok = HDF5_File_Writer::WriteAtrribute(locName, attr_name, val, values.size(), H5T_NATIVE_UINT);
487+
delete[] val; val=NULL;
488+
return ok;
489+
}
490+
471491
bool HDF5_File_Writer::WriteAtrribute(std::string locName, std::string attr_name, float value)
472492
{
473493
return HDF5_File_Writer::WriteAtrribute(locName, attr_name, &value, 0, H5T_NATIVE_FLOAT);

tools/hdf5_file_writer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ class HDF5_File_Writer
5353
bool WriteAtrribute(std::string locName, std::string attr_name, double const* value, hsize_t size);
5454
bool WriteAtrribute(std::string locName, std::string attr_name, std::vector<float> values);
5555
bool WriteAtrribute(std::string locName, std::string attr_name, std::vector<double> values);
56+
bool WriteAtrribute(std::string locName, std::string attr_name, std::vector<int> values);
57+
bool WriteAtrribute(std::string locName, std::string attr_name, std::vector<unsigned int> values);
5658
bool WriteAtrribute(std::string locName, std::string attr_name, float value);
5759
bool WriteAtrribute(std::string locName, std::string attr_name, double value);
5860
bool WriteAtrribute(std::string locName, std::string attr_name, int value);

tools/sar_calc.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,15 @@ int main(int argc, char *argv[])
2727
{
2828
cout << " ---------------------------------------------------------------------- " << endl;
2929
cout << " | SAR calculation for openEMS " << endl;
30-
cout << " | (C) 2012-2025 Thorsten Liebig <thorsten.liebig@gmx.de> GPL license" << endl;
30+
cout << " | (C) 2012-2026 Thorsten Liebig <thorsten.liebig@gmx.de> GPL license" << endl;
3131
cout << " ---------------------------------------------------------------------- " << endl;
3232

3333
options_description desc("Options");
3434
variables_map vm;
3535
try {
3636
string ifile, ofile, method;
3737
double m_avg = 0;
38+
double auto_range=0;
3839
bool debug = false;
3940
bool export_cube_stats = false;
4041
bool legacyHDF5 = false;
@@ -46,6 +47,7 @@ int main(int argc, char *argv[])
4647
("output,o", value(&ofile)->required(), "pathname for output hdf5 file")
4748
("method", value(&method)->default_value("SIMPLE"), "set SAR method: IEEE_C95_3, IEEE_62704, SIMPLE")
4849
("mass,m" , value(&m_avg), "averaging mass in g")
50+
("autorange,a" , value(&auto_range), "autorange, value limit in dB from max. (>0)")
4951
("verbose,v", bool_switch(&debug), "verbose")
5052
("progress,p", bool_switch(&progress), "show progress")
5153
("export_cube_stats,e", bool_switch(&export_cube_stats), "Export Cube Statistics")
@@ -64,11 +66,13 @@ int main(int argc, char *argv[])
6466
sar_calc.SetDebugLevel(int(debug));
6567
sar_calc.EnableProgress(progress);
6668
sar_calc.SetAveragingMass(m_avg/1000);
69+
sar_calc.EnableAutoRange(auto_range);
70+
if (export_cube_stats)
71+
sar_calc.EnableCubeStats();
6772
//sar_calc.SetAveragingMethod(SAR_Calculation::IEEE_62704);
6873
if (!sar_calc.SetAveragingMethod(method, !debug))
6974
return -1;
70-
sar_calc.CalcFromHDF5(ifile, ofile, export_cube_stats, legacyHDF5);
71-
return 0;
75+
return sar_calc.CalcFromHDF5(ifile, ofile, legacyHDF5);
7276
}
7377
catch(exception& e) {
7478
cerr << e.what() << "\n";

0 commit comments

Comments
 (0)