Skip to content

Commit eef61b9

Browse files
committed
Address PR feedback (Round 1)
- Improve comments - Add verifications and small code cleaning
1 parent 0f037b0 commit eef61b9

File tree

5 files changed

+43
-23
lines changed

5 files changed

+43
-23
lines changed

palace/drivers/drivensolver.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -384,10 +384,7 @@ ErrorIndicator DrivenSolver::SweepAdaptive(SpaceOperator &space_op) const
384384
{
385385
BlockTimer bt0(Timer::POSTPRO);
386386
Mpi::Print(" Printing PROM Matrices to disk.\n");
387-
if (root)
388-
{
389-
prom_op.PrintPROMMatrices(iodata.units, iodata.problem.output);
390-
}
387+
prom_op.PrintPROMMatrices(iodata.units, iodata.problem.output);
391388
}
392389

393390
// XX TODO: Add output of eigenvalue estimates from the PROM system (and nonlinear EVP

palace/models/romoperator.cpp

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,11 @@ std::vector<double> MinimalRationalInterpolation::FindMaxError(std::size_t N) co
279279
// }
280280

281281
// Fall back to sampling Q on discrete points if no roots exist in [start, end].
282-
// TODO: currently we always us this. Consider other optimization above again.
282+
//
283+
// TODO: Currently we always use this brute for sampling and we could optimize this more.
284+
// Also, the case of N>1 samples is not very useful below. It will typically give us
285+
// multiple sample points right next to each other in the same local maximum, rather than
286+
// N separate local maxima.
283287

284288
// We could use priority queue here to keep the N lowest values. However, we don't use
285289
// std::priority_queue class since we want to have access to the vector and also binary
@@ -289,6 +293,10 @@ std::vector<double> MinimalRationalInterpolation::FindMaxError(std::size_t N) co
289293
queue.reserve(N);
290294

291295
const std::size_t nr_sample = 1.0e6; // must be >= N
296+
MFEM_VERIFY(N < nr_sample,
297+
fmt::format("Number of location of error maximum N={} needs to be less than "
298+
"the fine sampling grid nr_sample={}.",
299+
N, nr_sample));
292300
const auto delta = (end - start) / nr_sample;
293301
for (double z_sample = start; z_sample <= end; z_sample += delta)
294302
{
@@ -348,7 +356,7 @@ RomOperator::RomOperator(const IoData &iodata, SpaceOperator &space_op,
348356
max_prom_size += space_op.GetLumpedPortOp().Size(); // Lumped ports are real fields
349357
}
350358

351-
// Reserve empty vectors but don't pre-allocate actual memory size due to overhead.
359+
// Reserve empty vectors.
352360
V.reserve(max_prom_size);
353361
v_node_label.reserve(max_prom_size);
354362

@@ -362,7 +370,7 @@ RomOperator::RomOperator(const IoData &iodata, SpaceOperator &space_op,
362370
void RomOperator::SetExcitationIndex(int excitation_idx)
363371
{
364372
// Return if cached. Ctor constructs with excitation_idx_cache = 0 which is not a valid
365-
// expiation index, so this is triggered the first time it is called in drivensolver.
373+
// excitation index, so this is triggered the first time it is called in drivensolver.
366374
if (excitation_idx_cache == excitation_idx)
367375
{
368376
return;
@@ -442,27 +450,30 @@ void RomOperator::UpdatePROM(const ComplexVector &u, std::string_view node_label
442450

443451
orth_R.conservativeResizeLike(Eigen::MatrixXd::Zero(dim_V_new, dim_V_new));
444452

445-
auto add_real_vector_to_basis = [this](const Vector &vector, std::string_view full_label)
453+
auto add_real_vector_to_basis = [this](const Vector &vector)
446454
{
447455
auto dim_V = V.size();
448-
V.push_back(vector);
449-
OrthogonalizeColumn(orthog_type, space_op.GetComm(), V, V.back(),
450-
orth_R.col(dim_V).data(), dim_V);
451-
orth_R(dim_V, dim_V) = linalg::Norml2(space_op.GetComm(), V.back());
452-
V.back() *= 1.0 / orth_R(dim_V, dim_V);
453-
v_node_label.emplace_back(full_label);
456+
auto &v = V.emplace_back(vector);
457+
OrthogonalizeColumn(orthog_type, space_op.GetComm(), V, v, orth_R.col(dim_V).data(),
458+
dim_V);
459+
orth_R(dim_V, dim_V) = linalg::Norml2(space_op.GetComm(), v);
460+
v *= 1.0 / orth_R(dim_V, dim_V);
454461
};
455462

456463
if (has_real)
457464
{
458-
add_real_vector_to_basis(u.Real(), fmt::format("{}_re", node_label));
465+
add_real_vector_to_basis(u.Real());
466+
v_node_label.emplace_back(fmt::format("{}_re", node_label));
459467
}
460468
if (has_imag)
461469
{
462-
add_real_vector_to_basis(u.Imag(), fmt::format("{}_im", node_label));
470+
add_real_vector_to_basis(u.Imag());
471+
v_node_label.emplace_back(fmt::format("{}_im", node_label));
463472
}
464473

465-
// Update reduced-order operators.
474+
// Update reduced-order operators. Resize preserves the upper dim0 x dim0 block of each
475+
// matrix and first dim0 entries of each vector and the projection uses the values
476+
// computed for the unchanged basis vectors.
466477
Kr.conservativeResize(dim_V_new, dim_V_new);
467478
ProjectMatInternal(comm, V, *K, Kr, r, dim_V_old);
468479
if (C)
@@ -561,10 +572,14 @@ std::vector<std::complex<double>> RomOperator::ComputeEigenvalueEstimates() cons
561572

562573
void RomOperator::PrintPROMMatrices(const Units &units, const fs::path &post_dir) const
563574
{
575+
if (!Mpi::Root(space_op.GetComm()))
576+
{
577+
return;
578+
}
564579
auto print_table = [post_dir, labels = this->v_node_label](const Eigen::MatrixXd &mat,
565580
std::string_view filename)
566581
{
567-
MFEM_VERIFY(labels.size() == mat.cols(), "Insonsistent PROM size!");
582+
MFEM_VERIFY(labels.size() == mat.cols(), "Inconsistent PROM size!");
568583
auto out = TableWithCSVFile(post_dir / filename);
569584
out.table.col_options.float_precision = 17;
570585
for (long i = 0; i < mat.cols(); i++)

palace/models/romoperator.hpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,11 @@ class RomOperator
9090
std::vector<Vector> V;
9191
Orthogonalization orthog_type;
9292

93-
// Label to distinguish port modes from solution projection and to print PROM matrices
93+
// Label to distinguish port modes from solution projection and to print PROM matrices.
9494
std::vector<std::string> v_node_label;
9595

96-
// Upper-triangular orthognoalization matrix R; U = VR with U modes. Memory pre-allocated.
96+
// Upper-triangular matrix R from orthogonalization procedure U = VR. Here U the HDM
97+
// fields added by `UpdatePROM`.
9798
Eigen::MatrixXd orth_R;
9899

99100
// MRIs: one for each excitation index. Only used to pick new frequency sample point.
@@ -115,7 +116,7 @@ class RomOperator
115116
return mri.at(excitation_idx).GetSamplePoints();
116117
}
117118

118-
// Return overlap matrix form orthogonalization of vectors in ROM.
119+
// Upper-triangular matrix of from orthogonalization of HDM fields added to PROM.
119120
const auto &GetRomOrthogonalityMatrix() const { return orth_R; }
120121

121122
// Set excitation index to build corresponding RHS vector (linear in frequency part).
@@ -124,7 +125,10 @@ class RomOperator
124125
// Assemble and solve the HDM at the specified frequency.
125126
void SolveHDM(int excitation_idx, double omega, ComplexVector &u);
126127

127-
// Add field configuration to the reduced-order basis and update the PROM.
128+
// Add field configuration to the reduced-order basis and update the PROM. Requires a name
129+
// "node_label". This will be printed in the header of the csv files when printing PROM
130+
// matrices. It is needed to distinguish port and solution field configuration as well as
131+
// to reconstruct if field configuration are pure real, imaginary or complex.
128132
void UpdatePROM(const ComplexVector &u, std::string_view node_label);
129133

130134
// Add solution u to the minimal-rational interpolation for error estimation. MRI are

palace/utils/configfile.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1898,6 +1898,7 @@ void DrivenSolverData::SetUp(json &solver)
18981898
std::cout << "AdaptiveTol: " << adaptive_tol << '\n';
18991899
std::cout << "AdaptiveMaxSamples: " << adaptive_max_size << '\n';
19001900
std::cout << "AdaptiveConvergenceMemory: " << adaptive_memory << '\n';
1901+
std::cout << "AdaptiveCircuitSynthesis: " << adaptive_circuit_synthesis << '\n';
19011902
}
19021903

19031904
// Cleanup

test/unit/test-romoperator.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
14
#include <iterator>
25
#include <vector>
36
#include <fmt/format.h>
@@ -43,7 +46,7 @@ TEST_CASE("MinimalRationalInterpolation", "[romoperator][Serial][Parallel]")
4346
auto max_err_1 = mri_1.FindMaxError(5);
4447
REQUIRE(max_err_1.size() == 5);
4548

46-
// By symmetry highest error should be at at zero.
49+
// By symmetry highest error should be at zero.
4750
CHECK_THAT(max_err_1[0], Catch::Matchers::WithinAbsMatcher(0.0, 1e-6));
4851

4952
// Test that elements of max_error are unique.

0 commit comments

Comments
 (0)