Skip to content

Commit 2bb6372

Browse files
AlejandroMunozManterolaCopilot
andcommitted
Add _farfield morstate export for rcs postprocessing
Co-authored-by: Copilot <copilot@github.com>
1 parent 7dd405c commit 2bb6372

3 files changed

Lines changed: 84 additions & 5 deletions

File tree

src/evolution/GlobalEvolution.cpp

Lines changed: 81 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,31 @@ SGBCHelperFields initSGBCHelperFields(const int size)
2929
return res;
3030
}
3131

32+
static mfem::Array<int> buildSurfaceMarkerFromTags(const std::vector<int>& tags, const mfem::ParFiniteElementSpace& fes)
33+
{
34+
mfem::Array<int> marker(fes.GetMesh()->bdr_attributes.Max());
35+
marker = 0;
36+
for (const int t : tags) {
37+
marker[t - 1] = 1;
38+
}
39+
return marker;
40+
}
41+
42+
static std::vector<int> collectRCSSurfaceTags(const Probes& probes)
43+
{
44+
std::unordered_set<int> unique_tags;
45+
for (const auto& p : probes.rcsSurfaceProbes) {
46+
for (const int t : p.tags) {
47+
unique_tags.insert(t);
48+
}
49+
}
50+
std::vector<int> tags(unique_tags.begin(), unique_tags.end());
51+
std::sort(tags.begin(), tags.end());
52+
return tags;
53+
}
54+
3255
GlobalEvolution::GlobalEvolution(
33-
mfem::ParFiniteElementSpace& fes, Model& model, SourcesManager& srcmngr, EvolutionOptions& options) :
56+
mfem::ParFiniteElementSpace& fes, Model& model, SourcesManager& srcmngr, EvolutionOptions& options, const Probes& probes) :
3457
mfem::TimeDependentOperator(numberOfFieldComponents* numberOfMaxDimensions* fes.GetNDofs()),
3558
fes_{ fes },
3659
model_{ model },
@@ -312,7 +335,7 @@ GlobalEvolution::GlobalEvolution(
312335
numberOfFieldComponents * numberOfMaxDimensions * (fes_.GetNDofs() + fes_.num_face_nbr_dofs)
313336
);
314337

315-
Probes probes;
338+
Probes emptyProbes;
316339

317340
// Keep TFSF submesh infrastructure for planewave source evaluation
318341
if (model_.getTotalFieldScatteredFieldToMarker().find(BdrCond::TotalFieldIn) != model_.getTotalFieldScatteredFieldToMarker().end()) {
@@ -323,7 +346,7 @@ GlobalEvolution::GlobalEvolution(
323346
}
324347

325348
// Build all operators on the global mesh
326-
ProblemDescription pd(model_, probes, srcmngr_.sources, opts_);
349+
ProblemDescription pd(model_, emptyProbes, srcmngr_.sources, opts_);
327350
DGOperatorFactory<mfem::ParFiniteElementSpace> dgops(pd, fes_);
328351
globalOperator_ = dgops.buildGlobalOperator();
329352

@@ -371,6 +394,61 @@ GlobalEvolution::GlobalEvolution(
371394
}
372395
}
373396
}
397+
398+
const bool has_rcs_probe = !probes.rcsSurfaceProbes.empty();
399+
const bool has_mor_probe = !probes.morStateProbes.empty();
400+
if (opts_.export_evolution_operator && has_rcs_probe && has_mor_probe) {
401+
if (Mpi::WorldSize() == 1) {
402+
const auto rcs_tags = collectRCSSurfaceTags(probes);
403+
if (!rcs_tags.empty()) {
404+
auto marker = buildSurfaceMarkerFromTags(rcs_tags, fes_);
405+
NearToFarFieldSubMesher ntff_submesher(model_.getConstMesh(), fes_, marker);
406+
407+
auto* ntff_submesh = ntff_submesher.getSubMesh();
408+
auto dgfec = dynamic_cast<const mfem::DG_FECollection*>(fes_.FEColl());
409+
if (!dgfec) {
410+
throw std::runtime_error("The FiniteElementCollection in the FiniteElementSpace is not DG.");
411+
}
412+
413+
mfem::FiniteElementSpace ntff_fes(ntff_submesh, dgfec);
414+
mfem::Array<int> farfield_sub_to_parent_ids;
415+
mfem::SubMeshUtils::BuildVdofToVdofMap(ntff_fes,
416+
fes_,
417+
ntff_submesh->GetFrom(),
418+
ntff_submesh->GetParentElementIDMap(),
419+
farfield_sub_to_parent_ids);
420+
421+
const int farfield_ndofs = farfield_sub_to_parent_ids.Size();
422+
const int parent_ndofs = fes_.GetNDofs();
423+
auto farfield_mapping_matrix = std::make_unique<mfem::SparseMatrix>(6 * farfield_ndofs, 6 * parent_ndofs);
424+
425+
for (int comp = 0; comp < 6; ++comp) {
426+
for (int sub_dof = 0; sub_dof < farfield_ndofs; ++sub_dof) {
427+
const int parent_dof = farfield_sub_to_parent_ids[sub_dof];
428+
const int row = comp * farfield_ndofs + sub_dof;
429+
const int col = comp * parent_ndofs + parent_dof;
430+
farfield_mapping_matrix->Set(row, col, 1.0);
431+
}
432+
}
433+
farfield_mapping_matrix->Finalize();
434+
435+
std::filesystem::path export_dir = std::filesystem::path("Exports") / "Operators" / model_.meshName_;
436+
if (!std::filesystem::exists(export_dir)) {
437+
std::filesystem::create_directories(export_dir);
438+
}
439+
440+
std::filesystem::path farfield_path = export_dir / (model_.meshName_ + "_farfield.csr");
441+
std::ofstream ofs_farfield(farfield_path);
442+
if (!ofs_farfield.is_open()) {
443+
throw std::runtime_error("Could not open file for writing: " + farfield_path.string());
444+
}
445+
farfield_mapping_matrix->PrintCSR2(ofs_farfield);
446+
ofs_farfield.close();
447+
std::cout << "Farfield mapping matrix exported to " << farfield_path << std::endl;
448+
}
449+
}
450+
}
451+
374452
if (model_.getSGBCToMarker().find(BdrCond::SGBC) != model_.getSGBCToMarker().end()) {
375453
SGBCOperator_ = dgops.buildSGBCGlobalOperator();
376454
}

src/evolution/GlobalEvolution.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "solver/SourcesManager.h"
44
#include "solver/SolverExtension.h"
55
#include "components/DGOperatorFactory.h"
6+
#include "components/Probes.h"
67
#include <unordered_map>
78

89
namespace maxwell {
@@ -16,7 +17,7 @@ class GlobalEvolution : public mfem::TimeDependentOperator {
1617
static const int numberOfFieldComponents = 2;
1718
static const int numberOfMaxDimensions = 3;
1819

19-
GlobalEvolution(mfem::ParFiniteElementSpace&, Model&, SourcesManager&, EvolutionOptions&);
20+
GlobalEvolution(mfem::ParFiniteElementSpace&, Model&, SourcesManager&, EvolutionOptions&, const Probes&);
2021
~GlobalEvolution();
2122

2223
virtual void Mult(const mfem::Vector& x, mfem::Vector& y) const;

src/solver/Solver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ std::unique_ptr<mfem::TimeDependentOperator> Solver::assignEvolutionOperator()
4343
return std::make_unique<HesthavenEvolution>(*fes_, model_, sourcesManager_, opts_.evolution);
4444
}
4545
else if (opts_.evolution.op == EvolutionOperatorType::Global) {
46-
auto global_evol = std::make_unique<GlobalEvolution>(*fes_, model_, sourcesManager_, opts_.evolution);
46+
auto global_evol = std::make_unique<GlobalEvolution>(*fes_, model_, sourcesManager_, opts_.evolution, probesManager_.probes);
4747
globalEvol_cache_ = global_evol.get(); // Cache the pointer
4848
return global_evol;
4949
}

0 commit comments

Comments
 (0)