diff --git a/include/main_workflow.hpp b/include/main_workflow.hpp index f52f07e7..8fcf9043 100644 --- a/include/main_workflow.hpp +++ b/include/main_workflow.hpp @@ -15,7 +15,7 @@ void RunExample(); MultiBlockSolver* InitSolver(); SampleGenerator* InitSampleGenerator(MPI_Comm comm); -std::vector GetGlobalBasisTagList(const TopologyHandlerMode &topol_mode, const TrainMode &train_mode, bool separate_variable_basis); +std::vector GetGlobalBasisTagList(const TopologyHandlerMode &topol_mode, bool separate_variable_basis); void GenerateSamples(MPI_Comm comm); void CollectSamples(SampleGenerator *sample_generator); diff --git a/include/multiblock_solver.hpp b/include/multiblock_solver.hpp index 8e0dfe0b..9311ccc6 100644 --- a/include/multiblock_solver.hpp +++ b/include/multiblock_solver.hpp @@ -108,7 +108,6 @@ friend class ParameterizedProblem; // rom variables. ROMHandlerBase *rom_handler = NULL; - TrainMode train_mode = NUM_TRAINMODE; bool use_rom = false; bool separate_variable_basis = false; @@ -136,7 +135,6 @@ friend class ParameterizedProblem; const bool UseRom() const { return use_rom; } ROMHandlerBase* GetROMHandler() const { return rom_handler; } TopologyHandler* GetTopologyHandler() const { return topol_handler; } - const TrainMode GetTrainMode() { return train_mode; } const bool IsVisualizationSaved() const { return visual.save; } const std::string GetSolutionFilePrefix() const { return sol_prefix; } const std::string GetVisualizationPrefix() const { return visual.prefix; } diff --git a/include/rom_handler.hpp b/include/rom_handler.hpp index 303d4caa..98df6134 100644 --- a/include/rom_handler.hpp +++ b/include/rom_handler.hpp @@ -15,13 +15,6 @@ namespace mfem { -enum TrainMode -{ - INDIVIDUAL, - UNIVERSAL, - NUM_TRAINMODE -}; - enum ROMBuildingLevel { NONE, @@ -37,10 +30,8 @@ enum NonlinearHandling NUM_NLNHNDL }; -const TrainMode SetTrainMode(); - -const std::string GetBasisTagForComponent(const int &comp_idx, const TrainMode &train_mode, const TopologyHandler *topol_handler, const std::string var_name=""); -const std::string GetBasisTag(const int &subdomain_index, const TrainMode &train_mode, const TopologyHandler *topol_handler, const std::string var_name=""); +const std::string GetBasisTagForComponent(const int &comp_idx, const TopologyHandler *topol_handler, const std::string var_name=""); +const std::string GetBasisTag(const int &subdomain_index, const TopologyHandler *topol_handler, const std::string var_name=""); class ROMHandlerBase { @@ -61,7 +52,6 @@ class ROMHandlerBase bool component_sampling = false; bool save_lspg_basis = false; ROMBuildingLevel save_operator = NUM_BLD_LVL; - TrainMode train_mode = NUM_TRAINMODE; bool nonlinear_mode = false; bool separate_variable = false; NonlinearHandling nlin_handle = NUM_NLNHNDL; @@ -120,14 +110,13 @@ class ROMHandlerBase void ParseInputs(); public: - ROMHandlerBase(const TrainMode &train_mode_, TopologyHandler *input_topol, - const Array &input_var_offsets, const std::vector &var_names, const bool separate_variable_basis); + ROMHandlerBase(TopologyHandler *input_topol, const Array &input_var_offsets, + const std::vector &var_names, const bool separate_variable_basis); virtual ~ROMHandlerBase(); // access const int GetNumSubdomains() { return numSub; } - const TrainMode GetTrainMode() { return train_mode; } const int GetNumROMRefComps() { return num_rom_comp; } const int GetNumROMRefBlocks() { return num_rom_ref_blocks; } const int GetRefNumBasis(const int &basis_idx) { return num_ref_basis[basis_idx]; } @@ -232,8 +221,8 @@ class MFEMROMHandler : public ROMHandlerBase mfem::BlockVector *reduced_sol = NULL; public: - MFEMROMHandler(const TrainMode &train_mode_, TopologyHandler *input_topol, - const Array &input_var_offsets, const std::vector &var_names, const bool separate_variable_basis); + MFEMROMHandler(TopologyHandler *input_topol, const Array &input_var_offsets, + const std::vector &var_names, const bool separate_variable_basis); virtual ~MFEMROMHandler(); diff --git a/include/sample_generator.hpp b/include/sample_generator.hpp index 3fabdceb..5bca52d2 100644 --- a/include/sample_generator.hpp +++ b/include/sample_generator.hpp @@ -111,7 +111,7 @@ class SampleGenerator The appended column indices of each basis tag are stored in col_idxs. */ void SaveSnapshot(BlockVector *U_snapshots, std::vector &snapshot_basis_tags, Array &col_idxs); - void SaveSnapshotPorts(TopologyHandler *topol_handler, const TrainMode &train_mode, const Array &col_idxs); + void SaveSnapshotPorts(TopologyHandler *topol_handler, const Array &col_idxs); void AddSnapshotGenerator(const int &fom_vdofs, const std::string &prefix, const std::string &basis_tag); void WriteSnapshots(); void WriteSnapshotPorts(); diff --git a/src/advdiff_solver.cpp b/src/advdiff_solver.cpp index 94b486f9..f4c21dd3 100644 --- a/src/advdiff_solver.cpp +++ b/src/advdiff_solver.cpp @@ -51,7 +51,6 @@ void AdvDiffSolver::BuildCompROMLinElems() { mfem_error("AdvDiffSolver::BuildCompROMLinElems is not implemented yet!\n"); - assert(train_mode == UNIVERSAL); assert(rom_handler->BasisLoaded()); assert(rom_elems); diff --git a/src/linelast_solver.cpp b/src/linelast_solver.cpp index a36b6193..70e89e74 100644 --- a/src/linelast_solver.cpp +++ b/src/linelast_solver.cpp @@ -500,7 +500,6 @@ void LinElastSolver::ProjectOperatorOnReducedBasis() // Component-wise assembly void LinElastSolver::BuildCompROMLinElems() { - assert(train_mode == UNIVERSAL); assert(rom_handler->BasisLoaded()); assert(rom_elems); @@ -524,7 +523,6 @@ void LinElastSolver::BuildCompROMLinElems() void LinElastSolver::BuildBdrROMLinElems() { - assert(train_mode == UNIVERSAL); assert(rom_handler->BasisLoaded()); assert(rom_elems); @@ -555,7 +553,6 @@ void LinElastSolver::BuildBdrROMLinElems() void LinElastSolver::BuildItfaceROMLinElems() { assert(topol_mode == TopologyHandlerMode::COMPONENT); - assert(train_mode == UNIVERSAL); assert(rom_handler->BasisLoaded()); assert(rom_elems); diff --git a/src/main_workflow.cpp b/src/main_workflow.cpp index e2c5996f..0d71af25 100644 --- a/src/main_workflow.cpp +++ b/src/main_workflow.cpp @@ -90,40 +90,28 @@ SampleGenerator* InitSampleGenerator(MPI_Comm comm) return generator; } -std::vector GetGlobalBasisTagList(const TopologyHandlerMode &topol_mode, const TrainMode &train_mode, bool separate_variable_basis) +std::vector GetGlobalBasisTagList(const TopologyHandlerMode &topol_mode, bool separate_variable_basis) { std::vector basis_tags(0); std::vector component_list(0); - if (train_mode == TrainMode::INDIVIDUAL) + if (topol_mode == TopologyHandlerMode::SUBMESH) { - TopologyHandler *topol_handler; - if (topol_mode == TopologyHandlerMode::SUBMESH) topol_handler = new SubMeshTopologyHandler(); - else if (topol_mode == TopologyHandlerMode::COMPONENT) topol_handler = new ComponentTopologyHandler(); - else - mfem_error("GetGlobalBasisTagList - TopologyHandlerMode is not set!\n"); - - for (int c = 0; c < topol_handler->GetNumSubdomains(); c++) - component_list.push_back("dom" + std::to_string(c)); + TopologyHandler *topol_handler = new SubMeshTopologyHandler(); + for (int c = 0; c < topol_handler->GetNumComponents(); c++) + component_list.push_back(topol_handler->GetComponentName(c)); delete topol_handler; } - else // if (train_mode == TrainMode::UNIVERSAL) + else if (topol_mode == TopologyHandlerMode::COMPONENT) { - if (topol_mode == TopologyHandlerMode::SUBMESH) - { - component_list.push_back("comp0"); - } - else if (topol_mode == TopologyHandlerMode::COMPONENT) - { - YAML::Node component_dict = config.FindNode("mesh/component-wise/components"); - assert(component_dict); - for (int p = 0; p < component_dict.size(); p++) - component_list.push_back(config.GetRequiredOptionFromDict("name", component_dict[p])); - } - else - mfem_error("GetGlobalBasisTagList - TopologyHandlerMode is not set!\n"); - } // if (train_mode == TrainMode::UNIVERSAL) + YAML::Node component_dict = config.FindNode("mesh/component-wise/components"); + assert(component_dict); + for (int p = 0; p < component_dict.size(); p++) + component_list.push_back(config.GetRequiredOptionFromDict("name", component_dict[p])); + } + else + mfem_error("GetGlobalBasisTagList - TopologyHandlerMode is not set!\n"); std::vector var_list(0); if (separate_variable_basis) @@ -223,11 +211,10 @@ void CollectSamples(SampleGenerator *sample_generator) assert(sample_generator); TopologyHandlerMode topol_mode = SetTopologyHandlerMode(); - TrainMode train_mode = SetTrainMode(); bool separate_variable_basis = config.GetOption("model_reduction/separate_variable_basis", false); // Find the all required basis tags. - std::vector basis_tags = GetGlobalBasisTagList(topol_mode, train_mode, separate_variable_basis); + std::vector basis_tags = GetGlobalBasisTagList(topol_mode, separate_variable_basis); // tag-specific optional inputs. YAML::Node basis_list = config.FindNode("basis/tags"); diff --git a/src/multiblock_solver.cpp b/src/multiblock_solver.cpp index 8eff3288..fdd24bc3 100644 --- a/src/multiblock_solver.cpp +++ b/src/multiblock_solver.cpp @@ -116,8 +116,6 @@ void MultiBlockSolver::ParseInputs() use_rom = config.GetOption("main/use_rom", false); separate_variable_basis = config.GetOption("model_reduction/separate_variable_basis", false); - train_mode = SetTrainMode(); - // save solution if single run. SetSolutionSaveMode(config.GetOption("save_solution/enabled", false)); } @@ -261,7 +259,6 @@ void MultiBlockSolver::GetComponentFESpaces(Array &comp_fe void MultiBlockSolver::BuildROMLinElems() { assert(topol_mode == TopologyHandlerMode::COMPONENT); - assert(train_mode == UNIVERSAL); assert(rom_handler->BasisLoaded()); BuildCompROMLinElems(); @@ -276,7 +273,6 @@ void MultiBlockSolver::BuildROMLinElems() void MultiBlockSolver::AssembleROMMat() { assert(topol_mode == TopologyHandlerMode::COMPONENT); - assert(train_mode == UNIVERSAL); assert(rom_elems); const Array *rom_block_offsets = rom_handler->GetBlockOffsets(); @@ -658,9 +654,9 @@ void MultiBlockSolver::AssembleROMNlinOper() void MultiBlockSolver::InitROMHandler() { - rom_handler = new MFEMROMHandler(train_mode, topol_handler, var_offsets, var_names, separate_variable_basis); + rom_handler = new MFEMROMHandler(topol_handler, var_offsets, var_names, separate_variable_basis); - if (!((topol_mode == TopologyHandlerMode::COMPONENT) && (train_mode == UNIVERSAL))) + if (!(topol_mode == TopologyHandlerMode::COMPONENT)) return; GetComponentFESpaces(comp_fes); @@ -674,13 +670,13 @@ void MultiBlockSolver::GetBasisTags(std::vector &basis_tags) basis_tags.resize(numSub * num_var); for (int m = 0, idx = 0; m < numSub; m++) for (int v = 0; v < num_var; v++, idx++) - basis_tags[idx] = GetBasisTag(m, train_mode, topol_handler, var_names[v]); + basis_tags[idx] = GetBasisTag(m, topol_handler, var_names[v]); } else { basis_tags.resize(numSub); for (int m = 0; m < numSub; m++) - basis_tags[m] = GetBasisTag(m, train_mode, topol_handler); + basis_tags[m] = GetBasisTag(m, topol_handler); } } @@ -710,7 +706,7 @@ void MultiBlockSolver::SaveSnapshots(SampleGenerator *sample_generator) Array col_idxs; sample_generator->SaveSnapshot(U_snapshots, basis_tags, col_idxs); - sample_generator->SaveSnapshotPorts(topol_handler, train_mode, col_idxs); + sample_generator->SaveSnapshotPorts(topol_handler, col_idxs); /* delete only the view vector, not the data itself. */ delete U_snapshots; diff --git a/src/poisson_solver.cpp b/src/poisson_solver.cpp index b4f23a5c..7c4284fc 100644 --- a/src/poisson_solver.cpp +++ b/src/poisson_solver.cpp @@ -344,7 +344,6 @@ void PoissonSolver::AssembleInterfaceMatrices() void PoissonSolver::BuildCompROMLinElems() { - assert(train_mode == UNIVERSAL); assert(rom_handler->BasisLoaded()); assert(rom_elems); @@ -368,7 +367,6 @@ void PoissonSolver::BuildCompROMLinElems() void PoissonSolver::BuildBdrROMLinElems() { - assert(train_mode == UNIVERSAL); assert(rom_handler->BasisLoaded()); assert(rom_elems); @@ -399,7 +397,6 @@ void PoissonSolver::BuildBdrROMLinElems() void PoissonSolver::BuildItfaceROMLinElems() { assert(topol_mode == TopologyHandlerMode::COMPONENT); - assert(train_mode == UNIVERSAL); assert(rom_handler->BasisLoaded()); assert(rom_elems); diff --git a/src/rom_handler.cpp b/src/rom_handler.cpp index 3c1a0085..e6311c08 100644 --- a/src/rom_handler.cpp +++ b/src/rom_handler.cpp @@ -16,71 +16,26 @@ using namespace std; namespace mfem { -const TrainMode SetTrainMode() -{ - TrainMode train_mode = TrainMode::NUM_TRAINMODE; - - std::string train_mode_str = config.GetOption("model_reduction/subdomain_training", "individual"); - if (train_mode_str == "individual") train_mode = TrainMode::INDIVIDUAL; - else if (train_mode_str == "universal") train_mode = TrainMode::UNIVERSAL; - else - mfem_error("Unknown subdomain training mode!\n"); - - return train_mode; -} - const std::string GetBasisTagForComponent( - const int &comp_idx, const TrainMode &train_mode, const TopologyHandler *topol_handler, const std::string var_name) + const int &comp_idx, const TopologyHandler *topol_handler, const std::string var_name) { - std::string tag; - switch (train_mode) - { - case (INDIVIDUAL): { tag = "dom" + std::to_string(comp_idx); break; } - case (UNIVERSAL): { tag = topol_handler->GetComponentName(comp_idx); break; } - default: - { - mfem_error("ROMHandler::GetBasisTagForComponent - Unknown training mode!\n"); - break; - } - } + std::string tag = topol_handler->GetComponentName(comp_idx); if (var_name != "") tag += "_" + var_name; return tag; } const std::string GetBasisTag( - const int &subdomain_index, const TrainMode &train_mode, const TopologyHandler *topol_handler, const std::string var_name) + const int &subdomain_index, const TopologyHandler *topol_handler, const std::string var_name) { - std::string tag; - switch (train_mode) - { - case (INDIVIDUAL): - { - tag = "dom" + std::to_string(subdomain_index); - break; - } - case (UNIVERSAL): - { - int c_type = topol_handler->GetMeshType(subdomain_index); - tag = topol_handler->GetComponentName(c_type); - break; - } - default: - { - mfem_error("ROMHandler::GetBasisTag - Unknown training mode!\n"); - break; - } - } - if (var_name != "") - tag += "_" + var_name; - return tag; + int c_type = topol_handler->GetMeshType(subdomain_index); + return GetBasisTagForComponent(c_type, topol_handler, var_name); } ROMHandlerBase::ROMHandlerBase( - const TrainMode &train_mode_, TopologyHandler *input_topol, const Array &input_var_offsets, + TopologyHandler *input_topol, const Array &input_var_offsets, const std::vector &var_names, const bool separate_variable_basis) - : train_mode(train_mode_), - topol_handler(input_topol), + : topol_handler(input_topol), numSub(input_topol->GetNumSubdomains()), fom_var_names(var_names), fom_var_offsets(input_var_offsets), @@ -127,10 +82,7 @@ void ROMHandlerBase::ParseInputs() operator_prefix = config.GetRequiredOption("model_reduction/save_operator/prefix"); num_rom_blocks = numSub; - if (train_mode == TrainMode::INDIVIDUAL) num_rom_ref_blocks = numSub; - else if (train_mode == TrainMode::UNIVERSAL) num_rom_ref_blocks = topol_handler->GetNumComponents(); - else - mfem_error("ROMHandler - subdomain training mode is not set!\n"); + num_rom_ref_blocks = topol_handler->GetNumComponents(); num_rom_comp = num_rom_ref_blocks; @@ -155,9 +107,9 @@ void ROMHandlerBase::ParseInputs() /* determine basis tag */ std::string basis_tag; if (separate_variable) - basis_tag = GetBasisTagForComponent(b / num_var, train_mode, topol_handler, fom_var_names[b % num_var]); + basis_tag = GetBasisTagForComponent(b / num_var, topol_handler, fom_var_names[b % num_var]); else - basis_tag = GetBasisTagForComponent(b, train_mode, topol_handler); + basis_tag = GetBasisTagForComponent(b, topol_handler); /* determine number of basis */ num_ref_basis[b] = config.LookUpFromDict("name", basis_tag, "number_of_basis", num_ref_basis_default, basis_list); @@ -169,31 +121,21 @@ void ROMHandlerBase::ParseInputs() } /* parse the dimension of basis */ - if (train_mode == TrainMode::INDIVIDUAL) - { - if (separate_variable) - dim_ref_basis[b] = fom_var_offsets[b+1] - fom_var_offsets[b]; - else - dim_ref_basis[b] = fom_num_vdofs[b]; - } // if (train_mode == TrainMode::INDIVIDUAL) - else // if (train_mode == TrainMode::UNIVERSAL) - { - int midx = -1; - int vidx = (separate_variable) ? b % num_var : 0; - for (int m = 0; m < numSub; m++) - if (topol_handler->GetMeshType(m) == (separate_variable ? b / num_var : b)) - { - midx = m; - break; - } - assert(midx >= 0); - - int idx = (separate_variable) ? midx * num_var + vidx : midx; - if (separate_variable) - dim_ref_basis[b] = fom_var_offsets[idx + 1] - fom_var_offsets[idx]; - else - dim_ref_basis[b] = fom_num_vdofs[idx]; - } // if (train_mode == TrainMode::UNIVERSAL) + int midx = -1; + int vidx = (separate_variable) ? b % num_var : 0; + for (int m = 0; m < numSub; m++) + if (topol_handler->GetMeshType(m) == (separate_variable ? b / num_var : b)) + { + midx = m; + break; + } + assert(midx >= 0); + + int idx = (separate_variable) ? midx * num_var + vidx : midx; + if (separate_variable) + dim_ref_basis[b] = fom_var_offsets[idx + 1] - fom_var_offsets[idx]; + else + dim_ref_basis[b] = fom_num_vdofs[idx]; } // for (int b = 0; b < num_rom_ref_blocks; b++) for (int k = 0; k < num_ref_basis.Size(); k++) @@ -228,17 +170,11 @@ void ROMHandlerBase::ParseSupremizerInput(Array &num_ref_supreme, ArrayGetMeshType(m); @@ -258,9 +194,9 @@ void ROMHandlerBase::LoadReducedBasis() for (int k = 0; k < num_rom_ref_blocks; k++) { if (separate_variable) - basis_tags[k] = GetBasisTagForComponent(k / num_var, train_mode, topol_handler, fom_var_names[k % num_var]); + basis_tags[k] = GetBasisTagForComponent(k / num_var, topol_handler, fom_var_names[k % num_var]); else - basis_tags[k] = GetBasisTagForComponent(k, train_mode, topol_handler); + basis_tags[k] = GetBasisTagForComponent(k, topol_handler); /* TODO(kevin): this is a boilerplate for parallel POD/EQP training. @@ -286,17 +222,7 @@ void ROMHandlerBase::LoadReducedBasis() int ROMHandlerBase::GetRefIndexForSubdomain(const int &subdomain_index) { - int idx = -1; - switch (train_mode) - { - case TrainMode::UNIVERSAL: - { idx = topol_handler->GetMeshType(subdomain_index); break; } - case TrainMode::INDIVIDUAL: - { idx = subdomain_index; break; } - default: - { mfem_error("LoadBasis: unknown TrainMode!\n"); break; } - } // switch (train_mode) - + int idx = topol_handler->GetMeshType(subdomain_index); assert(idx >= 0); return idx; } @@ -351,8 +277,10 @@ void ROMHandlerBase::SetBlockSizes() MFEMROMHandler */ -MFEMROMHandler::MFEMROMHandler(const TrainMode &train_mode_, TopologyHandler *input_topol, const Array &input_var_offsets, const std::vector &var_names, const bool separate_variable_basis) - : ROMHandlerBase(train_mode_, input_topol, input_var_offsets, var_names, separate_variable_basis) +MFEMROMHandler::MFEMROMHandler( + TopologyHandler *input_topol, const Array &input_var_offsets, + const std::vector &var_names, const bool separate_variable_basis) + : ROMHandlerBase(input_topol, input_var_offsets, var_names, separate_variable_basis) { romMat = new BlockMatrix(rom_block_offsets); romMat->owns_blocks = true; @@ -409,12 +337,6 @@ void MFEMROMHandler::LoadReducedBasis() dom_basis.SetSize(num_rom_blocks); for (int k = 0; k < num_rom_blocks; k++) { - if (train_mode == TrainMode::INDIVIDUAL) - { - dom_basis[k] = ref_basis[k]; - continue; - } - int m = (separate_variable) ? k / num_var : k; int c = topol_handler->GetMeshType(m); int v = (separate_variable) ? k % num_var : 0; @@ -969,8 +891,6 @@ void MFEMROMHandler::SaveBasisVisualization( assert(fes.Size() == num_var * numSub); std::string visual_prefix = config.GetRequiredOption("basis/visualization/prefix"); - if (train_mode == TrainMode::UNIVERSAL) - visual_prefix += "_universal"; for (int c = 0; c < num_rom_ref_blocks; c++) { @@ -978,16 +898,8 @@ void MFEMROMHandler::SaveBasisVisualization( file_prefix += "_" + std::to_string(c); int midx = -1; - switch (train_mode) { - case (TrainMode::INDIVIDUAL): midx = c; break; - case (TrainMode::UNIVERSAL): - { - for (int m = 0; m < numSub; m++) - if (topol_handler->GetMeshType(m) == c) { midx = m; break; } - break; - } - default: mfem_error("Unknown train mode!\n"); break; - } + for (int m = 0; m < numSub; m++) + if (topol_handler->GetMeshType(m) == c) { midx = m; break; } assert(midx >= 0); Mesh *mesh = fes[midx * num_var]->GetMesh(); diff --git a/src/sample_generator.cpp b/src/sample_generator.cpp index 3a6d5658..b2c22b57 100644 --- a/src/sample_generator.cpp +++ b/src/sample_generator.cpp @@ -202,7 +202,7 @@ void SampleGenerator::SaveSnapshot(BlockVector *U_snapshots, std::vector &col_idxs) +void SampleGenerator::SaveSnapshotPorts(TopologyHandler *topol_handler, const Array &col_idxs) { assert(topol_handler); const int numSub = topol_handler->GetNumSubdomains(); @@ -217,14 +217,14 @@ void SampleGenerator::SaveSnapshotPorts(TopologyHandler *topol_handler, const Tr const PortInfo *port = topol_handler->GetPortInfo(p); /* - We save the snapshot ports by dom%d (INDIVIDUAL) or component names (UNIVERSAL). + We save the snapshot ports by component names. Variable separation does not matter at this point. Though we use basis tags here, it is only for the sake of getting consistent domain/component mesh names. */ std::string mesh1, mesh2; - mesh1 = GetBasisTag(port->Mesh1, train_mode, topol_handler); - mesh2 = GetBasisTag(port->Mesh2, train_mode, topol_handler); + mesh1 = GetBasisTag(port->Mesh1, topol_handler); + mesh2 = GetBasisTag(port->Mesh2, topol_handler); /* note the mesh names are not necessarily the same as the subdomain names diff --git a/src/steady_ns_solver.cpp b/src/steady_ns_solver.cpp index 2fc0efeb..d9196095 100644 --- a/src/steady_ns_solver.cpp +++ b/src/steady_ns_solver.cpp @@ -632,7 +632,6 @@ void SteadyNSSolver::SolveROM() void SteadyNSSolver::AllocateROMTensorElems() { assert(topol_mode == TopologyHandlerMode::COMPONENT); - assert(train_mode == UNIVERSAL); const int num_comp = topol_handler->GetNumComponents(); comp_tensors.SetSize(num_comp); @@ -642,7 +641,6 @@ void SteadyNSSolver::AllocateROMTensorElems() void SteadyNSSolver::BuildROMTensorElems() { assert(topol_mode == TopologyHandlerMode::COMPONENT); - assert(train_mode == UNIVERSAL); assert(rom_handler->BasisLoaded()); // Component domain system @@ -667,7 +665,6 @@ void SteadyNSSolver::BuildROMTensorElems() void SteadyNSSolver::SaveROMTensorElems(const std::string &filename) { assert(topol_mode == TopologyHandlerMode::COMPONENT); - assert(train_mode == UNIVERSAL); assert(FileExists(filename)); hid_t file_id; @@ -709,7 +706,6 @@ void SteadyNSSolver::SaveROMTensorElems(const std::string &filename) void SteadyNSSolver::LoadROMTensorElems(const std::string &filename) { assert(topol_mode == TopologyHandlerMode::COMPONENT); - assert(train_mode == UNIVERSAL); hid_t file_id; herr_t errf = 0; @@ -749,7 +745,6 @@ void SteadyNSSolver::LoadROMTensorElems(const std::string &filename) void SteadyNSSolver::AssembleROMTensorOper() { assert(topol_mode == TopologyHandlerMode::COMPONENT); - assert(train_mode == UNIVERSAL); const int num_comp = topol_handler->GetNumComponents(); assert(comp_tensors.Size() == num_comp); @@ -764,7 +759,6 @@ void SteadyNSSolver::AssembleROMTensorOper() void SteadyNSSolver::AllocateROMEQPElems() { assert(topol_mode == TopologyHandlerMode::COMPONENT); - assert(train_mode == UNIVERSAL); assert(rom_handler); assert(rom_handler->BasisLoaded()); @@ -794,7 +788,6 @@ void SteadyNSSolver::AllocateROMEQPElems() void SteadyNSSolver::TrainEQPElems(SampleGenerator *sample_generator) { assert(topol_mode == TopologyHandlerMode::COMPONENT); - assert(train_mode == UNIVERSAL); assert(sample_generator); assert(rom_handler); @@ -820,7 +813,6 @@ void SteadyNSSolver::TrainEQPElems(SampleGenerator *sample_generator) void SteadyNSSolver::SaveEQPElems(const std::string &filename) { assert(topol_mode == TopologyHandlerMode::COMPONENT); - assert(train_mode == UNIVERSAL); /* TODO(kevin): this is a boilerplate for parallel POD/EQP training. @@ -866,7 +858,6 @@ void SteadyNSSolver::SaveEQPElems(const std::string &filename) void SteadyNSSolver::LoadEQPElems(const std::string &filename) { assert(topol_mode == TopologyHandlerMode::COMPONENT); - assert(train_mode == UNIVERSAL); assert(rom_handler->BasisLoaded()); hid_t file_id; @@ -906,7 +897,6 @@ void SteadyNSSolver::LoadEQPElems(const std::string &filename) void SteadyNSSolver::AssembleROMEQPOper() { assert(topol_mode == TopologyHandlerMode::COMPONENT); - assert(train_mode == UNIVERSAL); const int num_comp = rom_handler->GetNumROMRefComps(); assert(comp_eqps.Size() == num_comp); diff --git a/src/stokes_solver.cpp b/src/stokes_solver.cpp index 7e6579df..679f37b3 100644 --- a/src/stokes_solver.cpp +++ b/src/stokes_solver.cpp @@ -524,7 +524,6 @@ void StokesSolver::AssembleInterfaceMatrices() void StokesSolver::BuildCompROMLinElems() { assert(topol_mode == TopologyHandlerMode::COMPONENT); - assert(train_mode == UNIVERSAL); assert(rom_handler->BasisLoaded()); assert(rom_elems); @@ -579,7 +578,6 @@ void StokesSolver::BuildCompROMLinElems() void StokesSolver::BuildBdrROMLinElems() { assert(topol_mode == TopologyHandlerMode::COMPONENT); - assert(train_mode == UNIVERSAL); assert(rom_handler->BasisLoaded()); assert(rom_elems); @@ -638,7 +636,6 @@ void StokesSolver::BuildBdrROMLinElems() void StokesSolver::BuildItfaceROMLinElems() { assert(topol_mode == TopologyHandlerMode::COMPONENT); - assert(train_mode == UNIVERSAL); assert(rom_handler->BasisLoaded()); assert(rom_elems); @@ -964,13 +961,13 @@ void StokesSolver::LoadSupremizer() rom_handler->ParseSupremizerInput(num_ref_supreme, num_supreme); const int num_comp = topol_handler->GetNumComponents(); - int size = (train_mode == TrainMode::INDIVIDUAL) ? numSub : num_comp; + const int size = num_comp; DenseMatrix supreme_data; DenseMatrix *supreme = NULL; for (int m = 0; m < size; m++) { // Load the supremizer basis. - std::string basis_tag = GetBasisTagForComponent(m, train_mode, topol_handler, "sup"); + std::string basis_tag = GetBasisTagForComponent(m, topol_handler, "sup"); /* TODO(kevin): this is a boilerplate for parallel POD/EQP training. In full parallelization, all processes will participate in this supremizer reading procedure. @@ -1298,30 +1295,21 @@ void StokesSolver::EnrichSupremizer() std::string basis_prefix = rom_handler->GetBasisPrefix(); - if (train_mode == TrainMode::UNIVERSAL) - GetComponentFESpaces(comp_fes); + GetComponentFESpaces(comp_fes); Array num_ref_supreme, num_supreme; rom_handler->ParseSupremizerInput(num_ref_supreme, num_supreme); const int num_comp = topol_handler->GetNumComponents(); - int size = (train_mode == TrainMode::INDIVIDUAL) ? numSub : num_comp; + const int size = num_comp; for (int m = 0; m < size; m++) { // Load pressure ROM basis. rom_handler->GetReferenceBasis(m * num_var, ubasis); rom_handler->GetReferenceBasis(m * num_var + 1, pbasis); - if (train_mode == TrainMode::INDIVIDUAL) - { - ufes_comp = ufes[m]; - pfes_comp = pfes[m]; - } - else - { - ufes_comp = comp_fes[m * num_var]; - pfes_comp = comp_fes[m * num_var + 1]; - } + ufes_comp = comp_fes[m * num_var]; + pfes_comp = comp_fes[m * num_var + 1]; // Divergence operator. MixedBilinearFormDGExtension b_comp(ufes_comp, pfes_comp); @@ -1345,7 +1333,7 @@ void StokesSolver::EnrichSupremizer() Orthonormalize(*ubasis, *supreme); // Save the supremizer basis. - std::string basis_tag = GetBasisTagForComponent(m, train_mode, topol_handler, "sup"); + std::string basis_tag = GetBasisTagForComponent(m, topol_handler, "sup"); /* TODO(kevin): this is a boilerplate for parallel POD/EQP training. In full parallelization, all processes will participate in this supremizer writing procedure. diff --git a/src/topology_handler.cpp b/src/topology_handler.cpp index 2c3ba34d..7ae76651 100644 --- a/src/topology_handler.cpp +++ b/src/topology_handler.cpp @@ -207,14 +207,23 @@ SubMeshTopologyHandler::SubMeshTopologyHandler(Mesh* pmesh_) } } - // for SubMeshTopologyHandler, only single-component is allowed. - num_comp = 1; + /* for SubMeshTopologyHandler, each subdomain corresponds to a unique component. */ + num_comp = numSub; + + /* inidividual subdomains are unique */ mesh_types.SetSize(numSub); - mesh_types = 0; + for (int m = 0; m < numSub; m++) + mesh_types[m] = m; + + /* there is only 1 subdomain per component */ sub_composition.SetSize(num_comp); - sub_composition = numSub; + sub_composition = 1; + + /* every subdomain is the first mesh of its own type */ mesh_comp_idx.SetSize(numSub); - for (int m = 0; m < numSub; m++) mesh_comp_idx[m] = m; + mesh_comp_idx = 0; + + /* component names by index */ comp_names.resize(num_comp); for (int c = 0; c < num_comp; c++) comp_names[c] = "comp" + std::to_string(c); diff --git a/test/inputs/linelast.base.yml b/test/inputs/linelast.base.yml index 8b278e88..75fdbafd 100644 --- a/test/inputs/linelast.base.yml +++ b/test/inputs/linelast.base.yml @@ -38,7 +38,7 @@ sample_generation: parameters: - key: single_run/linelast_disp/rdisp_f type: double - sample_size: 2 + sample_size: 3 minimum: 0.9 maximum: 1.1 diff --git a/test/test_workflow.cpp b/test/test_workflow.cpp index 3645bb8e..8b44c0b8 100644 --- a/test/test_workflow.cpp +++ b/test/test_workflow.cpp @@ -10,7 +10,7 @@ using namespace std; using namespace mfem; static const double threshold = 1.0e-14; -static const double stokes_threshold = 1.0e-12; +static const double stokes_threshold = 1.0e-11; static const double linelast_threshold = 1.0e-13; /** @@ -21,36 +21,7 @@ TEST(GoogleTestFramework, GoogleTestFrameworkFound) SUCCEED(); } -TEST(Poisson_Workflow, MFEMIndividualTest) -{ - config = InputParser("inputs/test.base.yml"); - - config.dict_["model_reduction"]["rom_handler_type"] = "mfem"; - config.dict_["model_reduction"]["visualization"]["enabled"] = true; - config.dict_["model_reduction"]["visualization"]["prefix"] = "basis_paraview"; - for (int k = 0; k < 4; k++) - config.dict_["basis"]["tags"][k]["name"] = "dom" + std::to_string(k); - - config.dict_["main"]["mode"] = "sample_generation"; - GenerateSamples(MPI_COMM_WORLD); - - config.dict_["main"]["mode"] = "train_rom"; - TrainROM(MPI_COMM_WORLD); - - config.dict_["main"]["mode"] = "build_rom"; - BuildROM(MPI_COMM_WORLD); - - config.dict_["main"]["mode"] = "single_run"; - double error = SingleRun(MPI_COMM_WORLD); - - // This reproductive case must have a very small error at the level of finite-precision. - printf("Error: %.15E\n", error); - EXPECT_TRUE(error < threshold); - - return; -} - -TEST(Poisson_Workflow, MFEMUniversalTest) +TEST(Poisson_Workflow, SubmeshTest) { config = InputParser("inputs/test.base.yml"); @@ -60,15 +31,10 @@ TEST(Poisson_Workflow, MFEMUniversalTest) config.dict_["model_reduction"]["visualization"]["enabled"] = true; config.dict_["model_reduction"]["visualization"]["prefix"] = "basis_paraview"; - config.dict_["single_run"]["poisson0"]["k"] = 2.0; - config.dict_["sample_generation"]["parameters"][0]["sample_size"] = 1; - config.dict_["model_reduction"]["subdomain_training"] = "universal"; - config.dict_["basis"]["number_of_basis"] = 4; - // Test save/loadSolution as well. config.dict_["save_solution"]["enabled"] = true; config.dict_["model_reduction"]["compare_solution"]["load_solution"] = true; - config.dict_["model_reduction"]["compare_solution"]["fom_solution_file"] = "./sample0_solution.h5"; + config.dict_["model_reduction"]["compare_solution"]["fom_solution_file"] = "./sample1_solution.h5"; config.dict_["main"]["mode"] = "sample_generation"; GenerateSamples(MPI_COMM_WORLD); @@ -149,38 +115,7 @@ TEST(Poisson_Workflow, ComponentWiseWithDirectSolve) return; } -TEST(Stokes_Workflow, MFEMIndividualTest) -{ - config = InputParser("inputs/stokes.base.yml"); - for (int k = 0; k < 4; k++) - config.dict_["basis"]["tags"][k]["name"] = "dom" + std::to_string(k); - - config.dict_["model_reduction"]["rom_handler_type"] = "mfem"; - config.dict_["model_reduction"]["visualization"]["enabled"] = true; - config.dict_["model_reduction"]["visualization"]["prefix"] = "basis_paraview"; - - config.dict_["main"]["mode"] = "sample_generation"; - config.dict_["main"]["use_rom"] = false; - GenerateSamples(MPI_COMM_WORLD); - config.dict_["main"]["use_rom"] = true; - - config.dict_["main"]["mode"] = "train_rom"; - TrainROM(MPI_COMM_WORLD); - - config.dict_["main"]["mode"] = "build_rom"; - BuildROM(MPI_COMM_WORLD); - - config.dict_["main"]["mode"] = "single_run"; - double error = SingleRun(MPI_COMM_WORLD); - - // This reproductive case must have a very small error at the level of finite-precision. - printf("Error: %.15E\n", error); - EXPECT_TRUE(error < stokes_threshold); - - return; -} - -TEST(Stokes_Workflow, MFEMUniversalTest) +TEST(Stokes_Workflow, SubmeshTest) { config = InputParser("inputs/stokes.base.yml"); @@ -190,15 +125,10 @@ TEST(Stokes_Workflow, MFEMUniversalTest) config.dict_["model_reduction"]["visualization"]["enabled"] = true; config.dict_["model_reduction"]["visualization"]["prefix"] = "basis_paraview"; - config.dict_["single_run"]["channel_flow"]["nu"] = 2.0; - config.dict_["sample_generation"]["parameters"][0]["sample_size"] = 1; - config.dict_["model_reduction"]["subdomain_training"] = "universal"; - config.dict_["basis"]["number_of_basis"] = 4; - // Test save/loadSolution as well. config.dict_["save_solution"]["enabled"] = true; config.dict_["model_reduction"]["compare_solution"]["load_solution"] = true; - config.dict_["model_reduction"]["compare_solution"]["fom_solution_file"] = "./sample0_solution.h5"; + config.dict_["model_reduction"]["compare_solution"]["fom_solution_file"] = "./sample1_solution.h5"; config.dict_["main"]["mode"] = "sample_generation"; config.dict_["main"]["use_rom"] = false; @@ -233,15 +163,10 @@ TEST(Stokes_Workflow, MFEMGlobalSeparateTest) config.dict_["model_reduction"]["visualization"]["prefix"] = "basis_paraview"; config.dict_["model_reduction"]["linear_solver_type"] = "minres"; - config.dict_["single_run"]["channel_flow"]["nu"] = 2.0; - config.dict_["sample_generation"]["parameters"][0]["sample_size"] = 1; - config.dict_["model_reduction"]["subdomain_training"] = "universal"; - config.dict_["basis"]["number_of_basis"] = 4; - // Test save/loadSolution as well. config.dict_["save_solution"]["enabled"] = true; config.dict_["model_reduction"]["compare_solution"]["load_solution"] = true; - config.dict_["model_reduction"]["compare_solution"]["fom_solution_file"] = "./sample0_solution.h5"; + config.dict_["model_reduction"]["compare_solution"]["fom_solution_file"] = "./sample1_solution.h5"; config.dict_["main"]["mode"] = "sample_generation"; config.dict_["main"]["use_rom"] = false; @@ -355,36 +280,7 @@ TEST(Stokes_Workflow, ComponentSeparateVariable) return; } -TEST(SteadyNS_Workflow, MFEMIndividualTest) -{ - config = InputParser("inputs/steady_ns.base.yml"); - for (int k = 0; k < 4; k++) - config.dict_["basis"]["tags"][k]["name"] = "dom" + std::to_string(k); - - config.dict_["model_reduction"]["rom_handler_type"] = "mfem"; - config.dict_["model_reduction"]["visualization"]["enabled"] = true; - config.dict_["model_reduction"]["visualization"]["prefix"] = "basis_paraview"; - - config.dict_["main"]["mode"] = "sample_generation"; - GenerateSamples(MPI_COMM_WORLD); - - config.dict_["main"]["mode"] = "train_rom"; - TrainROM(MPI_COMM_WORLD); - - config.dict_["main"]["mode"] = "build_rom"; - BuildROM(MPI_COMM_WORLD); - - config.dict_["main"]["mode"] = "single_run"; - double error = SingleRun(MPI_COMM_WORLD); - - // This reproductive case must have a very small error at the level of finite-precision. - printf("Error: %.15E\n", error); - EXPECT_TRUE(error < stokes_threshold); - - return; -} - -TEST(SteadyNS_Workflow, MFEMUniversalTest) +TEST(SteadyNS_Workflow, SubmeshTest) { config = InputParser("inputs/steady_ns.base.yml"); @@ -396,15 +292,10 @@ TEST(SteadyNS_Workflow, MFEMUniversalTest) config.dict_["model_reduction"]["visualization"]["enabled"] = true; config.dict_["model_reduction"]["visualization"]["prefix"] = "basis_paraview"; - config.dict_["single_run"]["channel_flow"]["nu"] = 2.0; - config.dict_["sample_generation"]["parameters"][0]["sample_size"] = 1; - config.dict_["model_reduction"]["subdomain_training"] = "universal"; - config.dict_["basis"]["number_of_basis"] = 4; - // Test save/loadSolution as well. config.dict_["save_solution"]["enabled"] = true; config.dict_["model_reduction"]["compare_solution"]["load_solution"] = true; - config.dict_["model_reduction"]["compare_solution"]["fom_solution_file"] = "./sample0_solution.h5"; + config.dict_["model_reduction"]["compare_solution"]["fom_solution_file"] = "./sample1_solution.h5"; config.dict_["main"]["mode"] = "sample_generation"; GenerateSamples(MPI_COMM_WORLD); @@ -439,15 +330,10 @@ TEST(SteadyNS_Workflow, MFEMGlobalUniversalTest) config.dict_["model_reduction"]["visualization"]["enabled"] = true; config.dict_["model_reduction"]["visualization"]["prefix"] = "basis_paraview"; - config.dict_["single_run"]["channel_flow"]["nu"] = 2.0; - config.dict_["sample_generation"]["parameters"][0]["sample_size"] = 1; - config.dict_["model_reduction"]["subdomain_training"] = "universal"; - config.dict_["basis"]["number_of_basis"] = 4; - // Test save/loadSolution as well. config.dict_["save_solution"]["enabled"] = true; config.dict_["model_reduction"]["compare_solution"]["load_solution"] = true; - config.dict_["model_reduction"]["compare_solution"]["fom_solution_file"] = "./sample0_solution.h5"; + config.dict_["model_reduction"]["compare_solution"]["fom_solution_file"] = "./sample1_solution.h5"; config.dict_["main"]["mode"] = "sample_generation"; GenerateSamples(MPI_COMM_WORLD); @@ -591,48 +477,16 @@ TEST(SteadyNS_Workflow, ComponentSeparateVariable_EQP) return; } -TEST(LinElast_Workflow, MFEMIndividualTest) +TEST(LinElast_Workflow, SubmeshTest) { config = InputParser("inputs/linelast.base.yml"); config.dict_["model_reduction"]["rom_handler_type"] = "mfem"; - config.dict_["sample_generation"]["parameters"][0]["sample_size"] = 4; - config.dict_["basis"]["number_of_basis"] = 2; - for (int k = 0; k < 2; k++) - config.dict_["basis"]["tags"][k]["name"] = "dom" + std::to_string(k); - - config.dict_["main"]["mode"] = "sample_generation"; - GenerateSamples(MPI_COMM_WORLD); - - config.dict_["main"]["mode"] = "train_rom"; - TrainROM(MPI_COMM_WORLD); - config.dict_["main"]["mode"] = "build_rom"; - BuildROM(MPI_COMM_WORLD); - config.dict_["main"]["mode"] = "single_run"; - double error = SingleRun(MPI_COMM_WORLD); - - // This reproductive case must have a very small error at the level of finite-precision. - printf("Error: %.15E\n", error); - EXPECT_TRUE(error < threshold); - - return; -} - -TEST(LinElast_Workflow, MFEMUniversalTest) -{ - config = InputParser("inputs/linelast.base.yml"); - - config.dict_["model_reduction"]["rom_handler_type"] = "mfem"; - - config.dict_["single_run"]["linelast_disp"]["rdisp_f"] = 0.9; - config.dict_["sample_generation"]["parameters"][0]["sample_size"] = 2; - config.dict_["model_reduction"]["subdomain_training"] = "universal"; - config.dict_["basis"]["number_of_basis"] = 4; // Test save/loadSolution as well. config.dict_["save_solution"]["enabled"] = true; config.dict_["model_reduction"]["compare_solution"]["load_solution"] = true; - config.dict_["model_reduction"]["compare_solution"]["fom_solution_file"] = "./sample0_solution.h5"; + config.dict_["model_reduction"]["compare_solution"]["fom_solution_file"] = "./sample1_solution.h5"; config.dict_["main"]["mode"] = "sample_generation"; GenerateSamples(MPI_COMM_WORLD); @@ -712,11 +566,9 @@ TEST(LinElast_Workflow, ComponentWiseTest) return; } -TEST(AdvDiff_Workflow, MFEMIndividualTest) +TEST(AdvDiff_Workflow, SubmeshTest) { config = InputParser("inputs/advdiff.base.yml"); - for (int k = 0; k < 4; k++) - config.dict_["basis"]["tags"][k]["name"] = "dom" + std::to_string(k); config.dict_["model_reduction"]["visualization"]["enabled"] = true; config.dict_["model_reduction"]["visualization"]["prefix"] = "basis_paraview";