-
Notifications
You must be signed in to change notification settings - Fork 57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor measurement and printing for future features #302
base: main
Are you sure you want to change the base?
Conversation
2e0b7f0
to
c1a8a4b
Compare
- export build commands
- Used for testing since Catch does not support testing aborts
- Add tests - Add table wrapper for csv files for open-write-close - Make empty cell NULL
- switch post-processing functions to small classes that store data in tables - replace sequential row printing - separate write during sweep step and final write more clearly
- Requires non-empty output dir - Canonicalize and sync among processors - Introduces palace::fs namespace to stop injecting into std
- Simplify checks since output directory always exists
- Cleaner separation between measurement (PostOperator) and printing (in solvers) - Treat frequency as measurement to be supplied by solver - Add caching system in PostOperator for all measurements, extending port case - Simplify energy measurements using caching system - Store pointer view to lumped/wave port operators in PostOperator where appropriate
c1a8a4b
to
f58ccbf
Compare
- remove redunant default init - init doubles in postop
Hi, since you are refactoring the output format to support multi-excitations, I'd like to ask if would consider adding an option to output S-parameter files in Touchstone format. It's a de-facto standard in circuit simulators and beyond. |
Dear @fedeinthemix, Thank you very much for your suggestion. We'll have to think about it more, but right now we don't have plans to print touchstone files directly in Palace. In cases where people require touchstone files, we have recommended writing a script that reads in the palace csv files from all the separate simulations (e.g. using pandas) and then prints it in the right form. You could also look at scikit-rf that has a touchstone printer and parser. For Palace, we do want a consistant file formats with other measurements not covered by touchstone, like energy or fields. Also the touchstone spec does not quite cover some cases, like simulating only a subset of columns of the s-matrix. Please let use know, if there is there anything you think we are missing something in the Palace output. For example, is there something in the touchstone file format / metadata that you can't find easily? Thanks! |
Dear @phdum-a, Thank you for your answer. I thought that an option to output Touchstone files would be convenient since most RF/mmW passive circuits simulated with palace will probably be used in circuit simulators. But, I understand point, and, as you say, writing a conversion procedure is not a big deal. Thanks again for your answer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally looks pretty good. I have some changes I think need to be made at #325 from hughcars/new_postpro
. Additionally given it's a large refactor, mention it in the CHANGELOG.md
.
@@ -76,6 +76,9 @@ if(CMAKE_BUILD_TYPE MATCHES "Debug|debug|DEBUG") | |||
endif() | |||
endif() | |||
|
|||
# Replace mfem abort calls with exceptions for testing, default off | |||
set(PALACE_MFEM_USE_EXCEPTIONS CACHE NO "MFEM throw exceptsions instead of abort calls") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
set(PALACE_MFEM_USE_EXCEPTIONS CACHE NO BOOL "MFEM throw exceptsions instead of abort calls")
The BOOL
is needed to calm a warning about using the cache. However if you do that, the mfem build then fails due to their parsing of the variable, giving
set(MFEM_DEBUG OFF)
set(MFEM_USE_EXCEPTIONS CACHE)
set(MFEM_USE_ZLIB YES)
in the mfem cmake cache. I think sticking with
set(PALACE_MFEM_USE_EXCEPTIONS NO)
rather than needing to work around mfem's cmake approach.
buf.append(buf_a); | ||
} | ||
|
||
Mpi::Print("{}", fmt::to_string(buf)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This buffering trick will print everything in one shot rather than scrolling. I don't think its an issue as this goes by so fast anyway as to be indistinguishable from a block print. Only issue would be if anything in here can error and thereby print nothing.
Given there's a few of these buffer printing options, you might consider having an Mpi::Print
overload that ingests just a buffer, Mpi::Print(fmt::memory_buffer);
that does this under the hood if it's going to be very common. Especially given these buffers are being sent in with no formatting, just directly as strings.
// View to default options in table class, will be set when columns are added to Table | ||
ColumnOptions *defaults = nullptr; | ||
|
||
// ---- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unneeded, delete.
{ | ||
friend class Table; | ||
|
||
// View to default options in table class, will be set when columns are added to Table |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Any comment on a new line ends with .
,
// New line comment.
int v = 0; // Can end without
class TableWithCSVFile | ||
{ | ||
std::string csv_file_fullpath_ = ""; | ||
unsigned long file_append_curser = -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment describing what this variable is used for.
// Common domain postprocessing for all simulation types. | ||
void PostprocessDomains(const PostOperator &post_op, const std::string &name, int step, | ||
double time, double E_elec, double E_mag, double E_cap, | ||
double E_ind) const; | ||
|
||
// Common surface postprocessing for all simulation types. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Expand on this documentation, the disctinction between a printer and the performing of the actual measurement is one of the biggest innovations in this PR. A short sentence or two here describing this distinction would be good. Can then reference this in doc string above the printers in the other driver classes.
// ----------------- | ||
// Measurements / Postprocessing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delete.
// Port Contributions: not owned, view onto space_op only, it must not go out of scope | ||
LumpedPortOperator *lumped_port_op = nullptr; | ||
WavePortOperator *wave_port_op = nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do not want these classes referenced within post operator, which shouldn't know about them, other than via a higher level operator (SpaceOperator etc.). I have a refactor that removes the need for this, by passing them in at the relevant call sites, and doing away with the use of optionals/lazy evaluation of the measurement cache. See hughcars/new_postpro
struct MeasurementCache | ||
{ | ||
std::optional<std::complex<double>> omega = std::nullopt; | ||
|
||
std::optional<double> domain_E_field_energy_all = std::nullopt; | ||
std::optional<double> domain_H_field_energy_all = std::nullopt; | ||
|
||
std::optional<std::map<int, double>> domain_E_field_energy_i = std::nullopt; | ||
std::optional<std::map<int, double>> domain_H_field_energy_i = std::nullopt; | ||
|
||
std::optional<std::vector<FluxData>> surface_flux_i = std::nullopt; | ||
std::optional<std::vector<InterfaceData>> interface_eps_i = std::nullopt; | ||
|
||
std::optional<std::map<int, PortPostData>> lumped_port_vi = std::nullopt; | ||
std::optional<std::map<int, PortPostData>> wave_port_vi = std::nullopt; | ||
|
||
std::optional<double> lumped_port_inductor_energy = std::nullopt; | ||
std::optional<double> lumped_port_capacitor_energy = std::nullopt; | ||
|
||
std::optional<std::vector<std::complex<double>>> probe_E_field = std::nullopt; | ||
std::optional<std::vector<std::complex<double>>> probe_B_field = std::nullopt; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not need optionals on here, many of the measurements are setting the non-evaluable versions to 0.0
, and the containers all ready have a notion of size. Removing the optional, and moving all the measurements to occur within the MeasureAll
method, can also use concrete values whilst removing the need for mutability aswell. See hughcars/new_postpro
Also, measurement_cache
.
void PostOperator::MeasureAll() | ||
{ | ||
if (A) | ||
ClearAllMeasurementCache(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be simplified significantly by using the fact we know when MeasureAll
will be called will be the only time to do any measurements. The lazy evaluation isn't necessary. See hughcars/new_postpro
Refactoring of measurement and printing system in preparation for multi-excitation support.
Note: The output of all solvers after these changes should be identical to the current output*, for easy testing. Changes which alter output will be in subsequent PRs.
[*With one trivial change in the logger for eigenvalues from \omega/2pi -> f]