From 46130d8e694f2cda00816d9503b6ef91de0889af Mon Sep 17 00:00:00 2001 From: Alan Williams Date: Thu, 24 Oct 2024 16:37:26 -0600 Subject: [PATCH] STK: Snapshot 10-24-24 16:37 from Sierra 5.21.6-340-g20e31875 Signed-off-by: Alan Williams --- packages/stk/CHANGELOG.md | 6 + .../stk/stk_balance/stk_balance/balance.cpp | 7 +- .../internal/privateDeclarations.cpp | 3 +- .../internal/privateDeclarations.hpp | 9 +- .../stk_balance/m2n/m2nRebalance.cpp | 11 +- .../stk_balance/m2n_main/m2nMain.cpp | 14 +- .../stk_balance/setup/LifeCycle.cpp | 21 +- .../readInitialConditionNodalSubset.cpp | 3 +- .../IntegrationTestCoincidentElems.cpp | 2 + packages/stk/stk_io/example/io_mesh.cpp | 18 +- packages/stk/stk_io/stk_io/FillMesh.cpp | 8 +- packages/stk/stk_io/stk_io/IOHelpers.cpp | 18 +- packages/stk/stk_io/stk_io/IossBridge.cpp | 117 +++- packages/stk/stk_io/stk_io/IossBridge.hpp | 7 +- .../stk/stk_io/stk_io/ProcessSetsOrBlocks.cpp | 27 +- .../stk/stk_io/stk_io/SidesetTranslator.hpp | 41 +- .../stk/stk_io/stk_io/StkMeshIoBroker.cpp | 60 ++- .../stk/stk_io/stk_io/StkMeshIoBroker.hpp | 10 +- packages/stk/stk_math/stk_math/StkMath.hpp | 214 +++++--- .../stk/stk_mesh/stk_mesh/base/Bucket.hpp | 4 +- .../stk/stk_mesh/stk_mesh/base/BulkData.cpp | 115 +--- .../stk/stk_mesh/stk_mesh/base/BulkData.hpp | 113 +++- .../stk_mesh/stk_mesh/base/DeviceField.hpp | 24 +- .../stk/stk_mesh/stk_mesh/base/DeviceMesh.cpp | 453 ---------------- .../stk/stk_mesh/stk_mesh/base/DeviceMesh.hpp | 498 ++++++++++++++++-- .../stk_mesh/stk_mesh/base/FieldParallel.cpp | 6 +- .../stk/stk_mesh/stk_mesh/base/GetNgpMesh.hpp | 12 +- .../stk/stk_mesh/stk_mesh/base/HostField.hpp | 4 +- .../stk/stk_mesh/stk_mesh/base/HostMesh.hpp | 29 +- packages/stk/stk_mesh/stk_mesh/base/Ngp.hpp | 15 +- .../stk_mesh/stk_mesh/base/NgpFieldBLAS.hpp | 18 + .../stk_mesh/base/NgpFieldParallel.hpp | 2 +- .../stk_mesh/stk_mesh/base/NgpReductions.hpp | 19 +- .../stk/stk_mesh/stk_mesh/base/NgpTypes.hpp | 15 + .../stk_mesh/baseImpl/CommEntityMods.cpp | 17 +- .../stk_mesh/baseImpl/EntityKeyMapping.cpp | 4 + .../stk_mesh/baseImpl/NgpFieldBLASImpl.hpp | 137 ++++- ...ceMeshHostData.hpp => NgpMeshHostData.hpp} | 23 +- .../elementGraph/BulkDataIdMapper.hpp | 16 +- .../baseImpl/elementGraph/ElemElemGraph.cpp | 340 ++++++++++-- .../baseImpl/elementGraph/ElemElemGraph.hpp | 23 +- .../elementGraph/ElemElemGraphImpl.hpp | 2 - .../elementGraph/ElemElemGraphUpdater.hpp | 57 +- .../baseImpl/elementGraph/GraphEdgeData.cpp | 24 +- .../baseImpl/elementGraph/GraphEdgeData.hpp | 6 +- .../baseImpl/elementGraph/GraphTypes.hpp | 1 + packages/stk/stk_middle_mesh/Jamfile | 2 +- .../stk_ngp_test/NgpTestDeviceMacros.hpp | 2 +- .../stk_mesh/perfCommNeighbors.cpp | 2 +- .../morton_lbvh/CoarseSearchMortonLBVH.hpp | 4 +- .../LocalCoarseSearchMortonLBVH.hpp | 4 +- .../morton_lbvh/MortonLBVH_Search.hpp | 2 +- .../mesh_tools/DisconnectBlocksImpl.cpp | 50 +- .../stk_tools/scripts/trilinos_snapshot.sh | 2 +- .../stk_topology/topology_decl.hpp | 6 +- .../stk_topology/topology_defn.hpp | 45 +- .../topology_detail/meta_functions.hpp | 14 + .../topology_detail/topology_data.hpp | 19 +- .../stk_topology/topology_type.hpp | 28 + .../stk_topology/topology_utils.hpp | 36 +- .../stk_transfer/GeometricTransfer.hpp | 1 - .../stk_transfer/GeometricTransferImpl.hpp | 8 +- .../copy_by_id/TransferCopyById.cpp | 3 +- .../ElemGraphMultipleSharedSidesUtils.hpp | 14 +- .../stk_balance/MeshFixtureDecomposer.hpp | 6 +- .../stk_balance/MeshFixtureM2NDecomposer.hpp | 6 +- .../stk_balance/UnitTestBalanceFromField.cpp | 6 +- .../stk_balance/UnitTestBlockWeights.cpp | 6 +- .../stk_balance/UnitTestDefaultDecomposer.cpp | 4 +- .../UnitTestDiagnosticsComputation.cpp | 8 +- .../stk_balance/UnitTestLogFile.cpp | 18 +- .../stk_balance/UnitTestM2NFileOutput.cpp | 6 +- .../stk_balance/UnitTestM2NLogFile.cpp | 18 +- .../UnitTestM2NNestedDecomposition.cpp | 8 +- .../stk_balance/UnitTestM2NRebalance.cpp | 6 +- ...UnitTestM2NRebalanceTransientFieldData.cpp | 6 +- .../stk_balance/UnitTestNestedDecomposer.cpp | 4 +- .../stk_balance/UnitTestRebalance.cpp | 6 +- .../UnitTestRebalanceFileOutput.cpp | 6 +- .../stk_balance/UnitTestRebalanceSpiders.cpp | 6 +- .../UnitTestRebalanceTransientFieldData.cpp | 6 +- .../UnitTestStkBalanceDecomposition.cpp | 6 +- .../UnitTestStkBalancePartitioning.cpp | 6 +- .../UnitTestZoltanGraphGeneration.cpp | 6 +- .../stk_coupling/UnitTestSplitComm.cpp | 25 + .../stk_mesh/TestElemElemGraphUtils.hpp | 87 +++ .../stk_unit_tests/stk_mesh/UnitTestAura.cpp | 147 +++++- .../stk_mesh/UnitTestAuraToShared.cpp | 37 +- .../stk_mesh/UnitTestBulkData.cpp | 2 +- .../stk_mesh/UnitTestCEOCommonUtils.cpp | 1 - .../UnitTestElemGraphCoincidentElements.cpp | 2 +- .../stk_mesh/UnitTestModificationEnd.hpp | 1 - .../stk_mesh/UnitTestSidePolarity.cpp | 3 - .../stk_mesh/UnitTestSideSet.cpp | 59 ++- .../TwoHexesTwoProcsEGWithPermutations.cpp | 1 - .../TwoHexesTwoProcsElemGraph.cpp | 1 - .../UnitTestSkinMeshCoincidentElements.cpp | 9 +- .../stk_mesh/ngp/NgpMeshTest.cpp | 64 ++- .../stk_mesh/ngp/TestNgpMeshUpdate.cpp | 65 +++ .../stk_mesh/ngp/ngpFieldBLASTest.cpp | 111 ++++ .../stk_search/UnitTestCoarseSearch.cpp | 19 +- .../stk_search/UnitTestCoarseSearchTwoBox.cpp | 4 +- .../UnitTestCoarseSearchTwoSpheres.cpp | 4 +- .../stk_search/UnitTestDeviceMPIUtils.cpp | 4 +- .../UnitTestParallelConsistencyUtils.cpp | 30 +- .../unit_test_shell_quad_all_face_sides.cpp | 12 +- .../unit_test_shell_tri_all_face_sides.cpp | 12 +- .../environment/UnitTestOutputLog.cpp | 7 +- .../parallel/UnitTestOutputStreams.cpp | 106 ++++ packages/stk/stk_util/stk_util/Version.hpp | 2 +- .../environment/LogWithTimeAndMemory.cpp | 8 +- .../environment/LogWithTimeAndMemory.hpp | 3 +- .../stk_util/stk_util/parallel/CMakeLists.txt | 2 + .../stk_util/parallel/OutputStreams.cpp | 120 +++++ .../stk_util/parallel/OutputStreams.hpp | 73 +++ .../stk_util/registry/ProductRegistry.cpp | 2 +- .../stk/stk_util/stk_util/stk_kokkos_macros.h | 4 + 117 files changed, 2855 insertions(+), 1131 deletions(-) delete mode 100644 packages/stk/stk_mesh/stk_mesh/base/DeviceMesh.cpp rename packages/stk/stk_mesh/stk_mesh/baseImpl/{DeviceMeshHostData.hpp => NgpMeshHostData.hpp} (65%) create mode 100644 packages/stk/stk_unit_tests/stk_mesh/TestElemElemGraphUtils.hpp create mode 100644 packages/stk/stk_unit_tests/stk_util/parallel/UnitTestOutputStreams.cpp create mode 100644 packages/stk/stk_util/stk_util/parallel/OutputStreams.cpp create mode 100644 packages/stk/stk_util/stk_util/parallel/OutputStreams.hpp diff --git a/packages/stk/CHANGELOG.md b/packages/stk/CHANGELOG.md index 5b1b4b01f5a4..6160baab2c76 100644 --- a/packages/stk/CHANGELOG.md +++ b/packages/stk/CHANGELOG.md @@ -1,8 +1,14 @@ # CHANGELOG +5.21.6 (STK_VERSION 5210600) 10/25/2024 + stk_search: fix build-error (instantiation error for morton_lbvh_search) for gcc 13.2 + stk_util: added parallel/OutputStreams.hpp + - which includes the functions outputP0(), output(), output_flush(), set_outputP0(..), reset_default_output_streams(). + 5.21.5-2 (STK_VERSION 5210502) 10/07/2024 stk_search: Fixed HIP sort error. stk_mesh: add multi-field NGP-FieldBLAS field_fill + 5.21.5-1 (STK_VERSION 5210501) 9/27/2024 stk_mesh: deprecate BulkData::relation_exist diff --git a/packages/stk/stk_balance/stk_balance/balance.cpp b/packages/stk/stk_balance/stk_balance/balance.cpp index 357d43658b69..982dff5df0aa 100644 --- a/packages/stk/stk_balance/stk_balance/balance.cpp +++ b/packages/stk/stk_balance/stk_balance/balance.cpp @@ -50,6 +50,7 @@ #include "stk_tools/transfer_utils/TransientFieldTransferById.hpp" #include "stk_util/diag/StringUtil.hpp" #include "stk_util/parallel/ParallelReduce.hpp" +#include "stk_util/parallel/OutputStreams.hpp" #include "stk_util/util/ReportHandler.hpp" // for ThrowRequireMsg #include #include @@ -252,7 +253,7 @@ bool balanceStkMesh(const BalanceSettings& balanceSettings, stk::mesh::BulkData& const bool anyElementMovement = balancer.balance(mesh, selectors); DiagnosticsPrinter diagPrinter(stkMeshBulkData.parallel(), stkMeshBulkData.parallel_size()); - diagPrinter.print(sierra::Env::outputP0()); + diagPrinter.print(stk::outputP0()); return anyElementMovement; } @@ -270,7 +271,7 @@ bool balanceStkMesh(const BalanceSettings& balanceSettings, stk::mesh::BulkData& const bool anyElementMovement = balancer.balance(mesh); DiagnosticsPrinter diagPrinter(stkMeshBulkData.parallel(), stkMeshBulkData.parallel_size()); - diagPrinter.print(sierra::Env::outputP0()); + diagPrinter.print(stk::outputP0()); return anyElementMovement; } @@ -290,7 +291,7 @@ bool balanceStkMeshNodes(const BalanceSettings& balanceSettings, stk::mesh::Bulk balanceSettings.getNodeBalancerMaxIterations()); DiagnosticsPrinter diagPrinter(stkMeshBulkData.parallel(), stkMeshBulkData.parallel_size()); - diagPrinter.print(sierra::Env::outputP0()); + diagPrinter.print(stk::outputP0()); return anyChangedOwnership; } diff --git a/packages/stk/stk_balance/stk_balance/internal/privateDeclarations.cpp b/packages/stk/stk_balance/stk_balance/internal/privateDeclarations.cpp index d46f3b787696..cd6be5f6d0f9 100644 --- a/packages/stk/stk_balance/stk_balance/internal/privateDeclarations.cpp +++ b/packages/stk/stk_balance/stk_balance/internal/privateDeclarations.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -792,7 +793,7 @@ void fill_output_subdomain_field(const stk::mesh::BulkData & bulk, const Balance void logMessage(MPI_Comm communicator, const std::string &message) { - stk::log_with_time_and_memory(communicator, message); + stk::log_with_time_and_memory(communicator, message, stk::outputP0()); } void fill_zoltan2_graph(const BalanceSettings& balanceSettings, diff --git a/packages/stk/stk_balance/stk_balance/internal/privateDeclarations.hpp b/packages/stk/stk_balance/stk_balance/internal/privateDeclarations.hpp index 41221b5b9b46..b80c9b99971a 100644 --- a/packages/stk/stk_balance/stk_balance/internal/privateDeclarations.hpp +++ b/packages/stk/stk_balance/stk_balance/internal/privateDeclarations.hpp @@ -45,7 +45,7 @@ #include #include #include -#include +#include #include #include @@ -140,14 +140,11 @@ void print_zoltan_statistics(const ZoltanAdapter& stkMeshAdapter, Zoltan2::Evalu double localsum = 0.; for (size_t i = 0; i< stkMeshAdapter.getLocalNumIDs(); i++) localsum += kdd[i]; - sierra::Env::outputP0() << parallel_rank + stk::outputP0() << parallel_rank << " PRINTING METRICS nObj " << stkMeshAdapter.getLocalNumIDs() << " nwgts " << stkMeshAdapter.getNumWeightsPerID() << " sumwgt " << localsum << std::endl; - zoltanEvaluateParition.printMetrics(sierra::Env::outputP0()); - //sierra::Env::outputP0() << parallel_rank - // << " PRINTING GRAPH METRICS" << std::endl; - //zoltanEvaluateParition.printGraphMetrics(sierra::Env::outputP0()); + zoltanEvaluateParition.printMetrics(stk::outputP0()); } template diff --git a/packages/stk/stk_balance/stk_balance/m2n/m2nRebalance.cpp b/packages/stk/stk_balance/stk_balance/m2n/m2nRebalance.cpp index f15edf71376c..a1dd10d2eacc 100644 --- a/packages/stk/stk_balance/stk_balance/m2n/m2nRebalance.cpp +++ b/packages/stk/stk_balance/stk_balance/m2n/m2nRebalance.cpp @@ -39,6 +39,7 @@ #include #include #include +#include "stk_util/parallel/OutputStreams.hpp" #include "stk_util/environment/Env.hpp" #include "stk_util/environment/EnvData.hpp" #include "stk_util/environment/OutputLog.hpp" @@ -52,18 +53,18 @@ void set_output_streams(MPI_Comm comm, const stk::balance::M2NBalanceSettings & if (stk::parallel_machine_rank(comm) == 0) { const std::string & logName = balanceSettings.get_log_filename(); if (logName == "cout" || logName == "cerr") { - stk::EnvData::instance().m_outputP0 = stk::get_log_ostream(logName); + stk::set_outputP0(stk::get_log_ostream(logName)); } else { stk::bind_output_streams("log=\"" + logName + "\""); - stk::EnvData::instance().m_outputP0 = stk::get_log_ostream("log"); + stk::set_outputP0(stk::get_log_ostream("log")); } } else { - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + //stk::outputP0() is already a null output stream by default on other MPI ranks. } - Ioss::Utils::set_output_stream(sierra::Env::outputP0()); + Ioss::Utils::set_output_stream(stk::outputP0()); } void print_running_message(const stk::balance::M2NBalanceSettings & balanceSettings, MPI_Comm comm) @@ -120,7 +121,7 @@ void m2nRebalance(stk::io::StkMeshIoBroker& ioBroker, const stk::balance::M2NBal void rebalance_m2n(stk::balance::M2NBalanceSettings &balanceSettings, MPI_Comm comm) { print_running_message(balanceSettings, comm); - print_banner(sierra::Env::outputP0()); + print_banner(stk::outputP0()); std::shared_ptr bulk = stk::mesh::MeshBuilder(comm).create(); stk::io::StkMeshIoBroker ioBroker; diff --git a/packages/stk/stk_balance/stk_balance/m2n_main/m2nMain.cpp b/packages/stk/stk_balance/stk_balance/m2n_main/m2nMain.cpp index e3fd9f885f22..cba6b552446f 100644 --- a/packages/stk/stk_balance/stk_balance/m2n_main/m2nMain.cpp +++ b/packages/stk/stk_balance/stk_balance/m2n_main/m2nMain.cpp @@ -38,13 +38,15 @@ #include #include "stk_balance/internal/LogUtils.hpp" -#include +#include #include #include int main(int argc, const char**argv) { MPI_Init(&argc, const_cast(&argv)); + Kokkos::initialize(argc, const_cast(argv)); + MPI_Comm comm = MPI_COMM_WORLD; stk::balance::initialize_environment(comm, argv); @@ -58,10 +60,12 @@ int main(int argc, const char**argv) size_t hwmMax = 0, hwmMin = 0, hwmAvg = 0; stk::get_memory_high_water_mark_across_processors(comm, hwmMax, hwmMin, hwmAvg); - sierra::Env::outputP0() << "Memory HWM across procs, max/min/avg: " - << stk::human_bytes(hwmMax) << " / " - << stk::human_bytes(hwmMin) << " / " - << stk::human_bytes(hwmAvg) << std::endl; + stk::outputP0() << "Memory HWM across procs, max/min/avg: " + << stk::human_bytes(hwmMax) << " / " + << stk::human_bytes(hwmMin) << " / " + << stk::human_bytes(hwmAvg) << std::endl; + + Kokkos::finalize(); MPI_Finalize(); return 0; } diff --git a/packages/stk/stk_balance/stk_balance/setup/LifeCycle.cpp b/packages/stk/stk_balance/stk_balance/setup/LifeCycle.cpp index afeec92fce53..e16286296608 100644 --- a/packages/stk/stk_balance/stk_balance/setup/LifeCycle.cpp +++ b/packages/stk/stk_balance/stk_balance/setup/LifeCycle.cpp @@ -33,6 +33,7 @@ #include "LifeCycle.hpp" +#include "stk_util/parallel/OutputStreams.hpp" #include "stk_util/environment/Env.hpp" #include "stk_util/environment/EnvData.hpp" #include "stk_util/environment/OutputLog.hpp" @@ -81,7 +82,7 @@ void LifeCycle::run() } print_running_message(); - print_banner(sierra::Env::outputP0()); + print_banner(stk::outputP0()); if (is_serial_no_op()) { print_serial_no_op_message(); @@ -132,14 +133,14 @@ bool LifeCycle::rebalance_will_corrupt_data(const stk::io::StkMeshIoBroker & ioB if (isRebalancing && sameInputAndOutputFile && sameInputAndOutputProcCount) { if (hasTransientFieldData) { willCorruptData = true; - sierra::Env::outputP0() + stk::outputP0() << "Aborting rebalance: Overwriting input files that contain transient fields will" << std::endl << "lead to data corruption. Please specify a different outputDirectory." << std::endl; } if (has64BitIds) { willCorruptData = true; - sierra::Env::outputP0() + stk::outputP0() << "Aborting rebalance: Overwriting input files that contain 64-bit IDs will" << std::endl << "lead to data corruption. Please specify a different outputDirectory." << std::endl; } @@ -162,7 +163,7 @@ void LifeCycle::balance() io.write(mesh); DiagnosticsPrinter diagPrinter(m_comm, m_settings.get_num_output_processors()); - diagPrinter.print(sierra::Env::outputP0()); + diagPrinter.print(stk::outputP0()); } void LifeCycle::rebalance() @@ -187,7 +188,7 @@ void LifeCycle::rebalance() stk::balance::rebalance(ioBroker, m_settings); DiagnosticsPrinter diagPrinter(m_comm, m_settings.get_num_output_processors()); - diagPrinter.print(sierra::Env::outputP0()); + diagPrinter.print(stk::outputP0()); } void LifeCycle::set_output_streams() @@ -195,18 +196,18 @@ void LifeCycle::set_output_streams() if (m_isProc0) { const std::string & logName = m_settings.get_log_filename(); if (logName == "cout" || logName == "cerr") { - stk::EnvData::instance().m_outputP0 = stk::get_log_ostream(logName); + stk::set_outputP0(stk::get_log_ostream(logName)); } else { stk::bind_output_streams("log=\"" + logName + "\""); - stk::EnvData::instance().m_outputP0 = stk::get_log_ostream("log"); + stk::set_outputP0(stk::get_log_ostream("log")); } } else { - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + //stk::outputP0() is already a null output stream by default on other MPI ranks. } - Ioss::Utils::set_output_stream(sierra::Env::outputP0()); + Ioss::Utils::set_output_stream(stk::outputP0()); } void LifeCycle::print_parse_error(const char* what) const @@ -225,7 +226,7 @@ void LifeCycle::print_balance_error(const char* what) const void LifeCycle::print_serial_no_op_message() const { - sierra::Env::outputP0() + stk::outputP0() << "Aborting balance: Rewriting the same input serial mesh file. Please specify" << std::endl << "a different outputDirectory if you wish to copy the input file to an output" << std::endl << "file of the same name." << std::endl; diff --git a/packages/stk/stk_doc_tests/stk_io/readInitialConditionNodalSubset.cpp b/packages/stk/stk_doc_tests/stk_io/readInitialConditionNodalSubset.cpp index bf47fbd190c2..61a0e56add60 100644 --- a/packages/stk/stk_doc_tests/stk_io/readInitialConditionNodalSubset.cpp +++ b/packages/stk/stk_doc_tests/stk_io/readInitialConditionNodalSubset.cpp @@ -90,8 +90,9 @@ TEST(StkMeshIoBrokerHowTo, readInitialConditionNodalSubset) stk::mesh::MetaData &meta_data = stkIo.meta_data(); // Declare the nodal "temperature" field. Exists on all nodes. + constexpr int numStates = 1; stk::mesh::Field &temperature = - stkIo.meta_data().declare_field(stk::topology::NODE_RANK, appFieldName,1); + stkIo.meta_data().declare_field(stk::topology::NODE_RANK, appFieldName,numStates); // "NodeBlock_1" is the name of the node field on the input mesh. stk::io::MeshField mf(temperature, dbFieldNameShell); diff --git a/packages/stk/stk_integration_tests/stk_balance/IntegrationTestCoincidentElems.cpp b/packages/stk/stk_integration_tests/stk_balance/IntegrationTestCoincidentElems.cpp index f1d72e63e91d..89c00ed38035 100644 --- a/packages/stk/stk_integration_tests/stk_balance/IntegrationTestCoincidentElems.cpp +++ b/packages/stk/stk_integration_tests/stk_balance/IntegrationTestCoincidentElems.cpp @@ -91,6 +91,8 @@ class CoincidentElems : public stk::unit_test_util::MeshFixture TEST_F(CoincidentElems, balance_coincidentsNotSplit) { + if (stk::parallel_machine_size(MPI_COMM_WORLD) != 2) { GTEST_SKIP(); } + setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); std::string meshDesc = "0,1,HEX_8,1,2,3,4,5,6,7,8\n" diff --git a/packages/stk/stk_io/example/io_mesh.cpp b/packages/stk/stk_io/example/io_mesh.cpp index f63e00652961..aeee5d2b99c9 100644 --- a/packages/stk/stk_io/example/io_mesh.cpp +++ b/packages/stk/stk_io/example/io_mesh.cpp @@ -47,8 +47,7 @@ #include #include // for versi... #include // for Comma... -#include // for outputP0 -#include // for EnvData +#include #include // for log_w... #include // for get_c... #include // for paral... @@ -81,10 +80,7 @@ void set_output_streams(MPI_Comm comm) { - if (stk::parallel_machine_rank(comm) != 0) { - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; - } - Ioss::Utils::set_output_stream(sierra::Env::outputP0()); + Ioss::Utils::set_output_stream(stk::outputP0()); } class IoMeshDriver @@ -289,14 +285,14 @@ class IoMeshDriver // For each global field name on the input database, determine the type of the field // and define that same global field on the results, restart, history, and heartbeat outputs. if (!global_fields.empty()) { - sierra::Env::outputP0() << "Adding " << global_fields.size() << " global fields:\n"; + stk::outputP0() << "Adding " << global_fields.size() << " global fields:\n"; } auto io_region = ioBroker.get_input_ioss_region(); for (size_t i=0; i < global_fields.size(); i++) { const Ioss::Field &input_field = io_region->get_fieldref(global_fields[i]); - sierra::Env::outputP0() << "\t" << input_field.get_name() << " of type " << input_field.raw_storage()->name() << "\n"; + stk::outputP0() << "\t" << input_field.get_name() << " of type " << input_field.raw_storage()->name() << "\n"; if (input_field.raw_storage()->component_count() == 1) { double val = 0.0; @@ -446,7 +442,7 @@ class IoMeshDriver ioBroker.property_add(Ioss::Property("DECOMPOSITION_METHOD", decomp_method)); } else { - sierra::Env::outputP0()<<"decomposition not specified, defaulting to file-per-processor mode for mesh-read."<property_exists("ENABLE_ALL_FACE_SIDES_SHELL"); + int par_dimen = block->topology()->parametric_dimension(); + stk::mesh::EntityRank side_rank = par_dimen == 1 ? stk::topology::EDGE_RANK : stk::topology::FACE_RANK; + return (block->parent_element_topology()->is_shell() && useShellAllFaceSides) ? stk::topology::FACE_RANK : side_rank; +} + template void process_surface_entity_df(const Ioss::SideSet* sset, stk::mesh::BulkData & bulk) { @@ -215,7 +223,7 @@ void process_surface_entity_df(const Ioss::SideSet* sset, stk::mesh::BulkData & // be the same and this could fail (a sideset of mixed edges and faces) int par_dimen = block->topology()->parametric_dimension(); - stk::mesh::EntityRank side_rank = par_dimen == 1 ? stk::topology::EDGE_RANK : stk::topology::FACE_RANK; + stk::mesh::EntityRank side_rank = get_side_rank(region, block); // Would be nice to do: // std::vector sides ; @@ -242,15 +250,15 @@ void process_surface_entity_df(const Ioss::SideSet* sset, stk::mesh::BulkData & stk::topology elemTopo = bulk.bucket(elem).topology(); if(par_dimen == 0) { - stk::topology faceTopo = elemTopo.sub_topology(elemTopo.side_rank(), elemSide); + stk::topology sideTopo = elemTopo.sub_topology(elemTopo.side_rank(elemSide), elemSide); - Ioss::ElementTopology *ioss_topo = Ioss::ElementTopology::factory(faceTopo.name(), false); + Ioss::ElementTopology *ioss_topo = Ioss::ElementTopology::factory(sideTopo.name(), false); par_dimen = ioss_topo->parametric_dimension(); - side_rank = par_dimen == 1 ? stk::topology::EDGE_RANK : stk::topology::FACE_RANK; + side_rank = get_side_rank(region, block); } STKIORequire(par_dimen == 1 || par_dimen == 2); - if (par_dimen == 1) { + if (par_dimen == 1 && side_rank == stk::topology::EDGE_RANK) { // conversion from face ordinal to edge ordinal for shells if (elemTopo.is_shell()) { elemSide -= elemTopo.num_faces(); diff --git a/packages/stk/stk_io/stk_io/IossBridge.cpp b/packages/stk/stk_io/stk_io/IossBridge.cpp index 57cd09b1ab59..e645230b9b33 100644 --- a/packages/stk/stk_io/stk_io/IossBridge.cpp +++ b/packages/stk/stk_io/stk_io/IossBridge.cpp @@ -146,6 +146,12 @@ namespace stk { { const Ioss::SideBlock *sblk = dynamic_cast(entity); assert(sblk != nullptr); + + bool useShellAllFaceSides = sblk->get_database()->get_region()->property_exists("ENABLE_ALL_FACE_SIDES_SHELL"); + if (sblk->parent_element_topology()->is_shell() && useShellAllFaceSides) { + return stk::topology::FACE_RANK; + } + int rank = sblk->topology()->parametric_dimension(); if (sblk->topology()->shape() == Ioss::ElementShape::UNKNOWN) { rank = sblk->owner()->max_parametric_dimension(); @@ -1269,10 +1275,42 @@ const stk::mesh::FieldBase *declare_stk_field_internal(stk::mesh::MetaData &meta return stk::topology::BEGIN_TOPOLOGY; } + stk::topology map_ioss_to_all_face_sides_shell(const Ioss::ElementTopology* topology) + { + auto name = topology->name(); + + if (name == "edge2" || name == "edge3d2") { + return stk::topology::SHELL_SIDE_BEAM_2; + } else if (name == "edge3" || name == "edge3d3") { + return stk::topology::SHELL_SIDE_BEAM_3; + } else if (name == "trishell3") { + return stk::topology::SHELL_TRI_3_ALL_FACE_SIDES; + } else if (name == "trishell4") { + return stk::topology::SHELL_TRI_4_ALL_FACE_SIDES; + } else if (name == "trishell6") { + return stk::topology::SHELL_TRI_6_ALL_FACE_SIDES; + } else if (name == "shell4") { + return stk::topology::SHELL_QUAD_4_ALL_FACE_SIDES; + } else if (name == "shel8") { + return stk::topology::SHELL_QUAD_8_ALL_FACE_SIDES; + } else if (name == "shell9") { + return stk::topology::SHELL_QUAD_9_ALL_FACE_SIDES; + } else { + return stk::topology::INVALID_TOPOLOGY; + } + } + stk::topology map_ioss_topology_to_stk(const Ioss::ElementTopology *topology, - unsigned meshSpatialDimension) + unsigned meshSpatialDimension, bool useShellAllFaceSides) { + if (useShellAllFaceSides) { + auto topo = map_ioss_to_all_face_sides_shell(topology); + if (topo != stk::topology::INVALID_TOPOLOGY) + return topo; + } + stk::topology beginTopo = get_start_topology(topology, meshSpatialDimension); + for (stk::topology topo=beginTopo; topo < stk::topology::END_TOPOLOGY; ++topo) { if (topology->is_alias(topo.name())) { @@ -1293,13 +1331,27 @@ const stk::mesh::FieldBase *declare_stk_field_internal(stk::mesh::MetaData &meta return stk::topology::INVALID_TOPOLOGY; } + std::string map_all_face_sides_shell_to_ioss(stk::topology topo) + { + switch (topo) { + case stk::topology::SHELL_SIDE_BEAM_2 : return "edge3d2"; + case stk::topology::SHELL_SIDE_BEAM_3 : return "edge3d3"; + case stk::topology::SHELL_TRI_3_ALL_FACE_SIDES : return "trishell3"; + case stk::topology::SHELL_TRI_4_ALL_FACE_SIDES : return "trishell4"; + case stk::topology::SHELL_TRI_6_ALL_FACE_SIDES : return "trishell6"; + case stk::topology::SHELL_QUAD_4_ALL_FACE_SIDES : return "shell4"; + case stk::topology::SHELL_QUAD_8_ALL_FACE_SIDES : return "shell8"; + case stk::topology::SHELL_QUAD_9_ALL_FACE_SIDES : return "shell9"; + default : return topo.name(); + } + } + std::string map_stk_topology_to_ioss(stk::topology topo) { std::string name = topo.name(); // FIXME SHELL SIDE TOPOLOGY - if (topo == stk::topology::SHELL_SIDE_BEAM_2) { name = "edge3d2"; } - if (topo == stk::topology::SHELL_SIDE_BEAM_3) { name = "edge3d3"; } + name = map_all_face_sides_shell_to_ioss(topo); Ioss::ElementTopology *iossTopo = Ioss::ElementTopology::factory(name, true); return iossTopo != nullptr ? iossTopo->name() : "invalid"; @@ -1331,27 +1383,32 @@ const stk::mesh::FieldBase *declare_stk_field_internal(stk::mesh::MetaData &meta } } - void declare_stk_aliases(stk::mesh::Part& part, Ioss::GroupingEntity *ge, stk::mesh::MetaData &meta) + void declare_stk_aliases(Ioss::Region ®ion, stk::mesh::MetaData &meta, Ioss::EntityType entityType) { - meta.add_part_alias(part, part.name()); + const Ioss::AliasMap& ioss_alias_map = region.get_alias_map(entityType); + for(const auto& alias : ioss_alias_map) { + stk::mesh::Part* part = meta.get_part(alias.second); + if (part != nullptr) { + meta.add_part_alias(*part, part->name()); - if(nullptr != ge && ge->get_database() != nullptr) { - Ioss::Region* region = ge->get_database()->get_region(); - - if(ge->property_exists("db_name")) { - std::string canonName = ge->get_property("db_name").get_string(); - meta.add_part_alias(part, canonName); - } - - const Ioss::AliasMap& ioss_alias_map = region->get_alias_map(ge->type()); - for(auto&& alias : ioss_alias_map) { - if(stk::equal_case(alias.second, part.name())) { - meta.add_part_alias(part, alias.first); - } + meta.add_part_alias(*part, alias.first); } } } + void declare_stk_aliases(Ioss::Region ®ion, stk::mesh::MetaData &meta) + { + //There should be a line here for each entity-type processed in + //StkMeshIoBroker::create_input_mesh. + declare_stk_aliases(region, meta, Ioss::NODEBLOCK); + declare_stk_aliases(region, meta, Ioss::ELEMENTBLOCK); + declare_stk_aliases(region, meta, Ioss::SIDESET); + declare_stk_aliases(region, meta, Ioss::FACEBLOCK); + declare_stk_aliases(region, meta, Ioss::EDGEBLOCK); + declare_stk_aliases(region, meta, Ioss::NODESET); + declare_stk_aliases(region, meta, Ioss::ASSEMBLY); + } + stk::mesh::Part& declare_stk_part(Ioss::GroupingEntity* entity, stk::mesh::MetaData& meta) { if (entity->type() == Ioss::ASSEMBLY) { @@ -1366,7 +1423,10 @@ const stk::mesh::FieldBase *declare_stk_field_internal(stk::mesh::MetaData &meta { if (include_entity(entity)) { stk::mesh::Part & part = declare_stk_part(entity, meta); - declare_stk_aliases(part, entity, meta); + if(entity->property_exists("db_name")) { + std::string canonName = entity->get_property("db_name").get_string(); + meta.add_part_alias(part, canonName); + } if (entity->property_exists("id")) { meta.set_part_id(part, entity->get_property("id").get_int()); } @@ -1380,7 +1440,10 @@ const stk::mesh::FieldBase *declare_stk_field_internal(stk::mesh::MetaData &meta mesh::EntityRank type = get_entity_rank(entity, meta); stk::mesh::Part * part = nullptr; part = &meta.declare_part(entity->name(), type); - declare_stk_aliases(*part, entity, meta); + if(entity->property_exists("db_name")) { + std::string canonName = entity->get_property("db_name").get_string(); + meta.add_part_alias(*part, canonName); + } if (entity->property_exists("id")) { meta.set_part_id(*part, entity->get_property("id").get_int()); } @@ -1412,7 +1475,8 @@ const stk::mesh::FieldBase *declare_stk_field_internal(stk::mesh::MetaData &meta set_original_topology_type_from_ioss(entity, *part); } - stk::topology stkTopology = map_ioss_topology_to_stk(topology, meta.spatial_dimension()); + auto useShellAllFaceSides = entity->get_database()->get_region()->property_exists("ENABLE_ALL_FACE_SIDES_SHELL"); + stk::topology stkTopology = map_ioss_topology_to_stk(topology, meta.spatial_dimension(), useShellAllFaceSides); if (stkTopology != stk::topology::INVALID_TOPOLOGY) { if (stkTopology.rank() != part->primary_entity_rank() && entity->entity_count() == 0) { std::ostringstream os; @@ -2238,7 +2302,7 @@ const stk::mesh::FieldBase *declare_stk_field_internal(stk::mesh::MetaData &meta } std::tuple - get_touching_element_block_topology_from_side_block_by_tokenization(stk::io::OutputParams ¶ms, const stk::mesh::Part& part) + get_touching_element_block_topology_from_side_block_by_tokenization(stk::io::OutputParams ¶ms, const stk::mesh::Part& part, Ioss::SideSet *sset) { const stk::mesh::BulkData &bulk = params.bulk_data(); @@ -2288,7 +2352,8 @@ const stk::mesh::FieldBase *declare_stk_field_internal(stk::mesh::MetaData &meta if (elementTopo != nullptr) { elementTopoName = elementTopo->name(); - stkElementTopology = map_ioss_topology_to_stk(elementTopo, bulk.mesh_meta_data().spatial_dimension()); + bool useShellAllFaceSides = sset->get_database()->get_region()->property_exists("ENABLE_ALL_FACE_SIDES_SHELL"); + stkElementTopology = map_ioss_topology_to_stk(elementTopo, bulk.mesh_meta_data().spatial_dimension(), useShellAllFaceSides); } } @@ -2296,9 +2361,9 @@ const stk::mesh::FieldBase *declare_stk_field_internal(stk::mesh::MetaData &meta } std::tuple - get_touching_element_block_topology_from_side_block(stk::io::OutputParams ¶ms, const stk::mesh::Part& part) + get_touching_element_block_topology_from_side_block(stk::io::OutputParams ¶ms, const stk::mesh::Part& part, Ioss::SideSet *sset) { - return get_touching_element_block_topology_from_side_block_by_tokenization(params, part); + return get_touching_element_block_topology_from_side_block_by_tokenization(params, part, sset); } void define_side_block(stk::io::OutputParams ¶ms, @@ -2320,7 +2385,7 @@ const stk::mesh::FieldBase *declare_stk_field_internal(stk::mesh::MetaData &meta stk::topology stkElementTopology = stk::topology::INVALID_TOPOLOGY; std::tie(elementTopoName, elementTopo, stkElementTopology) = - get_touching_element_block_topology_from_side_block(params, part); + get_touching_element_block_topology_from_side_block(params, part, sset); const stk::mesh::BulkData &bulk = params.bulk_data(); diff --git a/packages/stk/stk_io/stk_io/IossBridge.hpp b/packages/stk/stk_io/stk_io/IossBridge.hpp index c28a91e58114..0198587b9f04 100644 --- a/packages/stk/stk_io/stk_io/IossBridge.hpp +++ b/packages/stk/stk_io/stk_io/IossBridge.hpp @@ -172,6 +172,8 @@ void internal_part_processing(Ioss::GroupingEntity *entity, stk::mesh::MetaData void internal_part_processing(Ioss::EntityBlock *entity, stk::mesh::MetaData &meta, TopologyErrorHandler handler); +void declare_stk_aliases(Ioss::Region& region, stk::mesh::MetaData& meta); + /** This is the primary function used by an application to define * the stk::mesh which corresponds to the Ioss mesh read from the * finite element model (e.g. exodusII file). For all entities in @@ -332,7 +334,7 @@ void define_io_fields(Ioss::GroupingEntity *entity, * stk::topology. If a corresponding topology is not found, a * runtime error exception will be thrown. */ -stk::topology map_ioss_topology_to_stk(const Ioss::ElementTopology *topology, unsigned mesh_spatial_dimension); +stk::topology map_ioss_topology_to_stk(const Ioss::ElementTopology *topology, unsigned mesh_spatial_dimension, bool useShellAllFaceSides = false); /** Given a stk::topology, return the * corresponding Ioss::ElementTopology string. If a corresponding @@ -656,7 +658,8 @@ void fill_data_for_side_block( OutputParams ¶ms, { STK_ThrowRequireMsg(io.type() == Ioss::SIDEBLOCK, "Input GroupingEntity must be of type Ioss::SIDEBLOCK"); - stk::topology stk_elem_topology = map_ioss_topology_to_stk(element_topology, params.bulk_data().mesh_meta_data().spatial_dimension()); + bool useShellAllFaceSides = io.get_database()->get_region()->property_exists("ENABLE_ALL_FACE_SIDES_SHELL"); + stk::topology stk_elem_topology = map_ioss_topology_to_stk(element_topology, params.bulk_data().mesh_meta_data().spatial_dimension(), useShellAllFaceSides); const stk::mesh::Part *parentElementBlock = get_parent_element_block(params.bulk_data(), params.io_region(), part->name()); diff --git a/packages/stk/stk_io/stk_io/ProcessSetsOrBlocks.cpp b/packages/stk/stk_io/stk_io/ProcessSetsOrBlocks.cpp index 76939854e99f..f50450bca6e2 100644 --- a/packages/stk/stk_io/stk_io/ProcessSetsOrBlocks.cpp +++ b/packages/stk/stk_io/stk_io/ProcessSetsOrBlocks.cpp @@ -314,6 +314,22 @@ void set_sideset_topology(const Ioss::SideSet *ss, stk::mesh::Part *part, const } } +void adjust_par_dimen_for_shell_all_face_sides(stk::topology topo, int& par_dimen) +{ + switch (topo) { + case stk::topology::SHELL_TRI_3_ALL_FACE_SIDES: + case stk::topology::SHELL_TRI_4_ALL_FACE_SIDES: + case stk::topology::SHELL_TRI_6_ALL_FACE_SIDES: + case stk::topology::SHELL_QUAD_4_ALL_FACE_SIDES: + case stk::topology::SHELL_QUAD_8_ALL_FACE_SIDES: + case stk::topology::SHELL_QUAD_9_ALL_FACE_SIDES: + par_dimen = 2; + break; + default: + break; + } +} + template void process_surface_entity(const Ioss::SideSet* sset, stk::mesh::BulkData & bulk, std::vector &sidesToMove, stk::io::StkMeshIoBroker::SideSetFaceCreationBehavior behavior) { @@ -323,6 +339,8 @@ void process_surface_entity(const Ioss::SideSet* sset, stk::mesh::BulkData & bul Ioss::Region *region = sset->get_database()->get_region(); + bool useShellAllFaceSides = region->property_exists("ENABLE_ALL_FACE_SIDES_SHELL"); + stk::mesh::SideSet *stkSideSet = nullptr; stk::mesh::Part *stkSideSetPart = get_part_for_grouping_entity(*region, meta, sset); bool internalSidesetFlag = true; @@ -410,9 +428,9 @@ void process_surface_entity(const Ioss::SideSet* sset, stk::mesh::BulkData & bul if(par_dimen == 0) { stk::topology elemTopo = bulk.bucket(elem).topology(); - stk::topology faceTopo = elemTopo.sub_topology(elemTopo.side_rank(), side_ordinal); + stk::topology sideTopo = elemTopo.sub_topology(elemTopo.side_rank(side_ordinal), side_ordinal); - Ioss::ElementTopology *ioss_topo = Ioss::ElementTopology::factory(faceTopo.name(), false); + Ioss::ElementTopology *ioss_topo = Ioss::ElementTopology::factory(sideTopo.name(), false); par_dimen = ioss_topo->parametric_dimension(); } @@ -426,6 +444,11 @@ void process_surface_entity(const Ioss::SideSet* sset, stk::mesh::BulkData & bul } } + if (useShellAllFaceSides) { + stk::topology elemTopo = bulk.bucket(elem).topology(); + adjust_par_dimen_for_shell_all_face_sides(elemTopo, par_dimen); + } + if (par_dimen == 1) { stk::topology elemTopo = bulk.bucket(elem).topology(); // conversion from face ordinal to edge ordinal for shells diff --git a/packages/stk/stk_io/stk_io/SidesetTranslator.hpp b/packages/stk/stk_io/stk_io/SidesetTranslator.hpp index 0b4b3d64c007..b92105819355 100644 --- a/packages/stk/stk_io/stk_io/SidesetTranslator.hpp +++ b/packages/stk/stk_io/stk_io/SidesetTranslator.hpp @@ -48,6 +48,34 @@ namespace stk { namespace io { +namespace impl { + +inline bool check_parent_topology_has_mixed_ranked_sides(const stk::mesh::Part* part, const stk::mesh::Part* parentElementBlock, + stk::topology stk_element_topology) +{ + if (parentElementBlock != nullptr) { + if (parentElementBlock->primary_entity_rank() != stk::topology::ELEM_RANK) { + STK_ThrowErrorMsg("Part: " << parentElementBlock->name() << " is not an element part."); + } + return parentElementBlock->topology().has_mixed_rank_sides(); + } + + if (stk_element_topology.rank() == stk::topology::ELEM_RANK) { + return stk_element_topology.has_mixed_rank_sides(); + } + + auto supersets = part->supersets(); + auto hasMixedRankSides = false; + for (auto topoPart : supersets) { + if (is_element_block(*topoPart)) { + hasMixedRankSides = true; + } + } + return hasMixedRankSides; +} + +} + template void fill_element_and_side_ids_from_sideset(const stk::mesh::SideSet& sset, stk::io::OutputParams ¶ms, @@ -71,7 +99,6 @@ void fill_element_and_side_ids_from_sideset(const stk::mesh::SideSet& sset, selector &= *faceOutputSelector; } stk::mesh::Selector parentElementSelector = (parentElementBlock == nullptr) ? stk::mesh::Selector() : *parentElementBlock; - const stk::mesh::EntityRank sideRank = part->primary_entity_rank(); unsigned previousBucketId = stk::mesh::INVALID_BUCKET_ID; @@ -79,8 +106,14 @@ void fill_element_and_side_ids_from_sideset(const stk::mesh::SideSet& sset, { stk::mesh::Entity element = sset[i].element; stk::mesh::EntityId elemId = bulk_data.identifier(element); - int zero_based_side_ord = sset[i].side - sideOrdOffset; - stk::mesh::Entity side = stk::mesh::get_side_entity_for_elem_side_pair_of_rank(bulk_data, element, zero_based_side_ord, sideRank); + stk::mesh::EntityRank sideRank = bulk_data.bucket(element).topology().side_rank(sset[i].side); + int ioss_zero_based_side_ord = sset[i].side - sideOrdOffset; + int stk_zero_based_side_ord = sset[i].side; + if (part->primary_entity_rank() == stk::topology::EDGE_RANK && + impl::check_parent_topology_has_mixed_ranked_sides(part, parentElementBlock, stk_element_topology)) { + stk_zero_based_side_ord -= sideOrdOffset; + } + stk::mesh::Entity side = stk::mesh::get_side_entity_for_elem_side_pair_of_rank(bulk_data, element, stk_zero_based_side_ord, sideRank); if(bulk_data.is_valid(side)) { stk::mesh::Bucket &sideBucket = bulk_data.bucket(side); @@ -107,7 +140,7 @@ void fill_element_and_side_ids_from_sideset(const stk::mesh::SideSet& sset, if (selectedByBucket && selectedByParent && selectedByOutput) { elem_side_ids.push_back(elemId); - elem_side_ids.push_back(zero_based_side_ord + 1); + elem_side_ids.push_back(ioss_zero_based_side_ord + 1); sides.push_back(side); } } diff --git a/packages/stk/stk_io/stk_io/StkMeshIoBroker.cpp b/packages/stk/stk_io/stk_io/StkMeshIoBroker.cpp index ff689be6b6b4..fb9f5e4438eb 100644 --- a/packages/stk/stk_io/stk_io/StkMeshIoBroker.cpp +++ b/packages/stk/stk_io/stk_io/StkMeshIoBroker.cpp @@ -165,7 +165,8 @@ StkMeshIoBroker::StkMeshIoBroker() m_autoLoadDistributionFactorPerNodeSet(true), m_enableEdgeIO(false), m_cacheEntityListForTransientSteps(false), - m_throwOnMissingInputFields(false) + m_throwOnMissingInputFields(false), + m_enableAllFaceSidesShellTopo(false) { Ioss::Init::Initializer::initialize_ioss(); } @@ -179,7 +180,8 @@ StkMeshIoBroker::StkMeshIoBroker(stk::ParallelMachine comm) m_autoLoadDistributionFactorPerNodeSet(true), m_enableEdgeIO(false), m_cacheEntityListForTransientSteps(false), - m_throwOnMissingInputFields(false) + m_throwOnMissingInputFields(false), + m_enableAllFaceSidesShellTopo(false) { Ioss::Init::Initializer::initialize_ioss(); } @@ -496,6 +498,10 @@ void StkMeshIoBroker::create_input_mesh() STK_ThrowErrorMsgIf(region==nullptr, "INTERNAL ERROR: Mesh Input Region pointer is NULL in create_input_mesh."); + if (get_enable_all_face_sides_shell_topo()) { + region->property_add(Ioss::Property("ENABLE_ALL_FACE_SIDES_SHELL", "YES")); + } + // See if meta data is null, if so, create a new one... if (is_meta_data_null()) { m_metaData = m_meshBuilder->create_meta_data(); @@ -534,6 +540,11 @@ void StkMeshIoBroker::create_input_mesh() process_assemblies(*region, meta_data()); build_assembly_hierarchies(*region, meta_data()); + //declare_stk_aliases adds aliases for each of the entity-types + //processed in the above few lines. If we add a new entity-type + //here, update the implementation of declare_stk_aliases!!! + declare_stk_aliases(*region, meta_data()); + create_surface_to_block_mapping(); store_attribute_field_ordering(); } @@ -592,6 +603,11 @@ size_t StkMeshIoBroker::create_output_mesh(const std::string &filename, Database auto output_file = std::shared_ptr(new impl::OutputFile(out_filename, m_communicator, db_type, properties, input_region, type, openFileImmediately)); + + if (get_enable_all_face_sides_shell_topo()) { + output_file->get_output_ioss_region()->property_add(Ioss::Property("ENABLE_ALL_FACE_SIDES_SHELL", "YES")); + } + m_outputFiles.push_back(output_file); size_t index_of_output_file = m_outputFiles.size()-1; return index_of_output_file; @@ -781,10 +797,14 @@ void StkMeshIoBroker::populate_mesh_entitysets(bool i_started_modification_cycle stk::mesh::toggle_sideset_updaters(bulk_data(), true); } -void StkMeshIoBroker::populate_mesh(bool delay_field_data_allocation) +void StkMeshIoBroker::populate_mesh(bool delayFieldDataAllocation) { - bool i_started_modification_cycle = populate_mesh_elements_and_nodes(delay_field_data_allocation); + bool i_started_modification_cycle = populate_mesh_elements_and_nodes(delayFieldDataAllocation); populate_mesh_entitysets(i_started_modification_cycle); + + if(check_integer_size_requirements() == 8) { + m_bulkData->set_large_ids_flag(true); + } } template @@ -814,6 +834,11 @@ void StkMeshIoBroker::populate_field_data() } else { process_field_data(*region, bulk_data(), m_autoLoadAttributes); } + + if(m_bulkData->is_automatic_aura_on()) { + std::vector< const stk::mesh::FieldBase *> fields(m_metaData->get_fields().begin(), m_metaData->get_fields().end()); + stk::mesh::communicate_field_data(m_bulkData->aura_ghosting(), fields); + } } void StkMeshIoBroker::create_bulk_data() @@ -844,23 +869,10 @@ void StkMeshIoBroker::populate_bulk_data() create_bulk_data(); - // to preserve behavior for callers of this method, don't do the - // delay-field-data-allocation optimization. - // If want the optimization, call the population_mesh/populate_field_data methods separately. - - bool delay_field_data_allocation = false; - populate_mesh(delay_field_data_allocation); + const bool delayFieldDataAllocation = true; + populate_mesh(delayFieldDataAllocation); populate_field_data(); - - if(m_bulkData->is_automatic_aura_on()) { - std::vector< const stk::mesh::FieldBase *> fields(m_metaData->get_fields().begin(), m_metaData->get_fields().end()); - stk::mesh::communicate_field_data(m_bulkData->aura_ghosting(), fields); - } - - if(check_integer_size_requirements() == 8) { - m_bulkData->set_large_ids_flag(true); - } } void StkMeshIoBroker::add_input_field(const stk::io::MeshField &mesh_field) @@ -1260,6 +1272,16 @@ bool StkMeshIoBroker::get_throw_on_missing_input_fields() const return m_throwOnMissingInputFields; } +void StkMeshIoBroker::set_enable_all_face_sides_shell_topo(bool flag) +{ + m_enableAllFaceSidesShellTopo = flag; +} + +bool StkMeshIoBroker::get_enable_all_face_sides_shell_topo() const +{ + return m_enableAllFaceSidesShellTopo; +} + void StkMeshIoBroker::set_option_to_not_collapse_sequenced_fields() { property_add(Ioss::Property("ENABLE_FIELD_RECOGNITION", "NO")); diff --git a/packages/stk/stk_io/stk_io/StkMeshIoBroker.hpp b/packages/stk/stk_io/stk_io/StkMeshIoBroker.hpp index 2b1201ded8a5..f58f08df3a40 100644 --- a/packages/stk/stk_io/stk_io/StkMeshIoBroker.hpp +++ b/packages/stk/stk_io/stk_io/StkMeshIoBroker.hpp @@ -325,7 +325,7 @@ namespace stk { // // NOTE: this function internally calls the two methods // 'populate_mesh()' and 'populate_field_data()', declared - // below, and does NOT do the delayed field-data allocation + // below, and does the delayed field-data allocation // optimization. void populate_bulk_data(); @@ -336,8 +336,8 @@ namespace stk { // 'populate_field_data()' method declared below. // Note that the above-declared 'populate_bulk_data()' method // calls both of these methods. - virtual void populate_mesh(bool delay_field_data_allocation = true); - bool populate_mesh_elements_and_nodes(bool delay_field_data_allocation); + virtual void populate_mesh(bool delayFieldDataAllocation = true); + bool populate_mesh_elements_and_nodes(bool delayFieldDataAllocation); void populate_mesh_entitysets(bool i_started_modification_cycle); // Read/generate the field-data for the mesh, including @@ -653,6 +653,9 @@ namespace stk { void set_throw_on_missing_input_fields(bool flag); bool get_throw_on_missing_input_fields() const; + void set_enable_all_face_sides_shell_topo(bool flag); + bool get_enable_all_face_sides_shell_topo() const; + void set_option_to_not_collapse_sequenced_fields(); int get_num_time_steps() const; double get_max_time() const; @@ -769,6 +772,7 @@ namespace stk { bool m_enableEdgeIO; bool m_cacheEntityListForTransientSteps; bool m_throwOnMissingInputFields{false}; + bool m_enableAllFaceSidesShellTopo; }; inline std::shared_ptr StkMeshIoBroker::get_output_ioss_region(size_t output_file_index) const { diff --git a/packages/stk/stk_math/stk_math/StkMath.hpp b/packages/stk/stk_math/stk_math/StkMath.hpp index a3e72e136853..94089365433e 100644 --- a/packages/stk/stk_math/stk_math/StkMath.hpp +++ b/packages/stk/stk_math/stk_math/StkMath.hpp @@ -35,162 +35,250 @@ #ifndef STK_MATH_H #define STK_MATH_H -#include #include #include #include #include +#include #define STK_MATH_FORCE_INLINE KOKKOS_FORCEINLINE_FUNCTION namespace stk { namespace math { -namespace hidden { -static STK_MATH_FORCE_INLINE double Cbrt(double x) { return cbrt(x); } -static STK_MATH_FORCE_INLINE float CbrtF(float x) { return cbrtf(x); } -} - template::value, int>::type = 0> STK_MATH_FORCE_INLINE T fmadd(T a, T b, T c) { return a*b+c; } -template::value, int>::type = 0> -STK_MATH_FORCE_INLINE T sqrt(T x) { - return std::sqrt(x); +template ::value && !std::is_same::value, int>::type = 0> +STK_MATH_FORCE_INLINE T sqrt(T x) +{ + return Kokkos::sqrt(x); } -template::value, int>::type = 0> +inline long double sqrt(long double x) { + return Kokkos::sqrtl(x); +} + +template ::value && !std::is_same::value, int>::type = 0> STK_MATH_FORCE_INLINE T cbrt(T x) { - return hidden::Cbrt(x); + return Kokkos::cbrt(x); } -template::value, int>::type = 0> +inline long double cbrt(long double x) { + return Kokkos::cbrtl(x); +} + +template ::value && !std::is_same::value, int>::type = 0> STK_MATH_FORCE_INLINE T log(T x) { - return std::log(x); + return Kokkos::log(x); } -template::value, int>::type = 0> +inline long double log(long double x) { + return Kokkos::logl(x); +} + +template ::value && !std::is_same::value, int>::type = 0> STK_MATH_FORCE_INLINE T log10(T x) { - return std::log10(x); + return Kokkos::log10(x); } -template::value, int>::type = 0> +inline long double log10(long double x) { + return Kokkos::log10l(x); +} + +template ::value && !std::is_same::value, int>::type = 0> STK_MATH_FORCE_INLINE T exp(T x) { - return std::exp(x); + return Kokkos::exp(x); +} + +inline long double exp(long double x) { + return Kokkos::expl(x); } STK_MATH_FORCE_INLINE double pow(const double x, const double y) { - return std::pow(x, y); + return Kokkos::pow(x, y); } STK_MATH_FORCE_INLINE float pow(const float x, const float y) { - return std::pow(x, y); + return Kokkos::pow(x, y); } STK_MATH_FORCE_INLINE double pow(const double x, int y) { - return std::pow(x, y); + return Kokkos::pow(x, y); } STK_MATH_FORCE_INLINE float pow(const float x, int y) { - return std::pow(x, y); + return Kokkos::pow(x, y); } -template::value, int>::type = 0> +template ::value && !std::is_same::value, int>::type = 0> STK_MATH_FORCE_INLINE T sin(T a) { - return std::sin(a); + return Kokkos::sin(a); } -template::value, int>::type = 0> +inline long double sin(long double a) { + return Kokkos::sinl(a); +} + +template ::value && !std::is_same::value, int>::type = 0> STK_MATH_FORCE_INLINE T cos(T a) { - return std::cos(a); + return Kokkos::cos(a); } -template::value, int>::type = 0> +inline long double cos(long double a) { + return Kokkos::cosl(a); +} + +template ::value && !std::is_same::value, int>::type = 0> STK_MATH_FORCE_INLINE T tan(T a) { - return std::tan(a); + return Kokkos::tan(a); } -template::value, int>::type = 0> +inline long double tan(long double a) { + return Kokkos::tanl(a); +} + +template ::value && !std::is_same::value, int>::type = 0> STK_MATH_FORCE_INLINE T sinh(T a) { - return std::sinh(a); + return Kokkos::sinh(a); } -template::value, int>::type = 0> +inline long double sinh(long double a) { + return Kokkos::sinhl(a); +} + +template ::value && !std::is_same::value, int>::type = 0> STK_MATH_FORCE_INLINE T cosh(T a) { - return std::cosh(a); + return Kokkos::cosh(a); } -template::value, int>::type = 0> +inline long double cosh(long double a) { + return Kokkos::coshl(a); +} + +template ::value && !std::is_same::value, int>::type = 0> STK_MATH_FORCE_INLINE T tanh(T a) { - return std::tanh(a); + return Kokkos::tanh(a); } -template::value, int>::type = 0> +inline long double tanh(long double a) { + return Kokkos::tanhl(a); +} + +template ::value && !std::is_same::value, int>::type = 0> STK_MATH_FORCE_INLINE T asin(T a) { - return std::asin(a); + return Kokkos::asin(a); } -template::value, int>::type = 0> +inline long double asin(long double a) { + return Kokkos::asinl(a); +} + +template ::value && !std::is_same::value, int>::type = 0> STK_MATH_FORCE_INLINE T acos(T a) { - return std::acos(a); + return Kokkos::acos(a); } -template::value, int>::type = 0> +inline long double acos(long double a) { + return Kokkos::acosl(a); +} + +template ::value && !std::is_same::value, int>::type = 0> STK_MATH_FORCE_INLINE T atan(T a) { - return std::atan(a); + return Kokkos::atan(a); } -template::value, int>::type = 0> +inline long double atan(long double a) { + return Kokkos::atanl(a); +} + +template ::value && !std::is_same::value, int>::type = 0> STK_MATH_FORCE_INLINE T atan2(T a, T b) { - return std::atan2(a, b); + return Kokkos::atan2(a,b); } -template::value, int>::type = 0> +inline long double atan2(long double a, long double b) { + return Kokkos::atan2l(a,b); +} + +template ::value && !std::is_same::value, int>::type = 0> STK_MATH_FORCE_INLINE T asinh(T a) { - return std::asinh(a); + return Kokkos::asinh(a); } -template::value, int>::type = 0> +inline long double asinh(long double a) { + return Kokkos::asinhl(a); +} + +template ::value && !std::is_same::value, int>::type = 0> STK_MATH_FORCE_INLINE T acosh(T a) { - return std::acosh(a); + return Kokkos::acosh(a); } -template::value, int>::type = 0> +inline long double acosh(long double a) { + return Kokkos::acoshl(a); +} + +template ::value && !std::is_same::value, int>::type = 0> STK_MATH_FORCE_INLINE T atanh(T a) { - return std::atanh(a); + return Kokkos::atanh(a); } -template::value, int>::type = 0> +inline long double atanh(long double a) { + return Kokkos::atanhl(a); +} + +template ::value && !std::is_same::value, int>::type = 0> STK_MATH_FORCE_INLINE T erf(T a) { - return std::erf(a); + return Kokkos::erf(a); } -template::value, int>::type = 0> -STK_MATH_FORCE_INLINE T multiplysign(T x, T y) { // return x times sign of y - return x * std::copysign(static_cast(1.0), y); +inline long double erf(long double a) { + return Kokkos::erf(a); } -//template::value, int>::type = 0> -//STK_MATH_FORCE_INLINE T copysign(T x, T y) { // return abs(x) times sign of y -// return std::copysign(x, y); -//} +template ::value && !std::is_same::value, int>::type = 0> +STK_MATH_FORCE_INLINE T copysign(T x, T y) { + return Kokkos::copysign(x,y); +} -STK_MATH_FORCE_INLINE double copysign(double x, double y) { // return abs(x) times sign of y - return std::copysign(x, y); +inline long double copysign(long double x, long double y) { + return Kokkos::copysignl(x,y); } -STK_MATH_FORCE_INLINE float copysign(float x, float y) { // return abs(x) times sign of y - return std::copysign(x, y); +template::value, int>::type = 0> +STK_MATH_FORCE_INLINE T multiplysign(T x, T y) { // return x times sign of y + return x * copysign(static_cast(1.0), y); } STK_MATH_FORCE_INLINE double abs(const double x) { - return std::abs(x); + return Kokkos::abs(x); } STK_MATH_FORCE_INLINE float abs(const float x) { - return std::abs(x); + return Kokkos::abs(x); } STK_MATH_FORCE_INLINE double max(const double x, const double y) { @@ -211,7 +299,7 @@ STK_MATH_FORCE_INLINE float min(const float& x, const float& y) { template::value, int>::type = 0> STK_MATH_FORCE_INLINE bool isnan(T a) { - return std::isnan(a); + return Kokkos::isnan(a); } //template::value, int>::type = 0> diff --git a/packages/stk/stk_mesh/stk_mesh/base/Bucket.hpp b/packages/stk/stk_mesh/stk_mesh/base/Bucket.hpp index 9d9af289ca09..423d3c07eefc 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/Bucket.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/Bucket.hpp @@ -51,7 +51,7 @@ namespace stk { namespace mesh { class Bucket; } } namespace stk { namespace mesh { class BulkData; } } namespace stk { namespace mesh { class FieldBase; } } -namespace stk { namespace mesh { class DeviceMesh; } } +namespace stk { namespace mesh { template class DeviceMeshT; } } namespace stk { namespace mesh { namespace impl { class BucketRepository; } } } namespace stk { namespace mesh { namespace impl { class Partition; } } } namespace stk { namespace mesh { namespace impl { struct OverwriteEntityFunctor; } } } @@ -506,7 +506,7 @@ class Bucket friend class impl::Partition; friend struct impl::OverwriteEntityFunctor; friend class BulkData; - friend class DeviceMesh; + template friend class DeviceMeshT; BulkData & m_mesh; const EntityRank m_entity_rank; diff --git a/packages/stk/stk_mesh/stk_mesh/base/BulkData.cpp b/packages/stk/stk_mesh/stk_mesh/base/BulkData.cpp index ad975fddea5f..9870058c6a6d 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/BulkData.cpp +++ b/packages/stk/stk_mesh/stk_mesh/base/BulkData.cpp @@ -369,7 +369,7 @@ BulkData::BulkData(std::shared_ptr mesh_meta_data, m_parallel( parallel ), m_volatile_fast_shared_comm_map(), m_volatile_fast_shared_comm_map_sync_count(0), - m_ngpMeshHostData(), + m_ngpMeshHostDataBase(), m_all_sharing_procs(mesh_meta_data->entity_rank_count()), m_all_sharing_procs_sync_count(0), m_ghost_parts(), @@ -925,6 +925,9 @@ void BulkData::entity_comm_list_insert(Entity node) void BulkData::add_node_sharing(Entity node, int sharing_proc) { + STK_ThrowRequireMsg(sharing_proc != parallel_rank() && sharing_proc < parallel_size(), + "add_node_sharing: illegal sharing_proc="<& allFields = mesh_meta_data().get_fields(dst_rank); - for(int i = 0, iend = allFields.size(); i < iend; ++i) - { - const int src_size = allFields[i]->get_meta_data_for_field()[src_bucket_id].m_bytesPerEntity; - if(src_size == 0) - { - continue; - } + const std::vector& allFieldsForRank = mesh_meta_data().get_fields(dst_rank); + for(const FieldBase* field : allFieldsForRank) { - unsigned char * const src = allFields[i]->get_meta_data_for_field()[src_bucket_id].m_data; - const int dst_size = allFields[i]->get_meta_data_for_field()[dst_bucket_id].m_bytesPerEntity; + const FieldMetaData& dstFieldMeta = field->get_meta_data_for_field()[dst_bucket_id]; + const int dst_size = dstFieldMeta.m_bytesPerEntity; - if(dst_size) - { - unsigned char * const dst = allFields[i]->get_meta_data_for_field()[dst_bucket_id].m_data; - STK_ThrowAssertMsg( dst_size == src_size, - "Incompatible field sizes: " << dst_size << " != " << src_size); + if(dst_size) { + const FieldMetaData& srcFieldMeta = field->get_meta_data_for_field()[src_bucket_id]; + const int src_size = srcFieldMeta.m_bytesPerEntity; - std::memcpy(dst + dst_size * dst_bucket_ord, - src + src_size * src_bucket_ord, - dst_size); + if (src_size) { + STK_ThrowAssertMsg( dst_size == src_size, "Incompatible field sizes: " << dst_size << " != " << src_size); + unsigned char * const src = srcFieldMeta.m_data; + unsigned char * const dst = dstFieldMeta.m_data; + + std::memcpy(dst + dst_size * dst_bucket_ord, + src + src_size * src_bucket_ord, + dst_size); + } } } } @@ -3342,8 +3343,10 @@ void BulkData::internal_change_ghosting( for (std::set::reverse_iterator reverseIterator = removeSendGhosts.rbegin(); reverseIterator != removeSendGhosts.rend(); ++reverseIterator) { const EntityKey key = reverseIterator->first; + Entity entity = get_entity(key); const int proc = reverseIterator->second; - if (impl::has_upward_send_ghost_connectivity(*this, ghosting, proc, get_entity(key))) { + if (!is_valid(entity) || + impl::has_upward_send_ghost_connectivity(*this, ghosting, proc, get_entity(key))) { continue; } @@ -4554,73 +4557,6 @@ void BulkData::internal_update_all_sharing_procs() const } } -void BulkData::internal_update_ngp_fast_comm_maps() const -{ - if (m_ngpMeshHostData == nullptr) { - m_ngpMeshHostData = std::make_shared(); - } - impl::DeviceMeshHostData& ngpHostData = *m_ngpMeshHostData; - - const EntityRank num_ranks = static_cast(mesh_meta_data().entity_rank_count()); - m_volatile_fast_shared_comm_map.resize(num_ranks); - if (parallel_size() > 1) { - const EntityCommListInfoVector& all_comm = m_entity_comm_list; - const EntityCommDatabase& commDB = internal_comm_db(); - - // Assemble map, find all shared entities and pack into volatile fast map - std::vector > shared_entity_counts(num_ranks); - for (EntityRank r = stk::topology::BEGIN_RANK; r < num_ranks; ++r) { - shared_entity_counts[r].assign(parallel_size(), 0); - } - - for (size_t i = 0, ie = all_comm.size(); i < ie; ++i) { - EntityKey const key = all_comm[i].key; - EntityRank const rank = key.rank(); - - if (all_comm[i].entity_comm != -1) { - PairIterEntityComm ec = commDB.comm(all_comm[i].entity_comm); - for(; !ec.empty() && ec->ghost_id == BulkData::SHARED; ++ec) { - shared_entity_counts[rank][ec->proc]++; - } - } - } - - for (EntityRank r = stk::topology::BEGIN_RANK; r < num_ranks; ++r) { - Kokkos::resize(Kokkos::WithoutInitializing, ngpHostData.hostVolatileFastSharedCommMapOffset[r], parallel_size()+1); - unsigned offset = 0; - for(int p=0; pshared() && all_comm[i].entity_comm != -1) { - const unsigned bucket_id = idx.bucket->bucket_id(); - const unsigned bucket_ord = idx.bucket_ordinal; - - const EntityKey key = all_comm[i].key; - const EntityRank rank = key.rank(); - - PairIterEntityComm ec = commDB.comm(all_comm[i].entity_comm); - for(; !ec.empty() && ec->ghost_id == BulkData::SHARED; ++ec) { - const unsigned index = ngpHostData.hostVolatileFastSharedCommMapOffset[rank](ec->proc) + shared_entity_counts[rank][ec->proc]++; - ngpHostData.hostVolatileFastSharedCommMap[rank](index) = FastMeshIndex{bucket_id, bucket_ord}; - } - } - } - } - ngpHostData.volatileFastSharedCommMapSyncCount = synchronized_count(); -} - #ifndef STK_HIDE_DEPRECATED_CODE // Delete after Sept 2024 void BulkData::internal_update_fast_comm_maps() const { @@ -5884,5 +5820,10 @@ std::vector BulkData::get_sidesets() const return m_sideSetData.get_sidesets(); } +EntityRank BulkData::get_entity_rank_count() const +{ + return mesh_meta_data().entity_rank_count(); +} + } // namespace mesh } // namespace stk diff --git a/packages/stk/stk_mesh/stk_mesh/base/BulkData.hpp b/packages/stk/stk_mesh/stk_mesh/base/BulkData.hpp index ce1615918346..6942896ee20a 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/BulkData.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/BulkData.hpp @@ -66,7 +66,7 @@ #include "NgpProfilingBlock.hpp" #include "stk_mesh/baseImpl/SoloSideIdGenerator.hpp" #include "stk_mesh/baseImpl/SideSetImpl.hpp" -#include "stk_mesh/baseImpl/DeviceMeshHostData.hpp" +#include "stk_mesh/baseImpl/NgpMeshHostData.hpp" namespace stk { namespace mesh { class EntityLess; } } namespace stk { namespace mesh { class FieldBase; } } @@ -86,7 +86,7 @@ namespace stk { namespace io { class StkMeshIoBroker; } } namespace stk { namespace mesh { namespace impl { struct RelationEntityToNode; } } } namespace stk { namespace mesh { namespace impl { NgpMeshBase* get_ngp_mesh(const BulkData & bulk); } } } namespace stk { namespace mesh { namespace impl { void set_ngp_mesh(const BulkData & bulk, NgpMeshBase * ngpMesh); } } } -namespace stk { namespace mesh { namespace impl { DeviceMeshHostData* get_ngp_mesh_host_data(const BulkData & bulk); } } } +namespace stk { namespace mesh { namespace impl { template NgpMeshHostData* get_ngp_mesh_host_data(const BulkData & bulk); } } } namespace stk { namespace tools { @@ -178,6 +178,8 @@ class BulkData { std::shared_ptr mesh_meta_data_ptr() {return m_meta_data; } const std::shared_ptr mesh_meta_data_ptr() const { return m_meta_data; } + EntityRank get_entity_rank_count() const; + /** \brief The parallel machine */ ParallelMachine parallel() const { return m_parallel.parallel() ; } @@ -579,7 +581,9 @@ class BulkData { #ifndef STK_HIDE_DEPRECATED_CODE // Delete after Sept 2024 STK_DEPRECATED inline VolatileFastSharedCommMapOneRank const& volatile_fast_shared_comm_map(EntityRank rank) const; #endif - inline HostCommMapIndices volatile_fast_shared_comm_map(EntityRank rank, int proc) const; + + template + inline NgpCommMapIndicesHostMirrorT volatile_fast_shared_comm_map(EntityRank rank, int proc) const; const std::vector& all_sharing_procs(stk::mesh::EntityRank rank) const; @@ -1192,7 +1196,7 @@ class BulkData { #ifndef STK_HIDE_DEPRECATED_CODE // Delete after Sept 2024 void internal_update_fast_comm_maps() const; #endif - void internal_update_ngp_fast_comm_maps() const; + template void internal_update_ngp_fast_comm_maps() const; void internal_update_all_sharing_procs() const; void add_sharing_info(stk::mesh::Entity entity, stk::mesh::BulkData::GhostingId ghostingId, int sharingProc); @@ -1442,7 +1446,7 @@ class BulkData { friend class ::stk::mesh::FaceCreator; friend class ::stk::mesh::EntityLess; friend class ::stk::io::StkMeshIoBroker; - friend class stk::mesh::DeviceMesh; + template friend class stk::mesh::DeviceMeshT; friend class stk::mesh::StkFieldSyncDebugger; template class NgpDebugger> friend class stk::mesh::DeviceField; @@ -1474,7 +1478,7 @@ class BulkData { stk::mesh::Permutation side_permutation, const stk::mesh::PartVector& parts); friend NgpMeshBase * impl::get_ngp_mesh(const BulkData & bulk); friend void impl::set_ngp_mesh(const BulkData & bulk, NgpMeshBase * ngpMesh); - friend impl::DeviceMeshHostData* impl::get_ngp_mesh_host_data(const BulkData & bulk); + template friend impl::NgpMeshHostData* impl::get_ngp_mesh_host_data(const BulkData & bulk); template friend void stk::tools::replace_bulk_data(const stk::mesh::BulkData & in_mesh, T & out_mesh, std::function op); @@ -1554,7 +1558,7 @@ class BulkData { private: // data mutable VolatileFastSharedCommMap m_volatile_fast_shared_comm_map; mutable unsigned m_volatile_fast_shared_comm_map_sync_count; - mutable std::shared_ptr m_ngpMeshHostData; + mutable std::shared_ptr m_ngpMeshHostDataBase; mutable std::vector > m_all_sharing_procs; mutable unsigned m_all_sharing_procs_sync_count; PartVector m_ghost_parts; @@ -1992,6 +1996,73 @@ BulkData::in_send_ghost( Entity entity) const return false; } +template +void BulkData::internal_update_ngp_fast_comm_maps() const +{ + if (m_ngpMeshHostDataBase == nullptr) { + m_ngpMeshHostDataBase = std::shared_ptr(new impl::NgpMeshHostData); + } + impl::NgpMeshHostData* ngpHostData = dynamic_cast*>(m_ngpMeshHostDataBase.get()); + + const EntityRank num_ranks = static_cast(get_entity_rank_count()); + if (parallel_size() > 1) { + const EntityCommListInfoVector& all_comm = m_entity_comm_list; + const EntityCommDatabase& commDB = internal_comm_db(); + + // Assemble map, find all shared entities and pack into volatile fast map + std::vector > shared_entity_counts(num_ranks); + for (EntityRank r = stk::topology::BEGIN_RANK; r < num_ranks; ++r) { + shared_entity_counts[r].assign(parallel_size(), 0); + } + + for (size_t i = 0, ie = all_comm.size(); i < ie; ++i) { + EntityKey const key = all_comm[i].key; + EntityRank const rank = key.rank(); + + if (all_comm[i].entity_comm != -1) { + PairIterEntityComm ec = commDB.comm(all_comm[i].entity_comm); + for(; !ec.empty() && ec->ghost_id == BulkData::SHARED; ++ec) { + shared_entity_counts[rank][ec->proc]++; + } + } + } + + for (EntityRank r = stk::topology::BEGIN_RANK; r < num_ranks; ++r) { + Kokkos::resize(Kokkos::WithoutInitializing, ngpHostData->hostVolatileFastSharedCommMapOffset[r], parallel_size()+1); + unsigned offset = 0; + for(int p=0; phostVolatileFastSharedCommMapOffset[r](p) = offset; + offset += shared_entity_counts[r][p]; + } + ngpHostData->hostVolatileFastSharedCommMapOffset[r](parallel_size()) = offset; + Kokkos::resize(Kokkos::WithoutInitializing, ngpHostData->hostVolatileFastSharedCommMap[r], offset); + } + + for (EntityRank r = stk::topology::BEGIN_RANK; r < num_ranks; ++r) { + shared_entity_counts[r].assign(parallel_size(), 0); + } + + for (size_t i = 0, ie = all_comm.size(); i < ie; ++i) { + Entity const e = all_comm[i].entity; + MeshIndex const& idx = mesh_index(e); + if (idx.bucket->shared() && all_comm[i].entity_comm != -1) { + const unsigned bucket_id = idx.bucket->bucket_id(); + const unsigned bucket_ord = idx.bucket_ordinal; + + const EntityKey key = all_comm[i].key; + const EntityRank rank = key.rank(); + + PairIterEntityComm ec = commDB.comm(all_comm[i].entity_comm); + for(; !ec.empty() && ec->ghost_id == BulkData::SHARED; ++ec) { + const unsigned index = ngpHostData->hostVolatileFastSharedCommMapOffset[rank](ec->proc) + shared_entity_counts[rank][ec->proc]++; + ngpHostData->hostVolatileFastSharedCommMap[rank](index) = FastMeshIndex{bucket_id, bucket_ord}; + } + } + } + } + ngpHostData->volatileFastSharedCommMapSyncCount = synchronized_count(); +} + #ifndef STK_HIDE_DEPRECATED_CODE // Delete after Sept 2024 STK_DEPRECATED inline VolatileFastSharedCommMapOneRank const& BulkData::volatile_fast_shared_comm_map(EntityRank rank) const @@ -2005,24 +2076,27 @@ BulkData::volatile_fast_shared_comm_map(EntityRank rank) const } #endif -inline HostCommMapIndices +template +inline NgpCommMapIndicesHostMirrorT BulkData::volatile_fast_shared_comm_map(EntityRank rank, int proc) const { STK_ThrowAssert(this->in_synchronized_state()); STK_ThrowAssertMsg(rank < stk::topology::ELEMENT_RANK, "Cannot share entities of rank: " << rank); - if (m_ngpMeshHostData == nullptr || - m_ngpMeshHostData->volatileFastSharedCommMapSyncCount < synchronized_count()) { - internal_update_ngp_fast_comm_maps(); + if (m_ngpMeshHostDataBase == nullptr || + (dynamic_cast*>(m_ngpMeshHostDataBase.get()))->volatileFastSharedCommMapSyncCount < synchronized_count()) { + internal_update_ngp_fast_comm_maps(); } if (parallel_size() > 1) { - const size_t dataBegin = m_ngpMeshHostData->hostVolatileFastSharedCommMapOffset[rank](proc); - const size_t dataEnd = m_ngpMeshHostData->hostVolatileFastSharedCommMapOffset[rank](proc+1); - return Kokkos::subview(m_ngpMeshHostData->hostVolatileFastSharedCommMap[rank], Kokkos::pair(dataBegin, dataEnd)); + impl::NgpMeshHostData* ngpHostData = dynamic_cast*>(m_ngpMeshHostDataBase.get()); + + const size_t dataBegin = ngpHostData->hostVolatileFastSharedCommMapOffset[rank](proc); + const size_t dataEnd = ngpHostData->hostVolatileFastSharedCommMapOffset[rank](proc+1); + return Kokkos::subview(ngpHostData->hostVolatileFastSharedCommMap[rank], Kokkos::pair(dataBegin, dataEnd)); } else { - return HostCommMapIndices("empty comm map indices", 0); + return NgpCommMapIndicesHostMirrorT("empty comm map indices", 0); } } @@ -2243,12 +2317,13 @@ inline void set_ngp_mesh(const BulkData & bulk, NgpMeshBase * ngpMesh) { bulk.set_ngp_mesh(ngpMesh); } -inline impl::DeviceMeshHostData* get_ngp_mesh_host_data(const BulkData& bulk) +template +inline impl::NgpMeshHostData* get_ngp_mesh_host_data(const BulkData& bulk) { - if (bulk.m_ngpMeshHostData == nullptr) { - bulk.m_ngpMeshHostData = std::make_shared(); + if (bulk.m_ngpMeshHostDataBase == nullptr) { + bulk.m_ngpMeshHostDataBase = std::shared_ptr(new impl::NgpMeshHostData); } - return bulk.m_ngpMeshHostData.get(); + return dynamic_cast*>(bulk.m_ngpMeshHostDataBase.get()); } } diff --git a/packages/stk/stk_mesh/stk_mesh/base/DeviceField.hpp b/packages/stk/stk_mesh/stk_mesh/base/DeviceField.hpp index 95843b71c459..7793036e1248 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/DeviceField.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/DeviceField.hpp @@ -507,6 +507,7 @@ class DeviceField : public NgpFieldBase { if (buckets.size() > deviceView.extent(0)) { deviceView = ViewType(Kokkos::ViewAllocateWithoutInitializing(hostField->name() + suffix), impl::allocation_size(buckets.size())); +#ifndef STK_UNIFIED_MEMORY if (hostView.extent(0) != deviceView.extent(0)) { #if defined STK_USE_DEVICE_MESH && !defined(STK_ENABLE_GPU) hostView = Kokkos::create_mirror(deviceView); @@ -514,6 +515,7 @@ class DeviceField : public NgpFieldBase hostView = Kokkos::create_mirror_view(deviceView); #endif } +#endif } } @@ -545,11 +547,19 @@ class DeviceField : public NgpFieldBase { construct_bucket_views(buckets, "_numFieldBucketComponentsPerEntity", hostBucketScratchMemory, deviceFieldBucketsNumComponentsPerEntity); +#ifndef STK_UNIFIED_MEMORY for (size_t i=0; isize(); } Kokkos::deep_copy(get_execution_space(), deviceBucketSizes, hostBucketScratchMemory); +#else + for (size_t i=0; isize(); + } +#endif } void set_field_buckets_pointer_view(const BucketVector& buckets) @@ -693,11 +709,17 @@ class DeviceField : public NgpFieldBase Bucket* bucket = buckets[bucketIdx]; unsigned oldBucketId = bucket->get_ngp_field_bucket_id(get_ordinal()); bool isModified = oldBucketId == INVALID_BUCKET_ID || bucket->get_ngp_field_bucket_is_modified(get_ordinal()); - + +#ifndef STK_UNIFIED_MEMORY hostBucketScratchMemory(bucketIdx) = isModified ? 1 : 0; +#else + deviceFieldBucketsMarkedModified(bucketIdx) = isModified ? 1 : 0; +#endif } +#ifndef STK_UNIFIED_MEMORY Kokkos::deep_copy(get_execution_space(), deviceFieldBucketsMarkedModified, hostBucketScratchMemory); +#endif impl::transpose_new_and_modified_buckets_to_device(get_execution_space(), deviceBucketPtrData, deviceData, deviceBucketSizes, deviceFieldBucketsNumComponentsPerEntity, deviceFieldBucketsMarkedModified); diff --git a/packages/stk/stk_mesh/stk_mesh/base/DeviceMesh.cpp b/packages/stk/stk_mesh/stk_mesh/base/DeviceMesh.cpp deleted file mode 100644 index a905d526a86f..000000000000 --- a/packages/stk/stk_mesh/stk_mesh/base/DeviceMesh.cpp +++ /dev/null @@ -1,453 +0,0 @@ -// Copyright 2002 - 2008, 2010, 2011 National Technology Engineering -// Solutions of Sandia, LLC (NTESS). Under the terms of Contract -// DE-NA0003525 with NTESS, the U.S. Government retains certain rights -// in this software. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// * Neither the name of NTESS nor the names of its contributors -// may be used to endorse or promote products derived from this -// software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "stk_mesh/base/DeviceMesh.hpp" - -namespace stk { -namespace mesh { - -void DeviceBucket::initialize_bucket_attributes(const stk::mesh::Bucket &bucket) -{ - m_bucketId = bucket.bucket_id(); - m_bucketCapacity = bucket.capacity(); - m_bucketSize = bucket.size(); - m_entityRank = bucket.entity_rank(); - m_bucketTopology = bucket.topology(); -} - -void DeviceBucket::initialize_fixed_data_from_host(const stk::mesh::Bucket &bucket) -{ - const stk::mesh::PartVector& parts = bucket.supersets(); - m_partOrdinals = PartOrdinalViewType(Kokkos::view_alloc(Kokkos::WithoutInitializing, "PartOrdinals"), - parts.size()); - auto hostPartOrdinals = HostPartOrdinalViewType(bucket.superset_part_ordinals().first, parts.size()); - Kokkos::deep_copy(m_partOrdinals, hostPartOrdinals); -} - -std::pair -DeviceBucket::scan_entities_for_nodal_connectivity(const stk::mesh::Bucket & bucket) -{ - if (bucket.topology() == stk::topology::INVALID_TOPOLOGY) { - unsigned maxNodesPerEntity = 0; - unsigned totalNumConnectedNodes = 0; - for (unsigned i = 0; i < bucket.size(); ++i) { - maxNodesPerEntity = std::max(maxNodesPerEntity, bucket.num_nodes(i)); - totalNumConnectedNodes += bucket.num_nodes(i); - } - return std::make_pair(maxNodesPerEntity, totalNumConnectedNodes); - } - - return std::make_pair(bucket.topology().num_nodes(), - bucket.topology().num_nodes() * m_bucketCapacity); -} - -void DeviceBucket::resize_device_views(const stk::mesh::Bucket & bucket) -{ - Kokkos::Profiling::pushRegion("resize_device_views()"); - - const auto [maxNodesPerEntity, totalNumConnectedNodes] = scan_entities_for_nodal_connectivity(bucket); - - if (m_nodeOrdinals.size() != maxNodesPerEntity) { - m_nodeOrdinals = OrdinalViewType(Kokkos::view_alloc(Kokkos::WithoutInitializing, "NodeOrdinals"), - static_cast(maxNodesPerEntity)); - OrdinalViewType& nodeOrds = m_nodeOrdinals; //local var to avoid implicit this capture - Kokkos::parallel_for(Kokkos::RangePolicy(0, maxNodesPerEntity), - KOKKOS_LAMBDA(const int i) { - nodeOrds(i) = static_cast(i); - }); - } - - if (m_entities.size() != m_bucketCapacity) { - m_entities = EntityViewType(Kokkos::view_alloc(Kokkos::WithoutInitializing, "BucketEntities"), m_bucketCapacity); - STK_ThrowRequireMsg(m_bucketCapacity > 0, "bucket capacity must be greater than 0"); - } - - if (m_nodeConnectivity.size() != totalNumConnectedNodes) { - m_nodeConnectivity = BucketConnectivityType(Kokkos::view_alloc(Kokkos::WithoutInitializing, - "NodeConnectivity"), totalNumConnectedNodes); - } - - if (m_nodeConnectivityOffsets.size() != m_bucketCapacity+1) { - m_nodeConnectivityOffsets = OrdinalViewType(Kokkos::view_alloc(Kokkos::WithoutInitializing, - "NodeConnectivityOffsets"), m_bucketCapacity+1); - } - Kokkos::Profiling::popRegion(); -} - -void DeviceBucket::update_entity_data_from_host(const stk::mesh::Bucket &bucket) -{ - Kokkos::Profiling::pushRegion("update_entity_data_from_host()"); - - m_bucketSize = bucket.size(); - m_bucketCapacity = bucket.capacity(); - - resize_device_views(bucket); - - Kokkos::Profiling::pushRegion("filling host-side Views"); - auto hostEntities = HostEntityViewType(bucket.begin(), m_bucketCapacity); - auto hostNodeConnectivity = Kokkos::create_mirror_view(Kokkos::WithoutInitializing, m_nodeConnectivity); - auto hostNodeConnectivityOffsets = Kokkos::create_mirror_view(Kokkos::WithoutInitializing, m_nodeConnectivityOffsets); - unsigned nodeOffset = 0; - for (unsigned iEntity = 0; iEntity < bucket.size(); ++iEntity) { - const unsigned nodesPerEntity = bucket.num_nodes(iEntity); - const stk::mesh::Entity * elemNodes = bucket.begin_nodes(iEntity); - for (unsigned iNode = 0; iNode < nodesPerEntity; ++iNode) { - hostNodeConnectivity(nodeOffset + iNode) = elemNodes[iNode]; - } - hostNodeConnectivityOffsets(iEntity) = nodeOffset; - nodeOffset += nodesPerEntity; - } - hostNodeConnectivityOffsets(bucket.size()) = nodeOffset; - Kokkos::Profiling::popRegion(); - - Kokkos::Profiling::pushRegion("deep_copy entities/connectivity/offsets"); - Kokkos::deep_copy(m_entities, hostEntities); - Kokkos::deep_copy(m_nodeConnectivity, hostNodeConnectivity); - Kokkos::deep_copy(m_nodeConnectivityOffsets, hostNodeConnectivityOffsets); - Kokkos::Profiling::popRegion(); - - Kokkos::Profiling::popRegion(); -} - -void DeviceMesh::update_mesh() -{ - if (is_up_to_date()) { - return; - } - - require_ngp_mesh_rank_limit(bulk->mesh_meta_data()); - - Kokkos::Profiling::pushRegion("DeviceMesh::update_mesh"); - const bool anyChanges = fill_buckets(*bulk); - - if (anyChanges) { - set_entity_keys(*bulk); - copy_entity_keys_to_device(); - set_bucket_entity_offsets(*bulk); - copy_bucket_entity_offsets_to_device(); - fill_sparse_connectivities(*bulk); - copy_sparse_connectivities_to_device(); - copy_volatile_fast_shared_comm_map_to_device(); - fill_mesh_indices(*bulk); - copy_mesh_indices_to_device(); - } - - synchronizedCount = bulk->synchronized_count(); - Kokkos::Profiling::popRegion(); -} - -bool DeviceMesh::fill_buckets(const stk::mesh::BulkData& bulk_in) -{ - bool anyBucketChanges = false; - - Kokkos::Profiling::pushRegion("fill_buckets"); - for (stk::mesh::EntityRank rank = stk::topology::NODE_RANK; rank < endRank; ++rank) { - const stk::mesh::BucketVector& stkBuckets = bulk_in.buckets(rank); - unsigned numStkBuckets = stkBuckets.size(); - - BucketView bucketBuffer(Kokkos::view_alloc(Kokkos::WithoutInitializing, "BucketBuffer"), numStkBuckets); - - if (numStkBuckets != buckets[rank].size()) { - anyBucketChanges = true; - } - - for (unsigned iBucket = 0; iBucket < numStkBuckets; ++iBucket) { - stk::mesh::Bucket& stkBucket = *stkBuckets[iBucket]; - const unsigned ngpBucketId = stkBucket.ngp_bucket_id(); - - if (ngpBucketId == INVALID_BUCKET_ID) { - Kokkos::Profiling::pushRegion("new bucket"); - // New bucket on host - new (&bucketBuffer[iBucket]) DeviceBucket(); - bucketBuffer[iBucket].initialize_bucket_attributes(stkBucket); - bucketBuffer[iBucket].initialize_fixed_data_from_host(stkBucket); - bucketBuffer[iBucket].update_entity_data_from_host(stkBucket); - anyBucketChanges = true; - Kokkos::Profiling::popRegion(); - } - else { - Kokkos::Profiling::pushRegion("pre-existing bucket"); - // Pre-existing bucket on host - new (&bucketBuffer[iBucket]) DeviceBucket(buckets[rank][ngpBucketId]); - if (stkBucket.is_modified()) { - bucketBuffer[iBucket].update_entity_data_from_host(stkBucket); - anyBucketChanges = true; - } - bucketBuffer[iBucket].m_bucketId = stkBucket.bucket_id(); - Kokkos::Profiling::popRegion(); - } - - stkBucket.set_ngp_bucket_id(iBucket); - } - - if (is_last_bucket_reference(rank)) { - for (unsigned iBucket = 0; iBucket < buckets[rank].size(); ++iBucket) { - buckets[rank][iBucket].~DeviceBucket(); - } - } - - buckets[rank] = bucketBuffer; - } - Kokkos::Profiling::popRegion(); - - return anyBucketChanges; -} - -constexpr double RESIZE_FACTOR = 0.05; - -template -inline void reallocate_views(DEVICE_VIEW & deviceView, HOST_VIEW & hostView, size_t requiredSize, double resizeFactor = 0.0) -{ - const size_t currentSize = deviceView.extent(0); - const size_t shrinkThreshold = currentSize - static_cast(2*resizeFactor*currentSize); - const bool needGrowth = (requiredSize > currentSize); - const bool needShrink = (requiredSize < shrinkThreshold); - - if (needGrowth || needShrink) { - const size_t newSize = requiredSize + static_cast(resizeFactor*requiredSize); - deviceView = DEVICE_VIEW(Kokkos::view_alloc(Kokkos::WithoutInitializing, deviceView.label()), newSize); - hostView = Kokkos::create_mirror_view(Kokkos::WithoutInitializing, deviceView); - } -} - -void DeviceMesh::set_entity_keys(const stk::mesh::BulkData& bulk_in) -{ - unsigned totalNumEntityKeys = bulk_in.get_size_of_entity_index_space(); - auto& hostEntityKeys = deviceMeshHostData->hostEntityKeys; - - reallocate_views(entityKeys, hostEntityKeys, totalNumEntityKeys, RESIZE_FACTOR); - - for (stk::mesh::EntityRank rank = stk::topology::NODE_RANK; rank < endRank; ++rank) { - const stk::mesh::BucketVector& stkBuckets = bulk_in.buckets(rank); - for (unsigned i = 0; i < stkBuckets.size(); ++i) { - const stk::mesh::Bucket & bucket = *stkBuckets[i]; - for (unsigned j = 0; j < bucket.size(); ++j) { - stk::mesh::Entity entity = bucket[j]; - hostEntityKeys[entity.local_offset()] = bulk_in.entity_key(entity); - } - } - } -} - -void DeviceMesh::set_bucket_entity_offsets(const stk::mesh::BulkData& bulk_in) -{ - auto& hostBucketEntityOffsets = deviceMeshHostData->hostBucketEntityOffsets; - - for(stk::mesh::EntityRank rank=stk::topology::NODE_RANK; ranksize(); - } - for (unsigned i = stkBuckets.size(); i < hostBucketEntityOffsets[rank].extent(0); ++i) { - hostBucketEntityOffsets[rank](i) = bucketOffsetIntoEntities; - } - } -} - -void DeviceMesh::fill_sparse_connectivities(const stk::mesh::BulkData& bulk_in) -{ - auto& hostEntityConnectivityOffset = deviceMeshHostData->hostEntityConnectivityOffset; - auto& hostBucketEntityOffsets = deviceMeshHostData->hostBucketEntityOffsets; - auto& hostSparseConnectivity = deviceMeshHostData->hostSparseConnectivity; - auto& hostSparseConnectivityOrdinals = deviceMeshHostData->hostSparseConnectivityOrdinals; - auto& hostSparsePermutations = deviceMeshHostData->hostSparsePermutations; - - unsigned totalNumConnectedEntities[stk::topology::NUM_RANKS][stk::topology::NUM_RANKS] = {{0}, {0}, {0}, {0}, {0}}; - unsigned totalNumPermutations[stk::topology::NUM_RANKS][stk::topology::NUM_RANKS] = {{0}, {0}, {0}, {0}, {0}}; - - for(stk::mesh::EntityRank rank=stk::topology::NODE_RANK; rank 0) { - - const stk::mesh::Entity* connectedEntities = stkBucket.begin(iEntity, connectedRank); - const stk::mesh::ConnectivityOrdinal* connectedOrdinals = stkBucket.begin_ordinals(iEntity, connectedRank); - const stk::mesh::Permutation* permutations = hasPermutation ? stkBucket.begin_permutations(iEntity, connectedRank) : nullptr; - for(unsigned i=0; iget_size_of_entity_index_space(); - hostMeshIndices = HostMeshIndexType(Kokkos::view_alloc(Kokkos::WithoutInitializing, "host_mesh_indices"), indexSpaceSize); - - for (stk::mesh::EntityRank rank=stk::topology::NODE_RANK; rankhostEntityKeys; - - Kokkos::deep_copy(entityKeys, hostEntityKeys); -} - -void DeviceMesh::copy_mesh_indices_to_device() -{ - unsigned length = hostMeshIndices.size(); - Kokkos::View nonconst_device_mesh_indices(Kokkos::view_alloc(Kokkos::WithoutInitializing, "tmp_dev_mesh_indices"), length); - Kokkos::deep_copy(nonconst_device_mesh_indices, hostMeshIndices); - deviceMeshIndices = nonconst_device_mesh_indices; -} - -void DeviceMesh::copy_bucket_entity_offsets_to_device() -{ - auto& hostBucketEntityOffsets = deviceMeshHostData->hostBucketEntityOffsets; - - for(stk::mesh::EntityRank rank=stk::topology::NODE_RANK; rankhostEntityConnectivityOffset; - auto& hostSparseConnectivity = deviceMeshHostData->hostSparseConnectivity; - auto& hostSparseConnectivityOrdinals = deviceMeshHostData->hostSparseConnectivityOrdinals; - auto& hostSparsePermutations = deviceMeshHostData->hostSparsePermutations; - - for(stk::mesh::EntityRank rank=stk::topology::NODE_RANK; rankvolatile_fast_shared_comm_map(stk::topology::NODE_RANK, 0); - auto& hostVolatileFastSharedCommMapOffset = deviceMeshHostData->hostVolatileFastSharedCommMapOffset; - auto& hostVolatileFastSharedCommMap = deviceMeshHostData->hostVolatileFastSharedCommMap; - - for (stk::mesh::EntityRank rank = stk::topology::NODE_RANK; rank < stk::topology::ELEM_RANK; ++rank) - { - Kokkos::resize(Kokkos::WithoutInitializing, volatileFastSharedCommMapOffset[rank], hostVolatileFastSharedCommMapOffset[rank].extent(0)); - Kokkos::resize(Kokkos::WithoutInitializing, volatileFastSharedCommMap[rank], hostVolatileFastSharedCommMap[rank].extent(0)); - Kokkos::deep_copy(volatileFastSharedCommMapOffset[rank], hostVolatileFastSharedCommMapOffset[rank]); - Kokkos::deep_copy(volatileFastSharedCommMap[rank], hostVolatileFastSharedCommMap[rank]); - } -} - -} -} diff --git a/packages/stk/stk_mesh/stk_mesh/base/DeviceMesh.hpp b/packages/stk/stk_mesh/stk_mesh/base/DeviceMesh.hpp index a091d9ea966c..492e189e2545 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/DeviceMesh.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/DeviceMesh.hpp @@ -53,21 +53,22 @@ #include #include -#include "stk_mesh/baseImpl/DeviceMeshHostData.hpp" +#include "stk_mesh/baseImpl/NgpMeshHostData.hpp" namespace stk { namespace mesh { -class DeviceMesh; +template class DeviceMeshT; -struct DeviceBucket { +template +struct DeviceBucketT { using ConnectedNodes = util::StridedArray; using ConnectedEntities = util::StridedArray; using ConnectedOrdinals = util::StridedArray; using Permutations = util::StridedArray; KOKKOS_FUNCTION - DeviceBucket() + DeviceBucketT() : m_owningMesh(nullptr), m_bucketSize(0), m_bucketCapacity(0), @@ -148,7 +149,7 @@ struct DeviceBucket { PartOrdinalViewType m_partOrdinals; - const stk::mesh::DeviceMesh* m_owningMesh; + const stk::mesh::DeviceMeshT* m_owningMesh; unsigned m_bucketSize; unsigned m_bucketCapacity; @@ -158,19 +159,25 @@ struct DeviceBucket { stk::mesh::EntityRank m_entityRank; }; -class DeviceMesh : public NgpMeshBase +using DeviceBucket = DeviceBucketT; + +template +class DeviceMeshT : public NgpMeshBase { public: - using MeshExecSpace = stk::ngp::ExecSpace; - using ConnectedNodes = DeviceBucket::ConnectedNodes; - using ConnectedEntities = DeviceBucket::ConnectedEntities; - using ConnectedOrdinals = DeviceBucket::ConnectedOrdinals; - using Permutations = DeviceBucket::Permutations; + typedef NgpMemSpace ngp_mem_space; + + static_assert(Kokkos::is_memory_space_v); + using MeshExecSpace = typename NgpMemSpace::execution_space; + using BucketType = DeviceBucketT; + using ConnectedNodes = typename BucketType::ConnectedNodes; + using ConnectedEntities = typename BucketType::ConnectedEntities; + using ConnectedOrdinals = typename BucketType::ConnectedOrdinals; + using Permutations = typename BucketType::Permutations; using MeshIndex = FastMeshIndex; - using BucketType = DeviceBucket; KOKKOS_FUNCTION - DeviceMesh() + DeviceMeshT() : NgpMeshBase(), bulk(nullptr), spatial_dimension(0), @@ -178,7 +185,7 @@ class DeviceMesh : public NgpMeshBase deviceMeshHostData(nullptr) {} - explicit DeviceMesh(const stk::mesh::BulkData& b) + explicit DeviceMeshT(const stk::mesh::BulkData& b) : NgpMeshBase(), bulk(&b), spatial_dimension(b.mesh_meta_data().spatial_dimension()), @@ -188,17 +195,17 @@ class DeviceMesh : public NgpMeshBase deviceMeshHostData(nullptr) { bulk->register_device_mesh(); - deviceMeshHostData = impl::get_ngp_mesh_host_data(*bulk); + deviceMeshHostData = impl::get_ngp_mesh_host_data(*bulk); update_mesh(); } - KOKKOS_DEFAULTED_FUNCTION DeviceMesh(const DeviceMesh &) = default; - KOKKOS_DEFAULTED_FUNCTION DeviceMesh(DeviceMesh &&) = default; - KOKKOS_DEFAULTED_FUNCTION DeviceMesh& operator=(const DeviceMesh &) = default; - KOKKOS_DEFAULTED_FUNCTION DeviceMesh& operator=(DeviceMesh &&) = default; + KOKKOS_DEFAULTED_FUNCTION DeviceMeshT(const DeviceMeshT &) = default; + KOKKOS_DEFAULTED_FUNCTION DeviceMeshT(DeviceMeshT &&) = default; + KOKKOS_DEFAULTED_FUNCTION DeviceMeshT& operator=(const DeviceMeshT &) = default; + KOKKOS_DEFAULTED_FUNCTION DeviceMeshT& operator=(DeviceMeshT &&) = default; KOKKOS_FUNCTION - virtual ~DeviceMesh() override { + virtual ~DeviceMeshT() override { clear_buckets_and_views(); } @@ -394,18 +401,18 @@ class DeviceMesh : public NgpMeshBase } KOKKOS_FUNCTION - const DeviceBucket &get_bucket(stk::mesh::EntityRank rank, unsigned index) const + const DeviceBucketT &get_bucket(stk::mesh::EntityRank rank, unsigned index) const { buckets[rank](index).m_owningMesh = this; return buckets[rank](index); } KOKKOS_FUNCTION - DeviceCommMapIndices volatile_fast_shared_comm_map(stk::topology::rank_t rank, int proc) const + NgpCommMapIndicesT volatile_fast_shared_comm_map(stk::topology::rank_t rank, int proc) const { const size_t dataBegin = volatileFastSharedCommMapOffset[rank][proc]; const size_t dataEnd = volatileFastSharedCommMapOffset[rank][proc+1]; - DeviceCommMapIndices buffer = Kokkos::subview(volatileFastSharedCommMap[rank], Kokkos::pair(dataBegin, dataEnd)); + NgpCommMapIndicesT buffer = Kokkos::subview(volatileFastSharedCommMap[rank], Kokkos::pair(dataBegin, dataEnd)); return buffer; } @@ -417,7 +424,7 @@ class DeviceMesh : public NgpMeshBase const stk::mesh::BulkData &get_bulk_on_host() const { - STK_ThrowRequireMsg(bulk != nullptr, "DeviceMesh::get_bulk_on_host, bulk==nullptr"); + STK_ThrowRequireMsg(bulk != nullptr, "DeviceMeshT::get_bulk_on_host, bulk==nullptr"); return *bulk; } @@ -478,13 +485,13 @@ class DeviceMesh : public NgpMeshBase void copy_volatile_fast_shared_comm_map_to_device(); - using BucketView = Kokkos::View; + using BucketView = Kokkos::View*, stk::ngp::UVMMemSpace>; const stk::mesh::BulkData *bulk; unsigned spatial_dimension; unsigned synchronizedCount; stk::mesh::EntityRank endRank; Kokkos::View copyCounter; - impl::DeviceMeshHostData* deviceMeshHostData; + impl::NgpMeshHostData* deviceMeshHostData; EntityKeyViewType entityKeys; @@ -501,9 +508,12 @@ class DeviceMesh : public NgpMeshBase FastSharedCommMapViewType volatileFastSharedCommMap[stk::topology::NUM_RANKS]; }; +using DeviceMesh = DeviceMeshT; + +template KOKKOS_INLINE_FUNCTION -DeviceBucket::ConnectedEntities -DeviceBucket::get_connected_entities(unsigned offsetIntoBucket, stk::mesh::EntityRank connectedRank) const { +typename DeviceBucketT::ConnectedEntities +DeviceBucketT::get_connected_entities(unsigned offsetIntoBucket, stk::mesh::EntityRank connectedRank) const { STK_NGP_ThrowAssert(connectedRank < stk::topology::NUM_RANKS); if (connectedRank == stk::topology::NODE_RANK) { const unsigned numNodes = m_nodeConnectivityOffsets(offsetIntoBucket+1)-m_nodeConnectivityOffsets(offsetIntoBucket); @@ -515,9 +525,10 @@ DeviceBucket::get_connected_entities(unsigned offsetIntoBucket, stk::mesh::Entit return m_owningMesh->get_connected_entities(entity_rank(), meshIndex, connectedRank); } +template KOKKOS_INLINE_FUNCTION -DeviceBucket::ConnectedOrdinals -DeviceBucket::get_connected_ordinals(unsigned offsetIntoBucket, stk::mesh::EntityRank connectedRank) const { +typename DeviceBucketT::ConnectedOrdinals +DeviceBucketT::get_connected_ordinals(unsigned offsetIntoBucket, stk::mesh::EntityRank connectedRank) const { STK_NGP_ThrowAssert(connectedRank < stk::topology::NUM_RANKS); if (connectedRank == stk::topology::NODE_RANK) { const unsigned numNodes = m_nodeConnectivityOffsets(offsetIntoBucket+1)-m_nodeConnectivityOffsets(offsetIntoBucket); @@ -527,7 +538,434 @@ DeviceBucket::get_connected_ordinals(unsigned offsetIntoBucket, stk::mesh::Entit stk::mesh::FastMeshIndex meshIndex{bucket_id(), offsetIntoBucket}; return m_owningMesh->get_connected_ordinals(entity_rank(), meshIndex, connectedRank); } +template +void DeviceBucketT::initialize_bucket_attributes(const stk::mesh::Bucket &bucket) +{ + m_bucketId = bucket.bucket_id(); + m_bucketCapacity = bucket.capacity(); + m_bucketSize = bucket.size(); + m_entityRank = bucket.entity_rank(); + m_bucketTopology = bucket.topology(); +} + +template +void DeviceBucketT::initialize_fixed_data_from_host(const stk::mesh::Bucket &bucket) +{ + const stk::mesh::PartVector& parts = bucket.supersets(); + m_partOrdinals = PartOrdinalViewType(Kokkos::view_alloc(Kokkos::WithoutInitializing, "PartOrdinals"), + parts.size()); + auto hostPartOrdinals = HostPartOrdinalViewType(bucket.superset_part_ordinals().first, parts.size()); + Kokkos::deep_copy(m_partOrdinals, hostPartOrdinals); +} + +template +std::pair +DeviceBucketT::scan_entities_for_nodal_connectivity(const stk::mesh::Bucket & bucket) +{ + if (bucket.topology() == stk::topology::INVALID_TOPOLOGY) { + unsigned maxNodesPerEntity = 0; + unsigned totalNumConnectedNodes = 0; + for (unsigned i = 0; i < bucket.size(); ++i) { + maxNodesPerEntity = std::max(maxNodesPerEntity, bucket.num_nodes(i)); + totalNumConnectedNodes += bucket.num_nodes(i); + } + return std::make_pair(maxNodesPerEntity, totalNumConnectedNodes); + } + + return std::make_pair(bucket.topology().num_nodes(), + bucket.topology().num_nodes() * m_bucketCapacity); +} + +template +void DeviceBucketT::resize_device_views(const stk::mesh::Bucket & bucket) +{ + Kokkos::Profiling::pushRegion("resize_device_views()"); + + const auto [maxNodesPerEntity, totalNumConnectedNodes] = scan_entities_for_nodal_connectivity(bucket); + + if (m_nodeOrdinals.size() != maxNodesPerEntity) { + m_nodeOrdinals = OrdinalViewType(Kokkos::view_alloc(Kokkos::WithoutInitializing, "NodeOrdinals"), + static_cast(maxNodesPerEntity)); + OrdinalViewType& nodeOrds = m_nodeOrdinals; //local var to avoid implicit this capture + Kokkos::parallel_for(Kokkos::RangePolicy(0, maxNodesPerEntity), + KOKKOS_LAMBDA(const int i) { + nodeOrds(i) = static_cast(i); + }); + } + + if (m_entities.size() != m_bucketCapacity) { + m_entities = EntityViewType(Kokkos::view_alloc(Kokkos::WithoutInitializing, "BucketEntities"), m_bucketCapacity); + STK_ThrowRequireMsg(m_bucketCapacity > 0, "bucket capacity must be greater than 0"); + } + + if (m_nodeConnectivity.size() != totalNumConnectedNodes) { + m_nodeConnectivity = BucketConnectivityType(Kokkos::view_alloc(Kokkos::WithoutInitializing, + "NodeConnectivity"), totalNumConnectedNodes); + } + + if (m_nodeConnectivityOffsets.size() != m_bucketCapacity+1) { + m_nodeConnectivityOffsets = OrdinalViewType(Kokkos::view_alloc(Kokkos::WithoutInitializing, + "NodeConnectivityOffsets"), m_bucketCapacity+1); + } + Kokkos::Profiling::popRegion(); +} + +template +void DeviceBucketT::update_entity_data_from_host(const stk::mesh::Bucket &bucket) +{ + Kokkos::Profiling::pushRegion("update_entity_data_from_host()"); + + m_bucketSize = bucket.size(); + m_bucketCapacity = bucket.capacity(); + + resize_device_views(bucket); + + Kokkos::Profiling::pushRegion("filling host-side Views"); + auto hostEntities = HostEntityViewType(bucket.begin(), m_bucketCapacity); + auto hostNodeConnectivity = Kokkos::create_mirror_view(Kokkos::WithoutInitializing, m_nodeConnectivity); + auto hostNodeConnectivityOffsets = Kokkos::create_mirror_view(Kokkos::WithoutInitializing, m_nodeConnectivityOffsets); + unsigned nodeOffset = 0; + for (unsigned iEntity = 0; iEntity < bucket.size(); ++iEntity) { + const unsigned nodesPerEntity = bucket.num_nodes(iEntity); + const stk::mesh::Entity * elemNodes = bucket.begin_nodes(iEntity); + for (unsigned iNode = 0; iNode < nodesPerEntity; ++iNode) { + hostNodeConnectivity(nodeOffset + iNode) = elemNodes[iNode]; + } + hostNodeConnectivityOffsets(iEntity) = nodeOffset; + nodeOffset += nodesPerEntity; + } + hostNodeConnectivityOffsets(bucket.size()) = nodeOffset; + Kokkos::Profiling::popRegion(); + + Kokkos::Profiling::pushRegion("deep_copy entities/connectivity/offsets"); + Kokkos::deep_copy(m_entities, hostEntities); + Kokkos::deep_copy(m_nodeConnectivity, hostNodeConnectivity); + Kokkos::deep_copy(m_nodeConnectivityOffsets, hostNodeConnectivityOffsets); + Kokkos::Profiling::popRegion(); + + Kokkos::Profiling::popRegion(); +} + +template +void DeviceMeshT::update_mesh() +{ + if (is_up_to_date()) { + return; + } + + require_ngp_mesh_rank_limit(bulk->mesh_meta_data()); + + Kokkos::Profiling::pushRegion("DeviceMeshT::update_mesh"); + const bool anyChanges = fill_buckets(*bulk); + + if (anyChanges) { + set_entity_keys(*bulk); + copy_entity_keys_to_device(); + set_bucket_entity_offsets(*bulk); + copy_bucket_entity_offsets_to_device(); + fill_sparse_connectivities(*bulk); + copy_sparse_connectivities_to_device(); + copy_volatile_fast_shared_comm_map_to_device(); + fill_mesh_indices(*bulk); + copy_mesh_indices_to_device(); + } + + synchronizedCount = bulk->synchronized_count(); + Kokkos::Profiling::popRegion(); +} + +template +bool DeviceMeshT::fill_buckets(const stk::mesh::BulkData& bulk_in) +{ + bool anyBucketChanges = false; + + Kokkos::Profiling::pushRegion("fill_buckets"); + for (stk::mesh::EntityRank rank = stk::topology::NODE_RANK; rank < endRank; ++rank) { + const stk::mesh::BucketVector& stkBuckets = bulk_in.buckets(rank); + unsigned numStkBuckets = stkBuckets.size(); + + BucketView bucketBuffer(Kokkos::view_alloc(Kokkos::WithoutInitializing, "BucketBuffer"), numStkBuckets); + + if (numStkBuckets != buckets[rank].size()) { + anyBucketChanges = true; + } + + for (unsigned iBucket = 0; iBucket < numStkBuckets; ++iBucket) { + stk::mesh::Bucket& stkBucket = *stkBuckets[iBucket]; + const unsigned ngpBucketId = stkBucket.ngp_bucket_id(); + + if (ngpBucketId == INVALID_BUCKET_ID) { + Kokkos::Profiling::pushRegion("new bucket"); + // New bucket on host + new (&bucketBuffer[iBucket]) DeviceBucketT(); + bucketBuffer[iBucket].initialize_bucket_attributes(stkBucket); + bucketBuffer[iBucket].initialize_fixed_data_from_host(stkBucket); + bucketBuffer[iBucket].update_entity_data_from_host(stkBucket); + anyBucketChanges = true; + Kokkos::Profiling::popRegion(); + } + else { + Kokkos::Profiling::pushRegion("pre-existing bucket"); + // Pre-existing bucket on host + new (&bucketBuffer[iBucket]) DeviceBucketT(buckets[rank][ngpBucketId]); + if (stkBucket.is_modified()) { + bucketBuffer[iBucket].update_entity_data_from_host(stkBucket); + anyBucketChanges = true; + } + bucketBuffer[iBucket].m_bucketId = stkBucket.bucket_id(); + Kokkos::Profiling::popRegion(); + } + + stkBucket.set_ngp_bucket_id(iBucket); + } + + if (is_last_bucket_reference(rank)) { + for (unsigned iBucket = 0; iBucket < buckets[rank].size(); ++iBucket) { + buckets[rank][iBucket].~DeviceBucketT(); + } + } + + buckets[rank] = bucketBuffer; + } + Kokkos::Profiling::popRegion(); + + return anyBucketChanges; +} + +constexpr double RESIZE_FACTOR = 0.05; + +template +inline void reallocate_views(DEVICE_VIEW & deviceView, HOST_VIEW & hostView, size_t requiredSize, double resizeFactor = 0.0) +{ + const size_t currentSize = deviceView.extent(0); + const size_t shrinkThreshold = currentSize - static_cast(2*resizeFactor*currentSize); + const bool needGrowth = (requiredSize > currentSize); + const bool needShrink = (requiredSize < shrinkThreshold); + + if (needGrowth || needShrink) { + const size_t newSize = requiredSize + static_cast(resizeFactor*requiredSize); + deviceView = DEVICE_VIEW(Kokkos::view_alloc(Kokkos::WithoutInitializing, deviceView.label()), newSize); + hostView = Kokkos::create_mirror_view(Kokkos::WithoutInitializing, deviceView); + } +} + +template +void DeviceMeshT::set_entity_keys(const stk::mesh::BulkData& bulk_in) +{ + unsigned totalNumEntityKeys = bulk_in.get_size_of_entity_index_space(); + auto& hostEntityKeys = deviceMeshHostData->hostEntityKeys; + + reallocate_views(entityKeys, hostEntityKeys, totalNumEntityKeys, RESIZE_FACTOR); + + for (stk::mesh::EntityRank rank = stk::topology::NODE_RANK; rank < endRank; ++rank) { + const stk::mesh::BucketVector& stkBuckets = bulk_in.buckets(rank); + for (unsigned i = 0; i < stkBuckets.size(); ++i) { + const stk::mesh::Bucket & bucket = *stkBuckets[i]; + for (unsigned j = 0; j < bucket.size(); ++j) { + stk::mesh::Entity entity = bucket[j]; + hostEntityKeys[entity.local_offset()] = bulk_in.entity_key(entity); + } + } + } +} +template +void DeviceMeshT::set_bucket_entity_offsets(const stk::mesh::BulkData& bulk_in) +{ + auto& hostBucketEntityOffsets = deviceMeshHostData->hostBucketEntityOffsets; + + for(stk::mesh::EntityRank rank=stk::topology::NODE_RANK; ranksize(); + } + for (unsigned i = stkBuckets.size(); i < hostBucketEntityOffsets[rank].extent(0); ++i) { + hostBucketEntityOffsets[rank](i) = bucketOffsetIntoEntities; + } + } +} + +template +void DeviceMeshT::fill_sparse_connectivities(const stk::mesh::BulkData& bulk_in) +{ + auto& hostEntityConnectivityOffset = deviceMeshHostData->hostEntityConnectivityOffset; + auto& hostBucketEntityOffsets = deviceMeshHostData->hostBucketEntityOffsets; + auto& hostSparseConnectivity = deviceMeshHostData->hostSparseConnectivity; + auto& hostSparseConnectivityOrdinals = deviceMeshHostData->hostSparseConnectivityOrdinals; + auto& hostSparsePermutations = deviceMeshHostData->hostSparsePermutations; + + unsigned totalNumConnectedEntities[stk::topology::NUM_RANKS][stk::topology::NUM_RANKS] = {{0}, {0}, {0}, {0}, {0}}; + unsigned totalNumPermutations[stk::topology::NUM_RANKS][stk::topology::NUM_RANKS] = {{0}, {0}, {0}, {0}, {0}}; + + for(stk::mesh::EntityRank rank=stk::topology::NODE_RANK; rank 0) { + + const stk::mesh::Entity* connectedEntities = stkBucket.begin(iEntity, connectedRank); + const stk::mesh::ConnectivityOrdinal* connectedOrdinals = stkBucket.begin_ordinals(iEntity, connectedRank); + const stk::mesh::Permutation* permutations = hasPermutation ? stkBucket.begin_permutations(iEntity, connectedRank) : nullptr; + for(unsigned i=0; i +void DeviceMeshT::fill_mesh_indices(const stk::mesh::BulkData& bulk_in) +{ + const size_t indexSpaceSize = bulk->get_size_of_entity_index_space(); + hostMeshIndices = HostMeshIndexType(Kokkos::view_alloc(Kokkos::WithoutInitializing, "host_mesh_indices"), indexSpaceSize); + + for (stk::mesh::EntityRank rank=stk::topology::NODE_RANK; rank +void DeviceMeshT::copy_entity_keys_to_device() +{ + auto& hostEntityKeys = deviceMeshHostData->hostEntityKeys; + + Kokkos::deep_copy(entityKeys, hostEntityKeys); +} + +template +void DeviceMeshT::copy_mesh_indices_to_device() +{ + unsigned length = hostMeshIndices.size(); + Kokkos::View nonconst_device_mesh_indices(Kokkos::view_alloc(Kokkos::WithoutInitializing, "tmp_dev_mesh_indices"), length); + Kokkos::deep_copy(nonconst_device_mesh_indices, hostMeshIndices); + deviceMeshIndices = nonconst_device_mesh_indices; +} + +template +void DeviceMeshT::copy_bucket_entity_offsets_to_device() +{ + auto& hostBucketEntityOffsets = deviceMeshHostData->hostBucketEntityOffsets; + + for(stk::mesh::EntityRank rank=stk::topology::NODE_RANK; rank +void DeviceMeshT::copy_sparse_connectivities_to_device() +{ + auto& hostEntityConnectivityOffset = deviceMeshHostData->hostEntityConnectivityOffset; + auto& hostSparseConnectivity = deviceMeshHostData->hostSparseConnectivity; + auto& hostSparseConnectivityOrdinals = deviceMeshHostData->hostSparseConnectivityOrdinals; + auto& hostSparsePermutations = deviceMeshHostData->hostSparsePermutations; + + for(stk::mesh::EntityRank rank=stk::topology::NODE_RANK; rank +void DeviceMeshT::copy_volatile_fast_shared_comm_map_to_device() +{ + bulk->volatile_fast_shared_comm_map(stk::topology::NODE_RANK, 0); + auto& hostVolatileFastSharedCommMapOffset = deviceMeshHostData->hostVolatileFastSharedCommMapOffset; + auto& hostVolatileFastSharedCommMap = deviceMeshHostData->hostVolatileFastSharedCommMap; + + for (stk::mesh::EntityRank rank = stk::topology::NODE_RANK; rank < stk::topology::ELEM_RANK; ++rank) + { + Kokkos::resize(Kokkos::WithoutInitializing, volatileFastSharedCommMapOffset[rank], hostVolatileFastSharedCommMapOffset[rank].extent(0)); + Kokkos::resize(Kokkos::WithoutInitializing, volatileFastSharedCommMap[rank], hostVolatileFastSharedCommMap[rank].extent(0)); + Kokkos::deep_copy(volatileFastSharedCommMapOffset[rank], hostVolatileFastSharedCommMapOffset[rank]); + Kokkos::deep_copy(volatileFastSharedCommMap[rank], hostVolatileFastSharedCommMap[rank]); + } +} } } diff --git a/packages/stk/stk_mesh/stk_mesh/base/FieldParallel.cpp b/packages/stk/stk_mesh/stk_mesh/base/FieldParallel.cpp index 9ae1c34d5598..b9254509fe57 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/FieldParallel.cpp +++ b/packages/stk/stk_mesh/stk_mesh/base/FieldParallel.cpp @@ -429,7 +429,7 @@ void parallel_op_impl(const BulkData& mesh, std::vector fields "Please don't mix fields with different primitive types in the same parallel assemble operation"); f.sync_to_host(); - HostCommMapIndices commMapIndices = mesh.volatile_fast_shared_comm_map(f.entity_rank(), proc); + HostCommMapIndices commMapIndices = mesh.volatile_fast_shared_comm_map(f.entity_rank(), proc); for(size_t i=0; i fields for (size_t j = 0 ; j < fields.size() ; ++j ) { const FieldBase& f = *fields[j]; - HostCommMapIndices commMapIndices = mesh.volatile_fast_shared_comm_map(f.entity_rank(),proc); + HostCommMapIndices commMapIndices = mesh.volatile_fast_shared_comm_map(f.entity_rank(),proc); for(size_t i=0; i fields unsigned recv_offset = 0; for (size_t j = 0 ; j < fields.size() ; ++j ) { const FieldBase& f = *fields[j] ; - HostCommMapIndices commMapIndices = mesh.volatile_fast_shared_comm_map(f.entity_rank(), iproc); + HostCommMapIndices commMapIndices = mesh.volatile_fast_shared_comm_map(f.entity_rank(), iproc); f.sync_to_host(); f.modify_on_host(); diff --git a/packages/stk/stk_mesh/stk_mesh/base/GetNgpMesh.hpp b/packages/stk/stk_mesh/stk_mesh/base/GetNgpMesh.hpp index 9c7ab6d86afe..7fd0de0df44b 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/GetNgpMesh.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/GetNgpMesh.hpp @@ -41,18 +41,24 @@ namespace stk { namespace mesh { -inline NgpMesh & get_updated_ngp_mesh(const BulkData & bulk) +template +inline NgpMeshT & get_updated_ngp_mesh(const BulkData & bulk) { NgpMeshBase * ngpMeshBase = impl::get_ngp_mesh(bulk); if (ngpMeshBase == nullptr) { - ngpMeshBase = new NgpMesh(bulk); + ngpMeshBase = new NgpMeshT(bulk); impl::set_ngp_mesh(bulk, ngpMeshBase); } else { ngpMeshBase->update_mesh(); } - return dynamic_cast(*ngpMeshBase); + return dynamic_cast&>(*ngpMeshBase); +} + +inline NgpMesh & get_updated_ngp_mesh(const BulkData & bulk) +{ + return get_updated_ngp_mesh(bulk); } }} diff --git a/packages/stk/stk_mesh/stk_mesh/base/HostField.hpp b/packages/stk/stk_mesh/stk_mesh/base/HostField.hpp index 8a0cde9ba484..fe70d29c9009 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/HostField.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/HostField.hpp @@ -194,7 +194,9 @@ class HostField : public NgpFieldBase void sync_to_host() override { sync_to_host(Kokkos::DefaultExecutionSpace()); - Kokkos::fence(); + if constexpr (!std::is_same_v) { + Kokkos::fence(); + } } void sync_to_host(const ExecSpace& execSpace) override diff --git a/packages/stk/stk_mesh/stk_mesh/base/HostMesh.hpp b/packages/stk/stk_mesh/stk_mesh/base/HostMesh.hpp index bf4dc9bcffa8..93109961ed67 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/HostMesh.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/HostMesh.hpp @@ -56,10 +56,15 @@ namespace stk { namespace mesh { -class HostMesh : public NgpMeshBase +template +class HostMeshT : public NgpMeshBase { public: - using MeshExecSpace = stk::ngp::HostExecSpace; + typedef NgpMemSpace ngp_mem_space; + + static_assert(Kokkos::SpaceAccessibility::accessible); + static_assert(Kokkos::is_memory_space_v); + using MeshExecSpace = typename NgpMemSpace::execution_space; using MeshIndex = FastMeshIndex; using BucketType = stk::mesh::Bucket; using ConnectedNodes = util::StridedArray; @@ -67,14 +72,14 @@ class HostMesh : public NgpMeshBase using ConnectedOrdinals = util::StridedArray; using Permutations = util::StridedArray; - HostMesh() + HostMeshT() : NgpMeshBase(), bulk(nullptr) { } - HostMesh(const stk::mesh::BulkData& b) + HostMeshT(const stk::mesh::BulkData& b) : NgpMeshBase(), bulk(&b), m_syncCountWhenUpdated(bulk->synchronized_count()) @@ -82,12 +87,12 @@ class HostMesh : public NgpMeshBase require_ngp_mesh_rank_limit(bulk->mesh_meta_data()); } - virtual ~HostMesh() override = default; + virtual ~HostMeshT() override = default; - HostMesh(const HostMesh &) = default; - HostMesh(HostMesh &&) = default; - HostMesh& operator=(const HostMesh&) = default; - HostMesh& operator=(HostMesh&&) = default; + HostMeshT(const HostMeshT &) = default; + HostMeshT(HostMeshT &&) = default; + HostMeshT& operator=(const HostMeshT&) = default; + HostMeshT& operator=(HostMeshT&&) = default; void update_mesh() override { @@ -229,9 +234,9 @@ class HostMesh : public NgpMeshBase return *bulk->buckets(rank)[i]; } - HostCommMapIndices volatile_fast_shared_comm_map(stk::topology::rank_t rank, int proc) const + NgpCommMapIndicesHostMirrorT volatile_fast_shared_comm_map(stk::topology::rank_t rank, int proc) const { - return bulk->volatile_fast_shared_comm_map(rank, proc); + return bulk->volatile_fast_shared_comm_map(rank, proc); } const stk::mesh::BulkData &get_bulk_on_host() const @@ -249,6 +254,8 @@ class HostMesh : public NgpMeshBase size_t m_syncCountWhenUpdated; }; +using HostMesh = HostMeshT; + } } diff --git a/packages/stk/stk_mesh/stk_mesh/base/Ngp.hpp b/packages/stk/stk_mesh/stk_mesh/base/Ngp.hpp index ae17f7fcc395..063f2a2616cd 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/Ngp.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/Ngp.hpp @@ -36,6 +36,7 @@ #include "Kokkos_Core.hpp" #include "stk_util/stk_kokkos_macros.h" +#include #if defined(STK_DEBUG_FIELD_SYNC) && !defined(STK_USE_DEVICE_MESH) static_assert(false, "The STK field sync debugger does nothing unless you also have enabled the DeviceMesh/DeviceField." @@ -45,8 +46,8 @@ static_assert(false, "The STK field sync debugger does nothing unless you also h namespace stk { namespace mesh { -class HostMesh; -class DeviceMesh; +template class HostMeshT; +template class DeviceMeshT; class StkFieldSyncDebugger; class EmptyStkFieldSyncDebugger; @@ -65,11 +66,17 @@ template class NgpDebugger = DefaultNgpFieldSync template class NgpDebugger = DefaultNgpFieldSyncDebugger> class DeviceField; #ifdef STK_USE_DEVICE_MESH - using NgpMesh = stk::mesh::DeviceMesh; + using NgpMeshDefaultMemSpace = stk::ngp::MemSpace; + template + using NgpMeshT = stk::mesh::DeviceMeshT; + using NgpMesh = NgpMeshT; template class NgpDebugger = DefaultNgpFieldSyncDebugger> using NgpField = stk::mesh::DeviceField; #else - using NgpMesh = stk::mesh::HostMesh; + using NgpMeshDefaultMemSpace = typename stk::ngp::HostExecSpace::memory_space; + template + using NgpMeshT = stk::mesh::HostMeshT; + using NgpMesh = NgpMeshT; template class NgpDebugger = DefaultNgpFieldSyncDebugger> using NgpField = stk::mesh::HostField; #endif diff --git a/packages/stk/stk_mesh/stk_mesh/base/NgpFieldBLAS.hpp b/packages/stk/stk_mesh/stk_mesh/base/NgpFieldBLAS.hpp index 3d0d0036581d..bd513ae79246 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/NgpFieldBLAS.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/NgpFieldBLAS.hpp @@ -126,6 +126,24 @@ void field_fill(const Scalar alpha, ngp_field_blas::impl::field_fill_impl(alpha, fields.data(), fields.size(), -1, &selector, execSpace, isDeviceExecSpaceUserOverride); } +template +inline void field_amax(Scalar& amaxOut, + const FieldBase& xField, + const EXEC_SPACE& execSpace, + bool isDeviceExecSpaceUserOverride = (!std::is_same_v) ) +{ + ngp_field_blas::impl::field_amax_impl(amaxOut, xField, nullptr, execSpace, isDeviceExecSpaceUserOverride); +} + +template +inline void field_amax(Scalar& amaxOut, + const FieldBase& xField, + const Selector& selector, + const EXEC_SPACE& execSpace, + bool isDeviceExecSpaceUserOverride = (!std::is_same_v) ) +{ + ngp_field_blas::impl::field_amax_impl(amaxOut, xField, &selector, execSpace, isDeviceExecSpaceUserOverride); +} template inline diff --git a/packages/stk/stk_mesh/stk_mesh/base/NgpFieldParallel.hpp b/packages/stk/stk_mesh/stk_mesh/base/NgpFieldParallel.hpp index 4f94c27279ba..a0b4128d299d 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/NgpFieldParallel.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/NgpFieldParallel.hpp @@ -187,7 +187,7 @@ class ParallelSumDataExchangeSymPackUnpackHandler for (stk::mesh::NgpField* field : m_ngpFields) { stk::mesh::FieldBase* stkField = m_ngpMesh.get_bulk_on_host().mesh_meta_data().get_fields()[field->get_ordinal()]; - stk::mesh::HostCommMapIndices commMapIndices = m_ngpMesh.get_bulk_on_host().volatile_fast_shared_comm_map(field->get_rank(), proc); + stk::mesh::HostCommMapIndices commMapIndices = m_ngpMesh.get_bulk_on_host().volatile_fast_shared_comm_map(field->get_rank(), proc); for (size_t i = 0; i < commMapIndices.extent(0); ++i) { const unsigned bucketId = commMapIndices(i).bucket_id; const unsigned numScalarsPerEntity = stk::mesh::field_scalars_per_entity(*stkField, bucketId); diff --git a/packages/stk/stk_mesh/stk_mesh/base/NgpReductions.hpp b/packages/stk/stk_mesh/stk_mesh/base/NgpReductions.hpp index 04822016e9cd..d294334c6fff 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/NgpReductions.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/NgpReductions.hpp @@ -132,7 +132,7 @@ struct ThreadReductionFunctor const AlgorithmPerEntity &functor; }; -template +template struct TeamReductionFunctor { using ReductionOp = ReductionOpT; @@ -141,7 +141,7 @@ struct TeamReductionFunctor TeamReductionFunctor(const Mesh m, const stk::mesh::EntityRank r, stk::NgpVector b, ReductionOp & red, const AlgorithmPerEntity& f) : mesh(m), rank(r), bucketIds(b), reduction(red), functor(f) {} - using TeamHandleType = typename stk::ngp::TeamPolicy::member_type; + using TeamHandleType = typename stk::ngp::TeamPolicy::member_type; KOKKOS_FUNCTION void operator()(const TeamHandleType& team, value_type& team_reduction) const @@ -176,10 +176,23 @@ void for_each_entity_reduce(Mesh& mesh, { stk::NgpVector bucketIds = mesh.get_bucket_ids(rank, selector); const unsigned numBuckets = bucketIds.size(); - TeamReductionFunctor teamFunctor(mesh, rank, bucketIds, reduction, functor); + TeamReductionFunctor teamFunctor(mesh, rank, bucketIds, reduction, functor); Kokkos::parallel_reduce(stk::ngp::TeamPolicy(numBuckets, Kokkos::AUTO), teamFunctor, reduction); } +template +void for_each_entity_reduce(Mesh& mesh, + stk::topology::rank_t rank, + const stk::mesh::Selector& selector, + ReductionOp& reduction, + const AlgorithmPerEntity& functor) +{ + stk::NgpVector bucketIds = mesh.get_bucket_ids(rank, selector); + const unsigned numBuckets = bucketIds.size(); + TeamReductionFunctor teamFunctor(mesh, rank, bucketIds, reduction, functor); + Kokkos::parallel_reduce(stk::ngp::TeamPolicy(numBuckets, Kokkos::AUTO), teamFunctor, reduction); +} + template struct FieldThreadReductionFunctor { diff --git a/packages/stk/stk_mesh/stk_mesh/base/NgpTypes.hpp b/packages/stk/stk_mesh/stk_mesh/base/NgpTypes.hpp index 726dbb1b277f..0a128c4f29e4 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/NgpTypes.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/NgpTypes.hpp @@ -44,21 +44,36 @@ namespace mesh { using DeviceCommMapIndices = Kokkos::View; using HostCommMapIndices = DeviceCommMapIndices::HostMirror; +using HostCommMapIndicesMemSpace = HostCommMapIndices::traits::memory_space; +template using NgpCommMapIndicesT = Kokkos::View; +template using NgpCommMapIndicesHostMirrorT = typename NgpCommMapIndicesT::HostMirror; + using EntityKeyViewType = Kokkos::View; using EntityViewType = Kokkos::View; using HostEntityViewType = Kokkos::View>; + +template using EntityKeyViewTypeT = Kokkos::View; +template using EntityViewTypeT = Kokkos::View; + + using BucketConnectivityType = Kokkos::View; using UnsignedViewType = Kokkos::View; +template using UnsignedViewTypeT = Kokkos::View; using Unsigned2dViewType = Kokkos::View; using BoolViewType = Kokkos::View; using OrdinalViewType = Kokkos::View; +template using OrdinalViewTypeT = Kokkos::View; using PartOrdinalViewType = Kokkos::View; using HostPartOrdinalViewType = Kokkos::View>; using PermutationViewType = Kokkos::View; +template using PermutationViewTypeT = Kokkos::View; using FastSharedCommMapViewType = DeviceCommMapIndices; using HostMeshIndexType = Kokkos::View::HostMirror; using MeshIndexType = Kokkos::View>; + + using BucketEntityOffsetsViewType = Kokkos::View; +template using BucketEntityOffsetsViewTypeT = Kokkos::View; template using FieldDataDeviceViewType = Kokkos::View; template using FieldDataHostViewType = Kokkos::View; diff --git a/packages/stk/stk_mesh/stk_mesh/baseImpl/CommEntityMods.cpp b/packages/stk/stk_mesh/stk_mesh/baseImpl/CommEntityMods.cpp index 22b5552c2a9e..26d8b5887f12 100644 --- a/packages/stk/stk_mesh/stk_mesh/baseImpl/CommEntityMods.cpp +++ b/packages/stk/stk_mesh/stk_mesh/baseImpl/CommEntityMods.cpp @@ -171,13 +171,16 @@ void CommEntityMods::unpack() .unpack( remote_owned_closure_int); remote_owned_closure = ((remote_owned_closure_int==1)?true:false); - EntityCommListInfo info = find_entity(m_bulkData, m_commList, key); - if (ghostId == BulkData::SHARED) { - m_sharedMods.emplace_back(EntityParallelState{procNumber, state, info, remote_owned_closure}); - } - else { - int remoteProc = (procNumber == m_bulkData.parallel_rank()) ? m_bulkData.parallel_owner_rank(info.entity) : procNumber; - m_ghostedMods.emplace_back(EntityParallelState{remoteProc, state, info, remote_owned_closure}); + EntityCommListInfoVector::const_iterator iter = std::lower_bound(m_commList.begin(), m_commList.end(), key); + if (iter != m_commList.end() && iter->key == key) { + EntityCommListInfo info = *iter; + if (ghostId == BulkData::SHARED) { + m_sharedMods.emplace_back(EntityParallelState{procNumber, state, info, remote_owned_closure}); + } + else { + int remoteProc = (procNumber == m_bulkData.parallel_rank()) ? m_bulkData.parallel_owner_rank(info.entity) : procNumber; + m_ghostedMods.emplace_back(EntityParallelState{remoteProc, state, info, remote_owned_closure}); + } } } } diff --git a/packages/stk/stk_mesh/stk_mesh/baseImpl/EntityKeyMapping.cpp b/packages/stk/stk_mesh/stk_mesh/baseImpl/EntityKeyMapping.cpp index f510717d7ea9..6bd313f4da55 100644 --- a/packages/stk/stk_mesh/stk_mesh/baseImpl/EntityKeyMapping.cpp +++ b/packages/stk/stk_mesh/stk_mesh/baseImpl/EntityKeyMapping.cpp @@ -98,6 +98,8 @@ void EntityKeyMapping::clear_all_cache() void EntityKeyMapping::clear_destroyed_entity_cache(EntityRank rank) const { + STK_ThrowAssertMsg(static_cast(rank) < m_destroy_cache.size(), "clear_destroyed_entity_cache rank="< 0 ? x : -x; } + + Scalar get_amax_val() const + { + auto resultHost = Kokkos::create_mirror_view(resultDevice); + Kokkos::deep_copy(resultHost, resultDevice); + return resultHost(0); + } + + KOKKOS_FUNCTION + void operator()(const stk::mesh::FastMeshIndex& entityIndex) const + { + const unsigned numComponents = ngpX.get_num_components_per_entity(entityIndex); + for (unsigned d = 0; d < numComponents; ++d) { + Scalar fieldVal = ngpX(entityIndex, d); + Scalar absFieldVal = abs(fieldVal); + Kokkos::atomic_max(&resultDevice(0), absFieldVal); + } + } + + NGP_FIELD_TYPE ngpX; + Kokkos::View resultDevice; +}; + +template +Scalar field_amax_no_mark_t( + const stk::mesh::FieldBase& xField, const stk::mesh::Selector& selector, const EXEC_SPACE& execSpace) +{ + if constexpr (operate_on_ngp_mesh()) { + xField.sync_to_device(); + stk::mesh::NgpField& ngpX = stk::mesh::get_updated_ngp_field(xField); + auto ngpMesh = stk::mesh::get_updated_ngp_mesh(xField.get_mesh()); + FieldAMax> fieldAMax(ngpX); + stk::mesh::for_each_entity_run(ngpMesh, xField.entity_rank(), selector, fieldAMax); + + Scalar localAmax = fieldAMax.get_amax_val(); + Scalar globalAmax = localAmax; + auto comm = xField.get_mesh().parallel(); + stk::all_reduce_max(comm, &localAmax, &globalAmax, 1u); + return globalAmax; + } else { + xField.sync_to_host(); + double amaxOut{0.0}; + stk::mesh::field_amax(amaxOut, xField, selector); + return amaxOut; + } +} + +template +void field_amax_no_mark_mod(Scalar& amaxOut, + const stk::mesh::FieldBase& xField, + const stk::mesh::Selector& selector, + const EXEC_SPACE& execSpace) +{ + const stk::mesh::DataTraits& dataTraits = xField.data_traits(); + + if (dataTraits.type_info == typeid(double)) { + amaxOut = field_amax_no_mark_t(xField, selector, execSpace); + } else if (dataTraits.type_info == typeid(float)) { + amaxOut = field_amax_no_mark_t(xField, selector, execSpace); + } else if (dataTraits.type_info == typeid(int)) { + amaxOut = field_amax_no_mark_t(xField, selector, execSpace); + } else if (dataTraits.type_info == typeid(unsigned)) { + amaxOut = field_amax_no_mark_t(xField, selector, execSpace); + } else { + STK_ThrowErrorMsg("field_amax doesn't yet support fields of type " << dataTraits.type_info.name()); + } +} + +template +void field_amax_impl(Scalar& amaxOut, + const stk::mesh::FieldBase& xField, + const stk::mesh::Selector* selectorPtr, + const EXEC_SPACE& execSpace, + bool isDeviceExecSpaceUserOverride) +{ + std::unique_ptr fieldSelector; + if (selectorPtr == nullptr) { + fieldSelector = std::make_unique(stk::mesh::Selector(xField)); + } + const stk::mesh::Selector& selector = selectorPtr != nullptr ? *selectorPtr : *(fieldSelector.get()); + + field_amax_no_mark_mod(amaxOut, xField, selector, execSpace); +} + template class FieldCopy { public: @@ -577,27 +670,25 @@ inline void field_axpbyz_impl(const stk::mesh::BulkData& mesh, STK_ThrowRequireMsg(dataTraits == yField.data_traits(), "xField and yField must have same datatype"); STK_ThrowRequireMsg(dataTraits == zField.data_traits(), "xField and zField must have same datatype"); - stk::mesh::Selector fieldSelector; + std::unique_ptr fieldSelector; if (selectorPtr == nullptr) { - fieldSelector = stk::mesh::Selector(xField) & stk::mesh::Selector(yField); - } else - { - fieldSelector = *selectorPtr; + fieldSelector = std::make_unique(stk::mesh::Selector(xField) & stk::mesh::Selector(yField)); } + const stk::mesh::Selector& selector = selectorPtr != nullptr ? *selectorPtr : *(fieldSelector.get()); if constexpr (ngp_field_blas::impl::operate_on_ngp_mesh()) { if (dataTraits.type_info == typeid(double)) { ngp_field_blas::impl::apply_functor_on_field>( - mesh, zField, xField, yField, alpha, beta, fieldSelector); + mesh, zField, xField, yField, alpha, beta, selector); } else if (dataTraits.type_info == typeid(float)) { ngp_field_blas::impl::apply_functor_on_field>( - mesh, zField, xField, yField, alpha, beta, fieldSelector); + mesh, zField, xField, yField, alpha, beta, selector); } else if (dataTraits.type_info == typeid(int)) { ngp_field_blas::impl::apply_functor_on_field>( - mesh, zField, xField, yField, alpha, beta, fieldSelector); + mesh, zField, xField, yField, alpha, beta, selector); } else if (dataTraits.type_info == typeid(unsigned)) { ngp_field_blas::impl::apply_functor_on_field>( - mesh, zField, xField, yField, alpha, beta, fieldSelector); + mesh, zField, xField, yField, alpha, beta, selector); } else { STK_ThrowErrorMsg("axpbyz doesn't yet support fields of type "< +struct NgpMeshHostData : NgpMeshHostDataBase { - EntityKeyViewType::HostMirror hostEntityKeys; - BucketEntityOffsetsViewType::HostMirror hostBucketEntityOffsets[stk::topology::NUM_RANKS]; - UnsignedViewType::HostMirror hostEntityConnectivityOffset[stk::topology::NUM_RANKS][stk::topology::NUM_RANKS]; - EntityViewType::HostMirror hostSparseConnectivity[stk::topology::NUM_RANKS][stk::topology::NUM_RANKS]; - OrdinalViewType::HostMirror hostSparseConnectivityOrdinals[stk::topology::NUM_RANKS][stk::topology::NUM_RANKS]; - PermutationViewType::HostMirror hostSparsePermutations[stk::topology::NUM_RANKS][stk::topology::NUM_RANKS]; - UnsignedViewType::HostMirror hostVolatileFastSharedCommMapOffset[stk::topology::NUM_RANKS]; - FastSharedCommMapViewType::HostMirror hostVolatileFastSharedCommMap[stk::topology::NUM_RANKS]; + typename EntityKeyViewTypeT::HostMirror hostEntityKeys; + typename BucketEntityOffsetsViewTypeT::HostMirror hostBucketEntityOffsets[stk::topology::NUM_RANKS]; + typename UnsignedViewTypeT::HostMirror hostEntityConnectivityOffset[stk::topology::NUM_RANKS][stk::topology::NUM_RANKS]; + typename EntityViewTypeT::HostMirror hostSparseConnectivity[stk::topology::NUM_RANKS][stk::topology::NUM_RANKS]; + typename OrdinalViewTypeT::HostMirror hostSparseConnectivityOrdinals[stk::topology::NUM_RANKS][stk::topology::NUM_RANKS]; + typename PermutationViewTypeT::HostMirror hostSparsePermutations[stk::topology::NUM_RANKS][stk::topology::NUM_RANKS]; + typename UnsignedViewTypeT::HostMirror hostVolatileFastSharedCommMapOffset[stk::topology::NUM_RANKS]; + typename NgpCommMapIndicesT::HostMirror hostVolatileFastSharedCommMap[stk::topology::NUM_RANKS]; unsigned volatileFastSharedCommMapSyncCount = 0; }; diff --git a/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/BulkDataIdMapper.hpp b/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/BulkDataIdMapper.hpp index 992efb94fb12..5bb5ae6d2157 100644 --- a/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/BulkDataIdMapper.hpp +++ b/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/BulkDataIdMapper.hpp @@ -68,11 +68,11 @@ class LocalIdMapperT set_local_ids(bulk, rank, sel & bulk.mesh_meta_data().locally_owned_part()); } - const LocalIDType INVALID_LOCAL_ID = std::numeric_limits::max(); + static constexpr LocalIDType INVALID_LOCAL_ID_TYPE = std::numeric_limits::max(); void set_size(const stk::mesh::BulkData &bulk) { - entityToLocalId.resize(bulk.get_size_of_entity_index_space(), INVALID_LOCAL_ID); + entityToLocalId.resize(bulk.get_size_of_entity_index_space(), INVALID_LOCAL_ID_TYPE); } void clear() @@ -82,7 +82,7 @@ class LocalIdMapperT void set_local_ids(const stk::mesh::BulkData &bulk, stk::mesh::EntityRank rank, const stk::mesh::Selector& selector) { - entityToLocalId.resize(bulk.get_size_of_entity_index_space(), INVALID_LOCAL_ID); + entityToLocalId.resize(bulk.get_size_of_entity_index_space(), INVALID_LOCAL_ID_TYPE); if(bulk.mesh_meta_data().entity_rank_count() >= rank) { stk::mesh::EntityVector entities; @@ -97,14 +97,12 @@ class LocalIdMapperT bool does_entity_have_local_id(stk::mesh::Entity entity) const { - return (entity.local_offset() < entityToLocalId.size() && entityToLocalId[entity.local_offset()] != INVALID_LOCAL_ID); + return (entity.local_offset() < entityToLocalId.size() && entityToLocalId[entity.local_offset()] != INVALID_LOCAL_ID_TYPE); } LocalIDType entity_to_local(stk::mesh::Entity entity) const { - STK_ThrowAssert(entityToLocalId.size() > entity.local_offset()); - - return entityToLocalId[entity.local_offset()]; + return (entityToLocalId.size() > entity.local_offset()) ? entityToLocalId[entity.local_offset()] : INVALID_LOCAL_ID_TYPE; } void make_space_for_new_elements(const stk::mesh::EntityVector & elements) @@ -115,7 +113,7 @@ class LocalIdMapperT maxEntity.set_local_offset(std::max(maxEntity.local_offset(), elem.local_offset())); if(maxEntity.local_offset() >= entityToLocalId.size()) - entityToLocalId.resize(maxEntity.local_offset() + 1, INVALID_LOCAL_ID); + entityToLocalId.resize(maxEntity.local_offset() + 1, INVALID_LOCAL_ID_TYPE); } void create_local_ids_for_elements(const stk::mesh::EntityVector & elements) @@ -132,7 +130,7 @@ class LocalIdMapperT void clear_local_id_for_elem(stk::mesh::Entity elem) { - entityToLocalId[elem.local_offset()] = INVALID_LOCAL_ID; + entityToLocalId[elem.local_offset()] = INVALID_LOCAL_ID_TYPE; } private: std::vector entityToLocalId; diff --git a/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/ElemElemGraph.cpp b/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/ElemElemGraph.cpp index bd0288d318d6..a78071162af0 100644 --- a/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/ElemElemGraph.cpp +++ b/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/ElemElemGraph.cpp @@ -1099,6 +1099,253 @@ void ElemElemGraph::delete_elements(const stk::mesh::impl::DeletedElementInfoVec m_modCycleWhenGraphModified = m_bulk_data.synchronized_count(); } +void ElemElemGraph::pack_remote_edges_to_send(stk::CommSparse& comm, + bool sendElem1Side1Nodes, + const std::vector& edgesToSend, + bool deletePllInfo) +{ + stk::mesh::EntityVector sideNodes; + impl::ParallelGraphInfo& pllInfo = m_parallelInfoForGraphEdges.get_parallel_graph_info(); + + for(const GraphEdge& graphEdge: edgesToSend) { + STK_ThrowRequireMsg(graphEdge.elem2() < 0, + "pack_remote_edges_to_send: remote edge should have negative elem2 Id."); + + const bool throwIfNotFound = false; + const impl::ParallelGraphInfo::const_iterator& pllInfo_iter = m_parallelInfoForGraphEdges.get_parallel_info_iterator_for_graph_edge(graphEdge, throwIfNotFound); + const bool foundIt = pllInfo_iter != pllInfo.end() && graphEdge == pllInfo_iter->first; + if (!foundIt) { + continue; + } + + const int otherProc = pllInfo_iter->second.get_proc_rank_of_neighbor(); + Entity elem1Entity = get_entity(graphEdge.elem1()); + comm.send_buffer(otherProc).pack(m_bulk_data.identifier(elem1Entity)); + comm.send_buffer(otherProc).pack(graphEdge.side1()); + + if (sendElem1Side1Nodes) { + stk::topology elem1Topo = m_bulk_data.bucket(elem1Entity).topology(); + stk::topology elem1SideTopo = elem1Topo.side_topology(graphEdge.side1()); + comm.send_buffer(otherProc).pack(elem1SideTopo.num_nodes()); + const stk::mesh::Entity* elem1Nodes = m_bulk_data.begin(elem1Entity,stk::topology::NODE_RANK); + sideNodes.resize(elem1SideTopo.num_nodes()); + impl::fill_element_side_nodes_from_topology(elem1Topo, elem1Nodes, graphEdge.side1(), sideNodes); + for(unsigned i=0; i(m_bulk_data.identifier(sideNodes[i])); + } + } + + comm.send_buffer(otherProc).pack(m_parallelInfoForGraphEdges.convert_negative_local_id_to_remote_global_id(graphEdge.elem2())); + comm.send_buffer(otherProc).pack(graphEdge.side2()); + + if (deletePllInfo) { + m_parallelInfoForGraphEdges.erase_parallel_info_for_graph_edge(graphEdge); + } + } +} + +void ElemElemGraph::unpack_remote_edges_to_delete(stk::CommSparse& comm, + bool unpackSideNodesToCheckEdgeValidity, + std::vector& edgesToDelete, + bool deletePllInfo) +{ + stk::mesh::EntityIdVector elem1SideNodeIds; + stk::mesh::EntityVector elem2SideNodes; + stk::mesh::EntityIdVector elem2SideNodeIds; + impl::ParallelGraphInfo& pllInfo = m_parallelInfoForGraphEdges.get_parallel_graph_info(); + for(int p=0; p(remoteElem1Id); + int remoteElem1Side = 0; + comm.recv_buffer(p).unpack(remoteElem1Side); + if (unpackSideNodesToCheckEdgeValidity) { + unsigned numSideNodes = 0; + comm.recv_buffer(p).unpack(numSideNodes); + elem1SideNodeIds.resize(numSideNodes); + for(unsigned i=0; i(elem1SideNodeIds[i]); + } + } + + EntityId remoteElem2Id = 0; + comm.recv_buffer(p).unpack(remoteElem2Id); + int remoteElem2Side = 0; + comm.recv_buffer(p).unpack(remoteElem2Side); + + Entity elem2 = m_bulk_data.get_entity(stk::topology::ELEM_RANK, remoteElem2Id); + if (unpackSideNodesToCheckEdgeValidity) { + stk::topology elem2Topo = m_bulk_data.bucket(elem2).topology(); + stk::topology elem2SideTopo = elem2Topo.side_topology(remoteElem2Side); + const Entity* elem2Nodes = m_bulk_data.begin(elem2,stk::topology::NODE_RANK); + elem2SideNodes.resize(elem2SideTopo.num_nodes()); + impl::fill_element_side_nodes_from_topology(elem2Topo, elem2Nodes, remoteElem2Side, elem2SideNodes); + elem2SideNodeIds.resize(elem2SideTopo.num_nodes()); + for(unsigned i=0; ifirst; + if (foundIt) { + pllInfo.erase(pllInfo_iter); + } + } + edgesToDelete.push_back(recvdGraphEdge); + } + } +} + +void ElemElemGraph::delete_remote_graph_edges(const std::vector& edgesToPossiblyDelete, + std::vector& recvdEdgesToDelete) +{ + stk::CommSparse comm(m_bulk_data.parallel()); + + bool commElem1Side1Nodes = true; + bool deletePllInfo = false; + pack_remote_edges_to_send(comm, commElem1Side1Nodes, edgesToPossiblyDelete, deletePllInfo); + comm.allocate_buffers(); + pack_remote_edges_to_send(comm, commElem1Side1Nodes, edgesToPossiblyDelete, deletePllInfo); + comm.communicate(); + std::vector edgesToActuallyDelete; + unpack_remote_edges_to_delete(comm, commElem1Side1Nodes, edgesToActuallyDelete, deletePllInfo); + + recvdEdgesToDelete.insert(recvdEdgesToDelete.end(), edgesToActuallyDelete.begin(), edgesToActuallyDelete.end()); + + stk::CommSparse comm2(comm.parallel()); + commElem1Side1Nodes = false; + pack_remote_edges_to_send(comm2, commElem1Side1Nodes, edgesToActuallyDelete, deletePllInfo); + comm2.allocate_buffers(); + deletePllInfo = true; + pack_remote_edges_to_send(comm2, commElem1Side1Nodes, edgesToActuallyDelete, deletePllInfo); + comm2.communicate(); + unpack_remote_edges_to_delete(comm2, commElem1Side1Nodes, recvdEdgesToDelete, deletePllInfo); +} + +void ElemElemGraph::update_graph_edges(const stk::mesh::EntityVector &elements) +{ + m_edgesToAdd.clear(); + m_edgesToDelete.clear(); + + std::vector graphEdgesInMesh; + std::vector coincidentGraphEdgesInMesh; + stk::mesh::EntityVector sideNodes; + impl::SerialElementDataVector connectedElementDataInMesh; + const bool onlyConsiderUpperSymmetry = false; + + stk::mesh::EntityVector changedShells; + std::vector remoteToDelete; + for(stk::mesh::Entity elem : elements) { + STK_ThrowRequireMsg(m_bulk_data.is_valid(elem) && m_bulk_data.state(elem) == Modified, + "ElemElemGraph::update_graph_edges P"< emptyDelete; + m_edgesToDelete.swap(emptyDelete); + } + + impl::ElemSideProcVector elemSideProcs = impl::build_element_side_ids_to_proc_map(m_bulk_data, elements); + impl::get_solid_elements_connected_to_shells_on_proc_boundaries( + m_bulk_data, changedShells, elements, elemSideProcs); + impl::ParallelElementDataVector elementSidesReceived; + communicate_shared_sides(elemSideProcs, elementSidesReceived); + fill_parallel_graph(elemSideProcs, elementSidesReceived); + + stk::util::sort_and_unique(m_edgesToAdd, GraphEdgeLessByElem1()); + m_graph.add_sorted_edges(m_edgesToAdd); + { + std::vector emptyAdd; + m_edgesToAdd.swap(emptyAdd); + } + + bool anyShellsExist = m_any_shell_elements_exist || !changedShells.empty(); + if (m_bulk_data.parallel_size() > 1) { + anyShellsExist = stk::is_true_on_any_proc(m_bulk_data.parallel(), anyShellsExist); + } + + if (anyShellsExist) { + handle_remote_edges_across_shells(changedShells); + } + + stk::util::sort_and_unique(m_edgesToDelete, GraphEdgeLessByElem1()); + m_graph.delete_sorted_edges(m_edgesToDelete); + + { + std::vector emptyDelete; + m_edgesToDelete.swap(emptyDelete); + } + + m_modCycleWhenGraphModified = m_bulk_data.synchronized_count(); +} + template void ElemElemGraph::add_new_local_edges_to_graph(GraphType &graph, const std::vector &newGraphEdges) { @@ -1157,6 +1404,27 @@ void ElemElemGraph::add_elements_locally(const stk::mesh::EntityVector& allEleme } } +void ElemElemGraph::handle_remote_edges_across_shells(stk::mesh::EntityVector& addedShellsVector) +{ + std::sort(addedShellsVector.begin(), addedShellsVector.end()); + STK_ThrowRequire(m_edgesToDelete.empty()); + GraphInfo graphInfo(m_graph, m_parallelInfoForGraphEdges, m_element_topologies); + remove_graph_edges_blocked_by_shell(graphInfo); + + stk::CommSparse comm(m_bulk_data.parallel()); + for (int phase = 0; phase < 2; ++phase) { + pack_remote_edge_across_shell(comm, addedShellsVector, phase); + if (0 == phase) { + comm.allocate_buffers(); + } + if (1 == phase) { + comm.communicate(); + } + } + + unpack_remote_edge_across_shell(comm); +} + void ElemElemGraph::add_elements(const stk::mesh::EntityVector &allUnfilteredElementsNotAlreadyInGraph) { stk::mesh::EntityVector allElementsNotAlreadyInGraph; @@ -1168,26 +1436,8 @@ void ElemElemGraph::add_elements(const stk::mesh::EntityVector &allUnfilteredEle impl::ElemSideProcVector only_added_elements = impl::build_element_side_ids_to_proc_map(m_bulk_data, allElementsNotAlreadyInGraph); std::sort(allElementsNotAlreadyInGraph.begin(), allElementsNotAlreadyInGraph.end()); - std::vector sharingProcs; - stk::mesh::EntityVector elemNodes; - for(stk::mesh::Entity addedShell : addedShellsVector) { - elemNodes.assign(m_bulk_data.begin_nodes(addedShell), m_bulk_data.end_nodes(addedShell)); - m_bulk_data.shared_procs_intersection(elemNodes, sharingProcs); - - if (!sharingProcs.empty()) { - stk::mesh::EntityVector solidElems = impl::gather_solid_elements_connected_to_shell(m_bulk_data, addedShell); - - for(stk::mesh::Entity elem : solidElems) { - stk::mesh::EntityVector::iterator elem_iter = std::lower_bound(allElementsNotAlreadyInGraph.begin(), allElementsNotAlreadyInGraph.end(), elem); - if (elem_iter == allElementsNotAlreadyInGraph.end()) { - unsigned side = stk::mesh::get_ordinal_and_permutation(m_bulk_data, elem, m_bulk_data.mesh_meta_data().side_rank(), elemNodes).first; - for(int p : sharingProcs) { - only_added_elements.push_back(impl::ElemSideProc(elem, side, p)); - } - } - } - } - } + impl::get_solid_elements_connected_to_shells_on_proc_boundaries( + m_bulk_data, addedShellsVector, allElementsNotAlreadyInGraph, only_added_elements); std::sort(only_added_elements.begin(), only_added_elements.end()); @@ -1209,23 +1459,7 @@ void ElemElemGraph::add_elements(const stk::mesh::EntityVector &allUnfilteredEle } if (anyShellsExist) { - std::sort(addedShellsVector.begin(), addedShellsVector.end()); - STK_ThrowRequire(m_edgesToDelete.empty()); - GraphInfo graphInfo(m_graph, m_parallelInfoForGraphEdges, m_element_topologies); - remove_graph_edges_blocked_by_shell(graphInfo); - - stk::CommSparse comm(m_bulk_data.parallel()); - for (int phase = 0; phase < 2; ++phase) { - pack_remote_edge_across_shell(comm, addedShellsVector, phase); - if (0 == phase) { - comm.allocate_buffers(); - } - if (1 == phase) { - comm.communicate(); - } - } - - unpack_remote_edge_across_shell(comm); + handle_remote_edges_across_shells(addedShellsVector); } stk::util::sort_and_unique(m_edgesToDelete, GraphEdgeLessByElem1()); @@ -1299,9 +1533,9 @@ void ElemElemGraph::pack_both_remote_shell_connectivity(stk::CommSparse &comm, i } } -void ElemElemGraph::pack_remote_edge_across_shell(stk::CommSparse &comm, stk::mesh::EntityVector &addedShells, int phase) +void ElemElemGraph::pack_remote_edge_across_shell(stk::CommSparse &comm, const stk::mesh::EntityVector &addedShells, int phase) { - for(stk::mesh::Entity &shell : addedShells) + for(stk::mesh::Entity shell : addedShells) { impl::LocalId shellId = m_idMapper.entity_to_local(shell); impl::LocalId leftId = impl::INVALID_LOCAL_ID; @@ -1541,6 +1775,34 @@ stk::mesh::EntityVector gather_solid_elements_connected_to_shell(const stk::mesh return solidElementsConnectedToShell; } +void get_solid_elements_connected_to_shells_on_proc_boundaries( + const stk::mesh::BulkData& bulk, + const stk::mesh::EntityVector& addedShellsVector, + const stk::mesh::EntityVector& allElementsNotAlreadyInGraph, + impl::ElemSideProcVector& only_added_elements) +{ + std::vector sharingProcs; + stk::mesh::EntityVector elemNodes; + for(stk::mesh::Entity addedShell : addedShellsVector) { + elemNodes.assign(bulk.begin_nodes(addedShell), bulk.end_nodes(addedShell)); + bulk.shared_procs_intersection(elemNodes, sharingProcs); + + if (!sharingProcs.empty()) { + stk::mesh::EntityVector solidElems = impl::gather_solid_elements_connected_to_shell(bulk, addedShell); + + for(stk::mesh::Entity elem : solidElems) { + stk::mesh::EntityVector::const_iterator elem_iter = std::lower_bound(allElementsNotAlreadyInGraph.begin(), allElementsNotAlreadyInGraph.end(), elem); + if (elem_iter == allElementsNotAlreadyInGraph.end()) { + unsigned side = stk::mesh::get_ordinal_and_permutation(bulk, elem, bulk.mesh_meta_data().side_rank(), elemNodes).first; + for(int p : sharingProcs) { + only_added_elements.push_back(impl::ElemSideProc(elem, side, p)); + } + } + } + } + } +} + }//namespace impl }} // end namespaces stk mesh diff --git a/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/ElemElemGraph.hpp b/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/ElemElemGraph.hpp index 1f781168b37a..a623532cae1e 100644 --- a/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/ElemElemGraph.hpp +++ b/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/ElemElemGraph.hpp @@ -143,6 +143,8 @@ class ElemElemGraph void delete_elements(const stk::mesh::impl::DeletedElementInfoVector &elements_to_delete); + void update_graph_edges(const stk::mesh::EntityVector &elements); + size_t size() const {return m_graph.get_num_elements_in_graph() - m_deleted_element_local_id_pool.size();} impl::LocalId get_local_element_id(stk::mesh::Entity local_element, bool require_valid_id = true) const; @@ -262,7 +264,7 @@ class ElemElemGraph void pack_shell_connectivity(stk::CommSparse & comm, const std::vector & shellConnectivityList, const std::vector &deletedShells); - void pack_remote_edge_across_shell(stk::CommSparse &comm, stk::mesh::EntityVector &addedShells, int phase); + void pack_remote_edge_across_shell(stk::CommSparse &comm, const stk::mesh::EntityVector &addedShells, int phase); void communicate_remote_edges_for_pre_existing_graph_nodes(const std::vector &newlySharedEdges, std::vector &receivedSharedEdges); @@ -341,6 +343,7 @@ class ElemElemGraph const impl::ShellConnectivityData& shellConnectivityData); bool are_connectivities_for_same_graph_edge(const impl::ShellConnectivityData& shellConn, const impl::ShellConnectivityData& shellConnectivityData); + void handle_remote_edges_across_shells(stk::mesh::EntityVector& addedShellsVector); bool is_connected_to_shell_on_side(stk::mesh::impl::LocalId localElemLocalId, int side); void insert_edge_between_elements(impl::LocalId local_elem_id, int side_index, @@ -348,6 +351,19 @@ class ElemElemGraph std::vector& coincidentGraphEdges) const; std::string print_edge(const GraphEdge& graphEdge); + + void pack_remote_edges_to_send(stk::CommSparse& comm, + bool sendElem1Side1Nodes, + const std::vector& edgesToSend, + bool deletePllInfo); + + void unpack_remote_edges_to_delete(stk::CommSparse& comm, + bool unpackSideNodesToCheckEdgeValidity, + std::vector& edgesToDelete, + bool deletePllInfo); + + void delete_remote_graph_edges(const std::vector& sendEdgesToDelete, + std::vector& recvdEdgesToDelete); }; namespace impl @@ -381,6 +397,11 @@ impl::ElemSideProcVector gather_element_side_ids_to_send(const stk::mesh::BulkDa stk::mesh::EntityVector gather_solid_elements_connected_to_shell(const stk::mesh::BulkData& bulkData, stk::mesh::Entity shellElement); +void get_solid_elements_connected_to_shells_on_proc_boundaries( + const stk::mesh::BulkData& bulk, + const stk::mesh::EntityVector& addedShellsVector, + const stk::mesh::EntityVector& allElementsNotAlreadyInGraph, + impl::ElemSideProcVector& only_added_elements); } // end impl }} // end stk mesh namespaces diff --git a/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/ElemElemGraphImpl.hpp b/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/ElemElemGraphImpl.hpp index e3a420d08c0c..df4748d57452 100644 --- a/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/ElemElemGraphImpl.hpp +++ b/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/ElemElemGraphImpl.hpp @@ -55,8 +55,6 @@ namespace stk { namespace mesh { namespace impl { -static const LocalId INVALID_LOCAL_ID = std::numeric_limits::max(); - struct RemoteElementData { public: diff --git a/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/ElemElemGraphUpdater.hpp b/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/ElemElemGraphUpdater.hpp index 316b3f88fb78..7230c55a40f9 100644 --- a/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/ElemElemGraphUpdater.hpp +++ b/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/ElemElemGraphUpdater.hpp @@ -35,24 +35,34 @@ #define STK_ELEM_ELEM_GRAPH_UPDATER_HPP #include // for size_t +#include "stk_mesh/base/Types.hpp" // for EntityId, EntityVector #include // for BulkData #include -#include // for MetaData #include // for topology, etc -#include // for ThrowRequire #include #include #include // for allocator, vector #include "stk_mesh/base/Bucket.hpp" // for Bucket #include "stk_mesh/base/Entity.hpp" // for Entity -#include "stk_mesh/base/Selector.hpp" // for Selector -#include "stk_mesh/base/Types.hpp" // for EntityId, EntityVector -#include "ElemElemGraph.hpp"// for ElemElemGraph -#include "ElemElemGraphImpl.hpp" +#include "ElemElemGraph.hpp" namespace stk { namespace mesh { +inline +void remove_created_and_deleted_elems(const stk::mesh::BulkData& bulk, + stk::mesh::EntityVector& elems) +{ + stk::util::sort_and_unique(elems); + elems.erase( + std::remove_if(elems.begin(), elems.end(), + [&](stk::mesh::Entity elem) { + return !bulk.is_valid(elem) || bulk.state(elem) == Created; + }), + elems.end() + ); +} + class ElemElemGraphUpdater : public stk::mesh::ModificationObserver { public: @@ -83,7 +93,7 @@ class ElemElemGraphUpdater : public stk::mesh::ModificationObserver if (bulkData.entity_rank(from) == stk::topology::ELEM_RANK && bulkData.entity_rank(to) == stk::topology::NODE_RANK && bulkData.bucket(from).owned()) { - elementsDeleted.push_back({from, bulkData.identifier(from), bulkData.bucket(from).topology().is_shell()}); + elementsChangedConn.push_back(from); } } @@ -92,8 +102,7 @@ class ElemElemGraphUpdater : public stk::mesh::ModificationObserver if (bulkData.entity_rank(from) == stk::topology::ELEM_RANK && bulkData.entity_rank(to) == stk::topology::NODE_RANK && bulkData.bucket(from).owned()) { - elementsDeleted.push_back({from, bulkData.identifier(from), bulkData.bucket(from).topology().is_shell()}); - elementsAdded.push_back(from); + elementsChangedConn.push_back(from); } } @@ -102,38 +111,62 @@ class ElemElemGraphUpdater : public stk::mesh::ModificationObserver if (changeEntityOwnerInProgress) { elementsAdded.clear(); elementsDeleted.clear(); + elementsChangedConn.clear(); elemGraph.fill_from_mesh(); changeEntityOwnerInProgress = false; + return; } - else if (maxNumAdded > 0) { + + if (maxNumAdded > 0) { elemGraph.add_elements(elementsAdded); elementsAdded.clear(); } + + if (maxNumChanged > 0) { + elemGraph.update_graph_edges(elementsChangedConn); + elementsChangedConn.clear(); + } } virtual void started_modification_end_notification() { stk::util::sort_and_unique(elementsDeleted); - if (get_global_sum(bulkData.parallel(), elementsDeleted.size()) > 0) { + remove_created_and_deleted_elems(bulkData, elementsChangedConn); + + constexpr size_t numValues = 2; + size_t localValues[numValues] = {0}, globalValues[numValues] = {0}; + localValues[0] = elementsDeleted.size(); + localValues[1] = elementsChangedConn.size(); + stk::all_reduce_sum(bulkData.parallel(), localValues, globalValues, numValues); + + if (globalValues[0] > 0) { elemGraph.delete_elements(elementsDeleted); elementsDeleted.clear(); } + + if (globalValues[1] > 0) { + elemGraph.update_graph_edges(elementsChangedConn); + elementsChangedConn.clear(); + } } virtual void fill_values_to_reduce(std::vector &valuesToReduce) { valuesToReduce.clear(); stk::util::sort_and_unique(elementsAdded); + remove_created_and_deleted_elems(bulkData, elementsChangedConn); unsigned value = any_added_elements_are_owned(elementsAdded) ? 1 : 0; if (value == 0) { elementsAdded.clear(); } valuesToReduce.push_back(value); + valuesToReduce.push_back(elementsChangedConn.size()); } virtual void set_reduced_values(const std::vector &reducedValues) { maxNumAdded = reducedValues[0]; + maxNumChanged = reducedValues[1]; } virtual void elements_about_to_move_procs_notification(const stk::mesh::EntityProcVec &elemProcPairsToMove) @@ -157,7 +190,9 @@ class ElemElemGraphUpdater : public stk::mesh::ModificationObserver stk::mesh::impl::ParallelGraphInfo newParallelGraphEntries; stk::mesh::EntityVector elementsAdded; stk::mesh::impl::DeletedElementInfoVector elementsDeleted; + stk::mesh::EntityVector elementsChangedConn; size_t maxNumAdded = 0; + size_t maxNumChanged = 0; bool changeEntityOwnerInProgress; }; diff --git a/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/GraphEdgeData.cpp b/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/GraphEdgeData.cpp index 1e4ed49ffd98..351d74716d26 100644 --- a/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/GraphEdgeData.cpp +++ b/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/GraphEdgeData.cpp @@ -251,6 +251,17 @@ void Graph::clear() m_numUnusedEntries = 0; } +void Graph::print(std::ostream& os) +{ + for(impl::LocalId i=0; i<(impl::LocalId)get_num_elements_in_graph(); ++i) { + GraphEdgesForElement graphEdges = get_edges_for_element(i); + os << "elem "<first == graphEdge, "ERROR: Proc " << m_procRank << " failed to find parallel graph info for edge " + if (throwIfNotFound) { + STK_ThrowRequireMsg( iter != m_parallel_graph_info.end() && iter->first == graphEdge, + "ERROR: Proc " << m_procRank << " failed to find parallel graph info for edge " << graphEdge << "."); + } return iter; } -impl::ParallelGraphInfo::iterator ParallelInfoForGraphEdges::get_parallel_info_iterator_for_graph_edge(const GraphEdge& graphEdge) +impl::ParallelGraphInfo::iterator ParallelInfoForGraphEdges::get_parallel_info_iterator_for_graph_edge(const GraphEdge& graphEdge, bool throwIfNotFound) { impl::ParallelGraphInfo::iterator iter = std::lower_bound(m_parallel_graph_info.begin(), m_parallel_graph_info.end(), graphEdge, GraphEdgeLessByElem2()); - STK_ThrowRequireMsg( iter != m_parallel_graph_info.end() && iter->first == graphEdge, "ERROR: Proc " << m_procRank << " failed to find parallel graph info for edge " + if (throwIfNotFound) { + STK_ThrowRequireMsg( iter != m_parallel_graph_info.end() && iter->first == graphEdge, "ERROR: Proc " << m_procRank << " failed to find parallel graph info for edge " << graphEdge << "."); + } return iter; } diff --git a/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/GraphEdgeData.hpp b/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/GraphEdgeData.hpp index b49136836e91..19cc168ab3af 100644 --- a/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/GraphEdgeData.hpp +++ b/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/GraphEdgeData.hpp @@ -37,6 +37,7 @@ #include "ElemElemGraphImpl.hpp" #include #include +#include namespace stk { @@ -64,6 +65,7 @@ class Graph void delete_sorted_edges(const std::vector& graphEdge); void clear(); + void print(std::ostream& os); private: using IndexRange = std::pair; @@ -98,8 +100,8 @@ class ParallelInfoForGraphEdges ParallelInfoForGraphEdges(int procRank) : m_procRank(procRank) {} impl::ParallelInfo& get_parallel_info_for_graph_edge(const GraphEdge& graphEdge); const impl::ParallelInfo& get_parallel_info_for_graph_edge(const GraphEdge& graphEdge) const; - impl::ParallelGraphInfo::const_iterator get_parallel_info_iterator_for_graph_edge(const GraphEdge& graphEdge) const; - impl::ParallelGraphInfo::iterator get_parallel_info_iterator_for_graph_edge(const GraphEdge& graphEdge); + impl::ParallelGraphInfo::const_iterator get_parallel_info_iterator_for_graph_edge(const GraphEdge& graphEdge, bool throwIfNotFound = true) const; + impl::ParallelGraphInfo::iterator get_parallel_info_iterator_for_graph_edge(const GraphEdge& graphEdge, bool throwIfNotFound = true); impl::ParallelGraphInfo &get_parallel_graph_info() { return m_parallel_graph_info; } const impl::ParallelGraphInfo &get_parallel_graph_info() const { return m_parallel_graph_info; } diff --git a/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/GraphTypes.hpp b/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/GraphTypes.hpp index 94716f93fa73..5fd182f954f5 100644 --- a/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/GraphTypes.hpp +++ b/packages/stk/stk_mesh/stk_mesh/baseImpl/elementGraph/GraphTypes.hpp @@ -47,6 +47,7 @@ namespace impl { using LocalId = int64_t; +static constexpr LocalId INVALID_LOCAL_ID = std::numeric_limits::max(); using PartOrdinals = std::vector; diff --git a/packages/stk/stk_middle_mesh/Jamfile b/packages/stk/stk_middle_mesh/Jamfile index b714c0bbab1a..b9608cf11828 100644 --- a/packages/stk/stk_middle_mesh/Jamfile +++ b/packages/stk/stk_middle_mesh/Jamfile @@ -190,7 +190,7 @@ lib stk_middle_mesh [ glob $(stk_middle_mesh-root)/stk_middle_mesh/predicates/*.cpp ] [ glob $(stk_middle_mesh-root)/stk_middle_mesh_utils/*.cpp ] ] - /sierra/stk_util//stk_util_environment + /sierra/stk_util//stk_util_parallel /sierra/stk_util//stk_util_util /sierra/stk_search//stk_search /mpi//mpi diff --git a/packages/stk/stk_ngp_test/stk_ngp_test/NgpTestDeviceMacros.hpp b/packages/stk/stk_ngp_test/stk_ngp_test/NgpTestDeviceMacros.hpp index 6c301b537ec7..0aac6f0aa609 100644 --- a/packages/stk/stk_ngp_test/stk_ngp_test/NgpTestDeviceMacros.hpp +++ b/packages/stk/stk_ngp_test/stk_ngp_test/NgpTestDeviceMacros.hpp @@ -1,7 +1,7 @@ #ifndef STK_NGP_TEST_NGPTESTDEVICEMACROS_HPP #define STK_NGP_TEST_NGPTESTDEVICEMACROS_HPP -#include +#include #define NGP_TEST_FUNCTION KOKKOS_FUNCTION #define NGP_TEST_INLINE KOKKOS_INLINE_FUNCTION diff --git a/packages/stk/stk_performance_tests/stk_mesh/perfCommNeighbors.cpp b/packages/stk/stk_performance_tests/stk_mesh/perfCommNeighbors.cpp index a6ca44575913..8d145096858f 100644 --- a/packages/stk/stk_performance_tests/stk_mesh/perfCommNeighbors.cpp +++ b/packages/stk/stk_performance_tests/stk_mesh/perfCommNeighbors.cpp @@ -278,7 +278,7 @@ class StkPerfComm : public stk::unit_test_util::MeshFixture const std::vector& procs = get_bulk().all_sharing_procs(stk::topology::NODE_RANK); stk::CommNeighbors commNeighbors(get_bulk().parallel(), procs); for(int p : procs) { - const stk::mesh::HostCommMapIndices sharedCommMap = get_bulk().volatile_fast_shared_comm_map(stk::topology::NODE_RANK, p); + const stk::mesh::HostCommMapIndices sharedCommMap = get_bulk().volatile_fast_shared_comm_map(stk::topology::NODE_RANK, p); size_t numEntities = sharedCommMap.extent(0); commNeighbors.send_buffer(p).reserve(numEntities*sizeof(stk::mesh::EntityKey)); } diff --git a/packages/stk/stk_search/stk_search/morton_lbvh/CoarseSearchMortonLBVH.hpp b/packages/stk/stk_search/stk_search/morton_lbvh/CoarseSearchMortonLBVH.hpp index 1a0f729a82c3..5779ae543a11 100644 --- a/packages/stk/stk_search/stk_search/morton_lbvh/CoarseSearchMortonLBVH.hpp +++ b/packages/stk/stk_search/stk_search/morton_lbvh/CoarseSearchMortonLBVH.hpp @@ -169,7 +169,7 @@ inline void coarse_search_morton_lbvh(std::vector(domainTree, rangeTree, callback, HostSpace{}); + stk::search::morton_lbvh_search(domainTree, rangeTree, callback, HostSpace{}); Kokkos::Profiling::popRegion(); if (enforceSearchResultSymmetry) { @@ -365,7 +365,7 @@ inline void coarse_search_morton_lbvh( Kokkos::Profiling::pushRegion("Inner morton search"); BoundingShapeIntersectionChecker intersectionChecker(localDomain, localRange, extendedRangeBoxes, remoteRangeIdentProcs, searchResults); - stk::search::morton_lbvh_search(domainTree, rangeTree, intersectionChecker, execSpace); + stk::search::morton_lbvh_search(domainTree, rangeTree, intersectionChecker, execSpace); searchResults = intersectionChecker.get_search_results(); Kokkos::Profiling::popRegion(); diff --git a/packages/stk/stk_search/stk_search/morton_lbvh/LocalCoarseSearchMortonLBVH.hpp b/packages/stk/stk_search/stk_search/morton_lbvh/LocalCoarseSearchMortonLBVH.hpp index 1d6b39beab82..a9491a05259f 100644 --- a/packages/stk/stk_search/stk_search/morton_lbvh/LocalCoarseSearchMortonLBVH.hpp +++ b/packages/stk/stk_search/stk_search/morton_lbvh/LocalCoarseSearchMortonLBVH.hpp @@ -137,7 +137,7 @@ void local_coarse_search_morton_lbvh( stk::search::CollisionList collisionList("Collision List"); Callback callback(domain, range, searchResults); - stk::search::morton_lbvh_search(domainTree, rangeTree, callback, HostSpace{}); + stk::search::morton_lbvh_search(domainTree, rangeTree, callback, HostSpace{}); searchResults = callback.get_search_results(); if (sortSearchResults) { @@ -335,7 +335,7 @@ local_coarse_search_morton_lbvh( Callback& callback = mortonData->callback; Kokkos::Profiling::popRegion(); - stk::search::morton_lbvh_search(domainTree, rangeTree, callback, execSpace); + stk::search::morton_lbvh_search(domainTree, rangeTree, callback, execSpace); searchResults = callback.get_search_results(); Kokkos::Profiling::popRegion(); diff --git a/packages/stk/stk_search/stk_search/morton_lbvh/MortonLBVH_Search.hpp b/packages/stk/stk_search/stk_search/morton_lbvh/MortonLBVH_Search.hpp index 07dd1bfd57be..7f9b4d95b1c9 100644 --- a/packages/stk/stk_search/stk_search/morton_lbvh/MortonLBVH_Search.hpp +++ b/packages/stk/stk_search/stk_search/morton_lbvh/MortonLBVH_Search.hpp @@ -187,7 +187,7 @@ inline void export_box_view_to_morton_tree(const BoxView boxes, Kokkos::parallel_for(policy, func); } -template +template inline void morton_lbvh_search(MortonAabbTree &tree1, MortonAabbTree &tree2, Callback& resultCallback, diff --git a/packages/stk/stk_tools/stk_tools/mesh_tools/DisconnectBlocksImpl.cpp b/packages/stk/stk_tools/stk_tools/mesh_tools/DisconnectBlocksImpl.cpp index da12ddfc1838..5b6fa3bba73f 100644 --- a/packages/stk/stk_tools/stk_tools/mesh_tools/DisconnectBlocksImpl.cpp +++ b/packages/stk/stk_tools/stk_tools/mesh_tools/DisconnectBlocksImpl.cpp @@ -10,6 +10,7 @@ #include "stk_mesh/base/SkinMeshUtil.hpp" #include "stk_mesh/base/ExodusTranslator.hpp" #include "stk_mesh/baseImpl/MeshImplUtils.hpp" +#include "stk_mesh/baseImpl/AuraGhosting.hpp" #include "stk_tools/mesh_tools/DisconnectBlocks.hpp" #include "stk_util/parallel/CommSparse.hpp" #include "stk_util/util/SortAndUnique.hpp" @@ -710,10 +711,6 @@ void disconnect_faces(stk::mesh::BulkData& bulk, LinkInfo& info) update_internal_face_entity_relation(bulk, faceInfo); } - if (bulk.has_face_adjacent_element_graph()) { - bulk.get_face_adjacent_element_graph().fill_from_mesh(); - } - for (auto faceInfo : info.internalSides) { disconnect_internal_face(bulk, faceInfo); } @@ -1260,33 +1257,30 @@ void update_node_id(stk::mesh::EntityId newNodeId, int proc, LinkInfo& info, con } } -void clean_up_aura(stk::mesh::BulkData& bulk, LinkInfo& info) +void remove_orphan_nodes(stk::mesh::BulkData& bulk) { - stk::mesh::EntityVector allNodes; - stk::mesh::get_entities(bulk, stk::topology::NODE_RANK, bulk.mesh_meta_data().locally_owned_part(), allNodes); - - for(stk::mesh::Entity node : allNodes) { - const int numElems = bulk.num_connectivity(node, stk::topology::ELEMENT_RANK); - const stk::mesh::Entity* elems = bulk.begin(node, stk::topology::ELEMENT_RANK); - int numDestroyedElems = 0; - - for(int i = numElems-1; i >= 0; --i) { - stk::mesh::Entity elem = elems[i]; - if(!bulk.bucket(elem).owned()) { - bulk.destroy_entity(elem); - ++numDestroyedElems; - } - } - - if(numDestroyedElems == numElems) { + stk::mesh::EntityVector ownedNodes; + stk::mesh::get_entities(bulk, stk::topology::NODE_RANK, bulk.mesh_meta_data().locally_owned_part(), ownedNodes); + for(stk::mesh::Entity node : ownedNodes) { + if (!stk::mesh::impl::has_upward_connectivity(bulk, node)) { bulk.destroy_entity(node); } } } +void clean_up_aura(stk::mesh::BulkData& bulk, LinkInfo& info) +{ + stk::mesh::impl::AuraGhosting auraGhosting; + auraGhosting.remove_aura(bulk); +} + void disconnect_block_pairs(stk::mesh::BulkData& bulk, const std::vector& blockPairsToDisconnect, LinkInfo& info) { + const bool haveGraph = bulk.has_face_adjacent_element_graph(); + if (haveGraph) { + bulk.delete_face_adjacent_element_graph(); + } bulk.modification_begin(); for (size_t i = 0; i < blockPairsToDisconnect.size(); ++i) { @@ -1314,11 +1308,11 @@ void disconnect_block_pairs(stk::mesh::BulkData& bulk, const std::vector& blockPairsToReconnect, LinkInfo& info) { + const bool haveGraph = bulk.has_face_adjacent_element_graph(); + if (haveGraph) { + bulk.delete_face_adjacent_element_graph(); + } bulk.modification_begin(); sanitize_node_map(info.originalNodeMap, info); @@ -1381,8 +1379,12 @@ void reconnect_block_pairs(stk::mesh::BulkData& bulk, const std::vector= num_faces()) { + if (has_mixed_rank_sides() && sub_ordinal >= num_faces()) { edge_node_ordinals(sub_ordinal - num_faces(), output_ordinals); } else { face_node_ordinals(sub_ordinal, output_ordinals); @@ -111,7 +96,7 @@ void topology::sub_topology_nodes(const NodeArray & nodes, unsigned sub_rank, un case NODE_RANK: *output_nodes = nodes[sub_ordinal]; break; case EDGE_RANK: edge_nodes(nodes, sub_ordinal, output_nodes); break; case FACE_RANK: - if (is_shell_side_ordinal(sub_ordinal)) { + if (has_mixed_rank_sides() && sub_ordinal >= num_faces()) { edge_nodes(nodes, sub_ordinal - num_faces(), output_nodes); } else { face_nodes(nodes, sub_ordinal, output_nodes); @@ -142,7 +127,7 @@ topology topology::sub_topology(unsigned sub_rank, unsigned sub_ordinal) const case NODE_RANK: return NODE; case EDGE_RANK: return edge_topology(sub_ordinal); case FACE_RANK: - if (is_shell_side_ordinal(sub_ordinal)) { + if (has_mixed_rank_sides() && sub_ordinal >= num_faces()) { return edge_topology(sub_ordinal - num_faces()); } return face_topology(sub_ordinal); @@ -155,7 +140,7 @@ template STK_INLINE_FUNCTION void topology::side_node_ordinals(unsigned side_ordinal, OrdinalOutputIterator output_ordinals) const { - if (is_shell_side_ordinal(side_ordinal)) { + if (has_mixed_rank_sides() && is_shell_side_ordinal(side_ordinal)) { sub_topology_node_ordinals(EDGE_RANK, side_ordinal-num_faces(), output_ordinals); } else { sub_topology_node_ordinals( side_rank(), side_ordinal, output_ordinals); @@ -166,7 +151,7 @@ template STK_INLINE_FUNCTION void topology::side_nodes(const NodeArray & nodes, unsigned side_ordinal, NodeOutputIterator output_nodes) const { - if (is_shell_side_ordinal(side_ordinal)) { + if (has_mixed_rank_sides() && is_shell_side_ordinal(side_ordinal)) { sub_topology_nodes( nodes, EDGE_RANK, side_ordinal-num_faces(), output_nodes); } else { sub_topology_nodes( nodes, side_rank(), side_ordinal, output_nodes); @@ -178,11 +163,11 @@ unsigned topology::num_sides() const { unsigned num_sides_out = 0u; if (side_rank() != INVALID_RANK) { - num_sides_out = side_rank() > NODE_RANK? num_sub_topology(side_rank()) : num_vertices(); + num_sides_out = side_rank() > NODE_RANK ? num_sub_topology(side_rank()) : num_vertices(); - if (is_shell_with_face_sides() && - !impl::is_temporary_shell_with_all_face_sides(m_value)) + if (has_mixed_rank_sides()) { num_sides_out += num_sub_topology(EDGE_RANK); + } } return num_sides_out; } @@ -190,7 +175,7 @@ unsigned topology::num_sides() const STK_INLINE_FUNCTION topology topology::side_topology(unsigned side_ordinal) const { - if (is_shell_side_ordinal(side_ordinal) && !impl::is_temporary_shell_with_all_face_sides(m_value)) + if (has_mixed_rank_sides() && is_shell_side_ordinal(side_ordinal)) return shell_side_topology(side_ordinal-num_faces()); return sub_topology(side_rank(), side_ordinal); @@ -248,12 +233,20 @@ bool topology::is_shell_with_face_sides() const { } STK_INLINE_FUNCTION -stk::topology::rank_t topology::side_rank() const { - using functor = topology_detail::side_rank_impl; +bool topology::has_mixed_rank_sides() const { + using functor = topology_detail::has_mixed_rank_sides_impl; topology::apply_functor< functor > apply; return apply(m_value); } +STK_INLINE_FUNCTION +stk::topology::rank_t topology::side_rank(unsigned ord) const { + using functor = topology_detail::side_rank_impl; + functor f(ord); + topology::apply_functor< functor > apply(f); + return apply(m_value); +} + STK_INLINE_FUNCTION unsigned topology::dimension() const { using functor = topology_detail::dimension_impl; diff --git a/packages/stk/stk_topology/stk_topology/topology_detail/meta_functions.hpp b/packages/stk/stk_topology/stk_topology/topology_detail/meta_functions.hpp index 282b669ae220..7ac49d9287a3 100644 --- a/packages/stk/stk_topology/stk_topology/topology_detail/meta_functions.hpp +++ b/packages/stk/stk_topology/stk_topology/topology_detail/meta_functions.hpp @@ -128,6 +128,20 @@ constexpr topology::topology_t face_topology_() //------------------------------------------------------------------------------ +template +STK_INLINE_FUNCTION +constexpr topology::rank_t side_rank_() +{ + if constexpr (SideOrdinal < Topology::num_faces) { + return topology::FACE_RANK; + } else { + return topology::EDGE_RANK; + } + return Topology::side_rank; +} + +//------------------------------------------------------------------------------ + template STK_INLINE_FUNCTION constexpr topology::topology_t shell_side_topology_() diff --git a/packages/stk/stk_topology/stk_topology/topology_detail/topology_data.hpp b/packages/stk/stk_topology/stk_topology/topology_detail/topology_data.hpp index ce22512c7afe..565b9478f624 100644 --- a/packages/stk/stk_topology/stk_topology/topology_detail/topology_data.hpp +++ b/packages/stk/stk_topology/stk_topology/topology_detail/topology_data.hpp @@ -68,6 +68,7 @@ struct topology_data static constexpr topology::rank_t side_rank = topology::INVALID_RANK; static constexpr bool is_valid = false; static constexpr bool has_homogeneous_faces = false; + static constexpr bool has_mixed_rank_sides = false; static constexpr bool is_shell = false; static constexpr uint8_t dimension = 0; static constexpr uint8_t num_vertices = 0; @@ -773,6 +774,7 @@ struct topology_data static constexpr topology::rank_t side_rank = topology::FACE_RANK; static constexpr bool is_shell = true; static constexpr bool has_homogeneous_faces = true; + static constexpr bool has_mixed_rank_sides = true; static constexpr uint8_t dimension = 3; static constexpr uint8_t num_faces = 2; @@ -797,6 +799,7 @@ struct topology_data static constexpr topology::rank_t side_rank = topology::FACE_RANK; static constexpr bool is_shell = true; static constexpr bool has_homogeneous_faces = true; + static constexpr bool has_mixed_rank_sides = true; static constexpr uint8_t dimension = 3; static constexpr uint8_t num_faces = 2; @@ -821,6 +824,7 @@ struct topology_data static constexpr topology::rank_t side_rank = topology::FACE_RANK; static constexpr bool is_shell = true; static constexpr bool has_homogeneous_faces = true; + static constexpr bool has_mixed_rank_sides = true; static constexpr uint8_t dimension = 3; static constexpr uint8_t num_faces = 2; @@ -846,7 +850,7 @@ struct topology_data static constexpr topology::rank_t rank = topology::ELEMENT_RANK; static constexpr topology::rank_t side_rank = topology::FACE_RANK; static constexpr bool is_shell = true; - static constexpr bool has_homogeneous_faces = true; + static constexpr bool has_homogeneous_faces = false; static constexpr uint8_t dimension = 3; static constexpr uint8_t num_faces = 5; @@ -873,7 +877,7 @@ struct topology_data static constexpr topology::rank_t rank = topology::ELEMENT_RANK; static constexpr topology::rank_t side_rank = topology::FACE_RANK; static constexpr bool is_shell = true; - static constexpr bool has_homogeneous_faces = true; + static constexpr bool has_homogeneous_faces = false; static constexpr uint8_t dimension = 3; static constexpr uint8_t num_faces = 5; @@ -900,7 +904,7 @@ struct topology_data static constexpr topology::rank_t rank = topology::ELEMENT_RANK; static constexpr topology::rank_t side_rank = topology::FACE_RANK; static constexpr bool is_shell = true; - static constexpr bool has_homogeneous_faces = true; + static constexpr bool has_homogeneous_faces = false; static constexpr uint8_t dimension = 3; static constexpr uint8_t num_faces = 5; @@ -1177,6 +1181,7 @@ struct topology_data static constexpr topology::rank_t side_rank = topology::FACE_RANK; static constexpr bool is_shell = true; static constexpr bool has_homogeneous_faces = true; + static constexpr bool has_mixed_rank_sides = true; static constexpr uint8_t dimension = 3; static constexpr uint8_t num_faces = 2; @@ -1201,6 +1206,7 @@ struct topology_data static constexpr topology::rank_t side_rank = topology::FACE_RANK; static constexpr bool is_shell = true; static constexpr bool has_homogeneous_faces = true; + static constexpr bool has_mixed_rank_sides = true; static constexpr uint8_t dimension = 3; static constexpr uint8_t num_faces = 2; @@ -1226,6 +1232,7 @@ struct topology_data static constexpr topology::rank_t side_rank = topology::FACE_RANK; static constexpr bool is_shell = true; static constexpr bool has_homogeneous_faces = true; + static constexpr bool has_mixed_rank_sides = true; static constexpr uint8_t dimension = 3; static constexpr uint8_t num_faces = 2; @@ -1252,7 +1259,7 @@ struct topology_data static constexpr topology::rank_t rank = topology::ELEMENT_RANK; static constexpr topology::rank_t side_rank = topology::FACE_RANK; static constexpr bool is_shell = true; - static constexpr bool has_homogeneous_faces = true; + static constexpr bool has_homogeneous_faces = false; static constexpr uint8_t dimension = 3; static constexpr uint8_t num_faces = 6; @@ -1280,7 +1287,7 @@ struct topology_data static constexpr topology::rank_t rank = topology::ELEMENT_RANK; static constexpr topology::rank_t side_rank = topology::FACE_RANK; static constexpr bool is_shell = true; - static constexpr bool has_homogeneous_faces = true; + static constexpr bool has_homogeneous_faces = false; static constexpr uint8_t dimension = 3; static constexpr uint8_t num_faces = 6; @@ -1309,7 +1316,7 @@ struct topology_data static constexpr topology::rank_t rank = topology::ELEMENT_RANK; static constexpr topology::rank_t side_rank = topology::FACE_RANK; static constexpr bool is_shell = true; - static constexpr bool has_homogeneous_faces = true; + static constexpr bool has_homogeneous_faces = false; static constexpr uint8_t dimension = 3; static constexpr uint8_t num_faces = 6; diff --git a/packages/stk/stk_topology/stk_topology/topology_type.hpp b/packages/stk/stk_topology/stk_topology/topology_type.hpp index a4bac5cd79b1..c63401efb554 100644 --- a/packages/stk/stk_topology/stk_topology/topology_type.hpp +++ b/packages/stk/stk_topology/stk_topology/topology_type.hpp @@ -64,6 +64,7 @@ struct topology::topology_type static const rank_t rank = data::rank; static const rank_t side_rank = data::side_rank; static const bool has_homogeneous_faces = data::has_homogeneous_faces; + static const bool has_mixed_rank_sides = data::has_mixed_rank_sides; static const bool is_shell = data::is_shell; static const unsigned dimension = data::dimension; static const unsigned num_nodes = data::num_nodes; @@ -95,6 +96,33 @@ struct topology::topology_type return false; } + STK_FUNCTION + static rank_t side_topology_rank(unsigned side_ordinal = 0) + { + switch (side_ordinal) + { + case 0: return topology_detail::side_rank_(); + case 1: return topology_detail::side_rank_(); + case 2: return topology_detail::side_rank_(); + case 3: return topology_detail::side_rank_(); + case 4: return topology_detail::side_rank_(); + case 5: return topology_detail::side_rank_(); + case 6: return topology_detail::side_rank_(); + case 7: return topology_detail::side_rank_(); + case 8: return topology_detail::side_rank_(); + case 9: return topology_detail::side_rank_(); + case 10: return topology_detail::side_rank_(); + case 11: return topology_detail::side_rank_(); + case 12: return topology_detail::side_rank_(); + case 13: return topology_detail::side_rank_(); + case 14: return topology_detail::side_rank_(); + case 15: return topology_detail::side_rank_(); + default: break; + } + + return INVALID_RANK; + } + /// the topology of the edge at the given ordinal STK_FUNCTION static topology edge_topology(unsigned edge_ordinal = 0) diff --git a/packages/stk/stk_topology/stk_topology/topology_utils.hpp b/packages/stk/stk_topology/stk_topology/topology_utils.hpp index 3e398d7b3081..b4be3a37ab78 100644 --- a/packages/stk/stk_topology/stk_topology/topology_utils.hpp +++ b/packages/stk/stk_topology/stk_topology/topology_utils.hpp @@ -38,6 +38,7 @@ // IWYU pragma: private, include "stk_topology/topology.hpp" #include "stk_topology/topology_decl.hpp" #include "stk_util/stk_config.h" +#include namespace stk { namespace topology_detail { @@ -108,6 +109,26 @@ struct lexicographical_smallest_permutation_preserve_polarity_impl { const NodeArray & m_element_nodes; }; +// temporary helpers until shell side conversions are fully complete +template +struct HasMixedRankSides : std::false_type {}; + +template +struct HasMixedRankSides : std::true_type {}; + +struct has_mixed_rank_sides_impl { + using result_type = bool; + + template + STK_INLINE_FUNCTION + result_type operator()(Topology) const { + if constexpr (HasMixedRankSides::value) { + return Topology::has_mixed_rank_sides; + } + return false; + } +}; + struct has_homogeneous_faces_impl { using result_type = bool; @@ -139,9 +160,22 @@ struct is_shell_with_face_sides_impl { struct side_rank_impl { using result_type = stk::topology::rank_t; + STK_INLINE_FUNCTION + side_rank_impl(unsigned ordinal) + : m_ordinal(ordinal) + {} + template STK_INLINE_FUNCTION - result_type operator()(Topology) const { return Topology::side_rank; } + result_type operator()(Topology) const { + if (!has_mixed_rank_sides_impl{}(Topology{})) { + return Topology::side_rank; + } else { + return Topology::side_topology_rank(m_ordinal); + } + } + + unsigned m_ordinal; }; struct dimension_impl { diff --git a/packages/stk/stk_transfer/stk_transfer/GeometricTransfer.hpp b/packages/stk/stk_transfer/stk_transfer/GeometricTransfer.hpp index 959fc577972a..bde5a2a57383 100644 --- a/packages/stk/stk_transfer/stk_transfer/GeometricTransfer.hpp +++ b/packages/stk/stk_transfer/stk_transfer/GeometricTransfer.hpp @@ -43,7 +43,6 @@ #include #include -#include #include #include diff --git a/packages/stk/stk_transfer/stk_transfer/GeometricTransferImpl.hpp b/packages/stk/stk_transfer/stk_transfer/GeometricTransferImpl.hpp index 8963be193406..8847b1cfab16 100644 --- a/packages/stk/stk_transfer/stk_transfer/GeometricTransferImpl.hpp +++ b/packages/stk/stk_transfer/stk_transfer/GeometricTransferImpl.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include @@ -128,9 +128,9 @@ void print_expansion_warnings(stk::ParallelMachine comm, int not_empty_count, si // sum and provide message to user size_t g_range_vector_size = 0; stk::all_reduce_max( comm, &range_vector_size, &g_range_vector_size, 1); - sierra::Env::outputP0() << "GeometricTransfer::coarse_search(): Number of points not found: " << g_range_vector_size + stk::outputP0() << "GeometricTransfer::coarse_search(): Number of points not found: " << g_range_vector_size << " after expanding bounding boxes: " << not_empty_count << " time(s)" << std::endl; - sierra::Env::outputP0() << "...will now expand the set of candidate bounding boxes and re-attempt the coarse search" << std::endl; + stk::outputP0() << "...will now expand the set of candidate bounding boxes and re-attempt the coarse search" << std::endl; } template @@ -189,7 +189,7 @@ void coarse_search_impl(typename INTERPOLATE::EntityProcRelationVec &range_to_ size_t range_vector_size = range_vector.size(); size_t g_range_vector_size = 0; stk::all_reduce_max( comm, &range_vector_size, &g_range_vector_size, 1); - sierra::Env::outputP0() << "GeometricTransfer::coarse_search(): Number of points not found: " + stk::outputP0() << "GeometricTransfer::coarse_search(): Number of points not found: " << g_range_vector_size << " in initial coarse search" << std::endl; } diff --git a/packages/stk/stk_transfer/stk_transfer/copy_by_id/TransferCopyById.cpp b/packages/stk/stk_transfer/stk_transfer/copy_by_id/TransferCopyById.cpp index 4b19f17f8f09..e3f600da27be 100644 --- a/packages/stk/stk_transfer/stk_transfer/copy_by_id/TransferCopyById.cpp +++ b/packages/stk/stk_transfer/stk_transfer/copy_by_id/TransferCopyById.cpp @@ -35,8 +35,7 @@ #include "TransferCopyById.hpp" #include #include -#include -#include +#include namespace stk { namespace transfer { diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/ElemGraphMultipleSharedSidesUtils.hpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/ElemGraphMultipleSharedSidesUtils.hpp index 212a1097572b..8269df79a033 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/ElemGraphMultipleSharedSidesUtils.hpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/ElemGraphMultipleSharedSidesUtils.hpp @@ -136,10 +136,12 @@ class TwoElemMultipleSharedSideTester : public ::testing::Test void add_shared_nodes(stk::mesh::BulkData& bulkData, const std::vector& sharedNodeIds) { - int otherProc = 1 - bulkData.parallel_rank(); - for(stk::mesh::EntityId nodeID : sharedNodeIds) { - stk::mesh::Entity node = bulkData.get_entity(stk::topology::NODE_RANK, nodeID); - bulkData.add_node_sharing(node, otherProc); + if (bulkData.parallel_size() > 1) { + const int otherProc = 1 - bulkData.parallel_rank(); + for(stk::mesh::EntityId nodeID : sharedNodeIds) { + stk::mesh::Entity node = bulkData.get_entity(stk::topology::NODE_RANK, nodeID); + bulkData.add_node_sharing(node, otherProc); + } } } @@ -415,11 +417,13 @@ TwoElemMultipleSharedSideTester : public ::testing::Test void add_shared_nodes(stk::mesh::BulkData& bulkData, const std::vector& sharedNodeIds) { - int otherProc = 1 - bulkData.parallel_rank(); + if (bulkData.parallel_size() > 1) { + const int otherProc = 1 - bulkData.parallel_rank(); for(stk::mesh::EntityId nodeID : sharedNodeIds) { stk::mesh::Entity node = bulkData.get_entity(stk::topology::NODE_RANK, nodeID); bulkData.add_node_sharing(node, otherProc); } + } } protected: diff --git a/packages/stk/stk_unit_tests/stk_balance/MeshFixtureDecomposer.hpp b/packages/stk/stk_unit_tests/stk_balance/MeshFixtureDecomposer.hpp index 7b65765f9ad8..996472321163 100644 --- a/packages/stk/stk_unit_tests/stk_balance/MeshFixtureDecomposer.hpp +++ b/packages/stk/stk_unit_tests/stk_balance/MeshFixtureDecomposer.hpp @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include @@ -94,9 +94,9 @@ class MeshFixtureDecomposer : public stk::unit_test_util::MeshFixture } - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + stk::set_outputP0(&stk::outputNull()); stk::balance::DecompositionChangeList decomp = m_decomposer->get_partition(); - stk::EnvData::instance().m_outputP0 = &std::cout; + stk::reset_default_output_streams(); bool isNested = true; for (const auto & entityProc : decomp) { diff --git a/packages/stk/stk_unit_tests/stk_balance/MeshFixtureM2NDecomposer.hpp b/packages/stk/stk_unit_tests/stk_balance/MeshFixtureM2NDecomposer.hpp index 504393a7d6c5..4fa374d900f5 100644 --- a/packages/stk/stk_unit_tests/stk_balance/MeshFixtureM2NDecomposer.hpp +++ b/packages/stk/stk_unit_tests/stk_balance/MeshFixtureM2NDecomposer.hpp @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include @@ -95,9 +95,9 @@ class MeshFixtureM2NDecomposer : public stk::unit_test_util::MeshFixture } - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + stk::set_outputP0(&stk::outputNull()); const stk::mesh::EntityProcVec & decomp = m_decomposer->get_partition(); - stk::EnvData::instance().m_outputP0 = &std::cout; + stk::reset_default_output_streams(); bool isNested = true; for (const stk::mesh::EntityProc & entityProc : decomp) { diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestBalanceFromField.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestBalanceFromField.cpp index 5099e07f7711..80d7e1a68fa6 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestBalanceFromField.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestBalanceFromField.cpp @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include "stk_balance/io/BalanceIO.hpp" #include #include @@ -77,12 +77,12 @@ class BalanceFromField : public MeshFixtureRebalance { public: BalanceFromField() { - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + stk::set_outputP0(&stk::outputNull()); testing::internal::CaptureStderr(); } ~BalanceFromField() override { - stk::EnvData::instance().m_outputP0 = &std::cout; + stk::reset_default_output_streams(); testing::internal::GetCapturedStderr(); } diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestBlockWeights.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestBlockWeights.cpp index e022f8b00b6e..a12487e5d515 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestBlockWeights.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestBlockWeights.cpp @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include #include @@ -99,11 +99,11 @@ class TestBlockWeights : public stk::unit_test_util::MeshFixture const int numProcs = 2; stk::mesh::EntityProcVec decomp; - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + stk::set_outputP0(&stk::outputNull()); stk::balance::internal::calculateGeometricOrGraphBasedDecomp(get_bulk(), selectors, get_bulk().parallel(), numProcs, balanceSettings, decomp); - stk::EnvData::instance().m_outputP0 = &std::cout; + stk::reset_default_output_streams(); check_decomposition(decomp, expectedElemsOnEachProc); } diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestDefaultDecomposer.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestDefaultDecomposer.cpp index b2ece1a28cee..eee8318fff0f 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestDefaultDecomposer.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestDefaultDecomposer.cpp @@ -108,9 +108,9 @@ class DefaultRebalance : public MeshFixtureRebalance m_balanceSettings.set_num_output_processors(numFinalProcs); m_balanceSettings.setDecompMethod(decompMethod); - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + stk::set_outputP0(&stk::outputNull()); stk::balance::rebalance(m_ioBroker, m_balanceSettings); - stk::EnvData::instance().m_outputP0 = &std::cout; + stk::reset_default_output_streams(); } }; diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestDiagnosticsComputation.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestDiagnosticsComputation.cpp index bca04706f40a..eece7645812f 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestDiagnosticsComputation.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestDiagnosticsComputation.cpp @@ -41,7 +41,7 @@ #include "stk_balance/rebalance.hpp" #include "stk_balance/balance.hpp" #include -#include +#include #include class TestDiagnosticsComputation : public stk::unit_test_util::MeshFixture @@ -53,13 +53,13 @@ class TestDiagnosticsComputation : public stk::unit_test_util::MeshFixture virtual void NGPSetUp() override { stk::balance::impl::g_diagnosticsContainer.clear(); - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + stk::set_outputP0(&stk::outputNull()); testing::internal::CaptureStderr(); } virtual void NGPTearDown() override { stk::balance::impl::g_diagnosticsContainer.clear(); - stk::EnvData::instance().m_outputP0 = &std::cout; + stk::reset_default_output_streams(); testing::internal::GetCapturedStderr(); } @@ -136,7 +136,7 @@ class TestDiagnosticsComputation : public stk::unit_test_util::MeshFixture stk::balance::rebalance(ioBroker, balanceSettings); stk::balance::DiagnosticsPrinter diagPrinter(get_comm(), balanceSettings.get_num_output_processors()); - diagPrinter.print(sierra::Env::outputP0()); + diagPrinter.print(stk::outputP0()); } std::string mesh_desc_four_beams() { diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestLogFile.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestLogFile.cpp index a2151787dcec..3dbbf798ae04 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestLogFile.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestLogFile.cpp @@ -35,7 +35,7 @@ #include "stk_unit_test_utils/MeshFixture.hpp" #include "stk_balance/setup/LifeCycle.hpp" #include "stk_balance/setup/DefaultSettings.hpp" -#include "stk_util/environment/Env.hpp" +#include "stk_util/parallel/OutputStreams.hpp" #include #include #include @@ -97,8 +97,8 @@ TEST_F(TestLogFile, defaultLogFile) stk::balance::LifeCycle balance(get_comm(), args.size(), args.data()); const std::string expectedOutput{"This is a test\n"}; - sierra::Env::outputP0() << expectedOutput; - sierra::Env::outputP0().flush(); + stk::outputP0() << expectedOutput; + stk::outputP0().flush(); if (get_parallel_rank() == 0) { ASSERT_TRUE(test_file_exists(logFileName)); @@ -119,8 +119,8 @@ TEST_F(TestLogFile, customLogFile) stk::balance::LifeCycle balance(get_comm(), args.size(), args.data()); const std::string expectedOutput{"This is a test\n"}; - sierra::Env::outputP0() << expectedOutput; - sierra::Env::outputP0().flush(); + stk::outputP0() << expectedOutput; + stk::outputP0().flush(); if (get_parallel_rank() == 0) { ASSERT_TRUE(test_file_exists(customLogFileName)); @@ -142,8 +142,8 @@ TEST_F(TestLogFile, standardOutLog) const std::string expectedOutput{"This is a test\n"}; testing::internal::CaptureStdout(); - sierra::Env::outputP0() << expectedOutput; - sierra::Env::outputP0().flush(); + stk::outputP0() << expectedOutput; + stk::outputP0().flush(); std::string stdoutString = testing::internal::GetCapturedStdout(); if (get_parallel_rank() == 0) { @@ -163,8 +163,8 @@ TEST_F(TestLogFile, standardErrLog) const std::string expectedOutput{"This is a test\n"}; testing::internal::CaptureStderr(); - sierra::Env::outputP0() << expectedOutput; - sierra::Env::outputP0().flush(); + stk::outputP0() << expectedOutput; + stk::outputP0().flush(); std::string stderrString = testing::internal::GetCapturedStderr(); if (get_parallel_rank() == 0) { diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestM2NFileOutput.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestM2NFileOutput.cpp index 22853f16cf43..9d78bc7d3239 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestM2NFileOutput.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestM2NFileOutput.cpp @@ -33,7 +33,7 @@ // #include "MeshFixtureM2NRebalance.hpp" -#include +#include #include #include #include @@ -50,9 +50,9 @@ class M2NFileOutput : public MeshFixtureM2NRebalance stk::balance::M2NBalanceSettings balanceSettings(get_output_file_name(), numFinalProcs); balanceSettings.setDecompMethod("rcb"); - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + stk::set_outputP0(&stk::outputNull()); stk::balance::m2n::m2nRebalance(m_ioBroker, balanceSettings); - stk::EnvData::instance().m_outputP0 = &std::cout; + stk::reset_default_output_streams(); } }; diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestM2NLogFile.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestM2NLogFile.cpp index b32601ef1c24..29177e28fe23 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestM2NLogFile.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestM2NLogFile.cpp @@ -35,7 +35,7 @@ #include "stk_unit_test_utils/MeshFixture.hpp" #include "stk_balance/setup/DefaultSettings.hpp" #include -#include "stk_util/environment/Env.hpp" +#include "stk_util/parallel/OutputStreams.hpp" #include #include #include @@ -96,8 +96,8 @@ TEST_F(TestM2NLogFile, defaultLogFile) set_up_output_streams({}); const std::string expectedOutput{"This is a test\n"}; - sierra::Env::outputP0() << expectedOutput; - sierra::Env::outputP0().flush(); + stk::outputP0() << expectedOutput; + stk::outputP0().flush(); if (get_parallel_rank() == 0) { ASSERT_TRUE(test_file_exists(logFileName)); @@ -114,8 +114,8 @@ TEST_F(TestM2NLogFile, customLogFile) set_up_output_streams({"-l", logFileName.c_str()}); const std::string expectedOutput{"This is a test\n"}; - sierra::Env::outputP0() << expectedOutput; - sierra::Env::outputP0().flush(); + stk::outputP0() << expectedOutput; + stk::outputP0().flush(); if (get_parallel_rank() == 0) { ASSERT_TRUE(test_file_exists(logFileName)); @@ -133,8 +133,8 @@ TEST_F(TestM2NLogFile, standardOutLog) const std::string expectedOutput{"This is a test\n"}; testing::internal::CaptureStdout(); - sierra::Env::outputP0() << expectedOutput; - sierra::Env::outputP0().flush(); + stk::outputP0() << expectedOutput; + stk::outputP0().flush(); std::string stdoutString = testing::internal::GetCapturedStdout(); if (get_parallel_rank() == 0) { @@ -150,8 +150,8 @@ TEST_F(TestM2NLogFile, standardErrLog) const std::string expectedOutput{"This is a test\n"}; testing::internal::CaptureStderr(); - sierra::Env::outputP0() << expectedOutput; - sierra::Env::outputP0().flush(); + stk::outputP0() << expectedOutput; + stk::outputP0().flush(); std::string stderrString = testing::internal::GetCapturedStderr(); if (get_parallel_rank() == 0) { diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestM2NNestedDecomposition.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestM2NNestedDecomposition.cpp index c8366363c7d1..04407347fe9b 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestM2NNestedDecomposition.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestM2NNestedDecomposition.cpp @@ -203,9 +203,9 @@ class M2NDefaultRebalance : public MeshFixtureM2NRebalance stk::balance::M2NBalanceSettings balanceSettings(get_output_file_name(), numFinalProcs); balanceSettings.setDecompMethod("rcb"); - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + stk::set_outputP0(&stk::outputNull()); stk::balance::m2n::m2nRebalance(m_ioBroker, balanceSettings); - stk::EnvData::instance().m_outputP0 = &std::cout; + stk::reset_default_output_streams(); } }; @@ -248,9 +248,9 @@ class M2NNestedRebalance : public MeshFixtureM2NRebalance stk::balance::M2NBalanceSettings balanceSettings(get_output_file_name(), numFinalProcs, useNestedDecomp); balanceSettings.setDecompMethod("rcb"); - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + stk::set_outputP0(&stk::outputNull()); stk::balance::m2n::m2nRebalance(m_ioBroker, balanceSettings); - stk::EnvData::instance().m_outputP0 = &std::cout; + stk::reset_default_output_streams(); } }; diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestM2NRebalance.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestM2NRebalance.cpp index 807a35c729d2..da20e11d5997 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestM2NRebalance.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestM2NRebalance.cpp @@ -32,7 +32,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #include "MeshFixtureM2NRebalance.hpp" -#include +#include #include namespace { @@ -46,9 +46,9 @@ class M2NRebalance : public MeshFixtureM2NRebalance stk::balance::M2NBalanceSettings balanceSettings(get_output_file_name(), numFinalProcs); balanceSettings.setDecompMethod("rcb"); - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + stk::set_outputP0(&stk::outputNull()); stk::balance::m2n::m2nRebalance(m_ioBroker, balanceSettings); - stk::EnvData::instance().m_outputP0 = &std::cout; + stk::reset_default_output_streams(); stk::mesh::Part * block1 = m_ioBroker.meta_data().get_part("block_1"); ASSERT_NE(block1, nullptr); diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestM2NRebalanceTransientFieldData.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestM2NRebalanceTransientFieldData.cpp index 76f1778511bb..920574534b13 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestM2NRebalanceTransientFieldData.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestM2NRebalanceTransientFieldData.cpp @@ -32,7 +32,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #include "MeshFixtureM2NRebalance.hpp" -#include +#include #include namespace { @@ -46,9 +46,9 @@ class M2NRebalanceTransientFieldData : public MeshFixtureM2NRebalance stk::balance::M2NBalanceSettings balanceSettings(get_output_file_name(), numFinalProcs); balanceSettings.setDecompMethod("rcb"); - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + stk::set_outputP0(&stk::outputNull()); stk::balance::m2n::m2nRebalance(m_ioBroker, balanceSettings); - stk::EnvData::instance().m_outputP0 = &std::cout; + stk::reset_default_output_streams(); } }; diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestNestedDecomposer.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestNestedDecomposer.cpp index cd351281f574..6bbf36231fc5 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestNestedDecomposer.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestNestedDecomposer.cpp @@ -150,9 +150,9 @@ class NestedRebalance : public MeshFixtureRebalance m_balanceSettings.set_use_nested_decomp(useNestedDecomp); m_balanceSettings.setDecompMethod(decompMethod); - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + stk::set_outputP0(&stk::outputNull()); stk::balance::rebalance(m_ioBroker, m_balanceSettings); - stk::EnvData::instance().m_outputP0 = &std::cout; + stk::reset_default_output_streams(); } }; diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestRebalance.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestRebalance.cpp index 0114cd66c7d5..8ab1ea193f0e 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestRebalance.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestRebalance.cpp @@ -32,7 +32,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #include "MeshFixtureRebalance.hpp" -#include +#include #include #include @@ -49,9 +49,9 @@ class Rebalance : public MeshFixtureRebalance m_balanceSettings.set_num_output_processors(numFinalProcs); m_balanceSettings.setDecompMethod(decompMethod); - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + stk::set_outputP0(&stk::outputNull()); stk::balance::rebalance(m_ioBroker, m_balanceSettings); - stk::EnvData::instance().m_outputP0 = &std::cout; + stk::reset_default_output_streams(); stk::mesh::Part * block1 = m_ioBroker.meta_data().get_part("block_1"); ASSERT_NE(block1, nullptr); diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestRebalanceFileOutput.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestRebalanceFileOutput.cpp index 6a25bf740afb..29e85106f309 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestRebalanceFileOutput.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestRebalanceFileOutput.cpp @@ -33,7 +33,7 @@ // #include "MeshFixtureRebalance.hpp" -#include +#include #include #include #include @@ -53,9 +53,9 @@ class RebalanceFileOutput : public MeshFixtureRebalance m_balanceSettings.set_num_output_processors(numFinalProcs); m_balanceSettings.setDecompMethod(decompMethod); - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + stk::set_outputP0(&stk::outputNull()); stk::balance::rebalance(m_ioBroker, m_balanceSettings); - stk::EnvData::instance().m_outputP0 = &std::cout; + stk::reset_default_output_streams(); } }; diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestRebalanceSpiders.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestRebalanceSpiders.cpp index 436122f715b5..6129764b0303 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestRebalanceSpiders.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestRebalanceSpiders.cpp @@ -32,7 +32,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #include "MeshFixtureRebalance.hpp" -#include +#include #include #include #include @@ -75,9 +75,9 @@ class RebalanceSpiders : public MeshFixtureRebalance m_balanceSettings.set_num_output_processors(numFinalProcs); m_balanceSettings.setDecompMethod(decompMethod); - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + stk::set_outputP0(&stk::outputNull()); stk::balance::rebalance(m_ioBroker, m_balanceSettings); - stk::EnvData::instance().m_outputP0 = &std::cout; + stk::reset_default_output_streams(); } void check_spider_body_ownership(const stk::mesh::EntityKeyProcVec & spiderBody) diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestRebalanceTransientFieldData.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestRebalanceTransientFieldData.cpp index 1dd5f1d50fe8..64058cddafb2 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestRebalanceTransientFieldData.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestRebalanceTransientFieldData.cpp @@ -32,7 +32,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #include "MeshFixtureRebalance.hpp" -#include +#include #include #include @@ -49,9 +49,9 @@ class RebalanceTransientFieldData : public MeshFixtureRebalance m_balanceSettings.set_num_output_processors(numFinalProcs); m_balanceSettings.setDecompMethod(decompMethod); - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + stk::set_outputP0(&stk::outputNull()); stk::balance::rebalance(m_ioBroker, m_balanceSettings); - stk::EnvData::instance().m_outputP0 = &std::cout; + stk::reset_default_output_streams(); } }; diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestStkBalanceDecomposition.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestStkBalanceDecomposition.cpp index 0615411d0e62..bd492095fbd8 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestStkBalanceDecomposition.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestStkBalanceDecomposition.cpp @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include @@ -78,11 +78,11 @@ class StkBalanceDecomposition : public stk::unit_test_util::MeshFixture void balance_mesh(const std::vector & selectors) { stk::balance::GraphCreationSettings balanceSettings; - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + stk::set_outputP0(&stk::outputNull()); stk::balance::Balancer balancer(balanceSettings); stk::balance::BalanceMesh balanceMesh(get_bulk()); balancer.balance(balanceMesh, selectors); - stk::EnvData::instance().m_outputP0 = &std::cout; + stk::reset_default_output_streams(); } void test_mesh_element_distribution(const std::vector & expectedElemsPerProc) diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestStkBalancePartitioning.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestStkBalancePartitioning.cpp index 9bd58fc9ea03..91a6d67f5339 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestStkBalancePartitioning.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestStkBalancePartitioning.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include @@ -50,11 +50,11 @@ class StkBalancePartitioning : public stk::unit_test_util::MeshFixture stk::balance::BalanceSettings & balanceSettings) { m_numFinalSubdomains = numFinalSubdomains; - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + stk::set_outputP0(&stk::outputNull()); stk::balance::internal::calculateGeometricOrGraphBasedDecomp(get_bulk(), selectors, decompCommunicator, numFinalSubdomains, balanceSettings, m_decomp); - stk::EnvData::instance().m_outputP0 = &std::cout; + stk::reset_default_output_streams(); } diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestZoltanGraphGeneration.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestZoltanGraphGeneration.cpp index ed121961aaa5..c385d19df978 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestZoltanGraphGeneration.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestZoltanGraphGeneration.cpp @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include @@ -62,9 +62,9 @@ class ZoltanGraphGeneration : public stk::unit_test_util::MeshFixture void fill_zoltan_graph(const stk::mesh::Selector & selector, const stk::balance::BalanceSettings & balanceSettings) { - stk::EnvData::instance().m_outputP0 = &stk::EnvData::instance().m_outputNull; + stk::set_outputP0(&stk::outputNull()); stk::balance::internal::createZoltanParallelGraph(get_bulk(), selector, get_comm(), balanceSettings, m_graph); - stk::EnvData::instance().m_outputP0 = &std::cout; + stk::reset_default_output_streams(); } void fill_zoltan_graph_for_decomp(const stk::mesh::Selector & selector) diff --git a/packages/stk/stk_unit_tests/stk_coupling/UnitTestSplitComm.cpp b/packages/stk/stk_unit_tests/stk_coupling/UnitTestSplitComm.cpp index 7a4d6f7dfd8d..0dffd4dc887b 100644 --- a/packages/stk/stk_unit_tests/stk_coupling/UnitTestSplitComm.cpp +++ b/packages/stk/stk_unit_tests/stk_coupling/UnitTestSplitComm.cpp @@ -34,6 +34,7 @@ #include // for AssertHelper, ASSERT_TRUE, etc #include +#include #include #include #include @@ -153,6 +154,30 @@ TEST(UnitTestSplitComm, get_other_colors_3_colors) } } +TEST(UnitTestSplitComm, outputP0_3_colors) +{ + int numWorldProcs = stk::parallel_machine_size(MPI_COMM_WORLD); + if (numWorldProcs != 3) { GTEST_SKIP(); } + int myRank = stk::parallel_machine_rank(MPI_COMM_WORLD); + int myColor = myRank; + + stk::coupling::SplitComms splitComms(MPI_COMM_WORLD, myColor); + splitComms.set_free_comms_in_destructor(true); + EXPECT_EQ(myColor, splitComms.get_local_color()); + + MPI_Comm myComm = splitComms.get_split_comm(); + int myRankOnMyColor = stk::parallel_machine_rank(myComm); + EXPECT_EQ(0, myRankOnMyColor); + + std::ostringstream oss; + stk::set_outputP0(&oss, myComm); + std::string expected("expected output"); + stk::outputP0() << expected; + EXPECT_EQ(expected, oss.str()); + + stk::reset_default_output_streams(MPI_COMM_WORLD); +} + TEST(UnitTestSplitComm, split_comms_comm_world) { int myColor = stk::parallel_machine_rank(MPI_COMM_WORLD); diff --git a/packages/stk/stk_unit_tests/stk_mesh/TestElemElemGraphUtils.hpp b/packages/stk/stk_unit_tests/stk_mesh/TestElemElemGraphUtils.hpp new file mode 100644 index 000000000000..c953c3b65b37 --- /dev/null +++ b/packages/stk/stk_unit_tests/stk_mesh/TestElemElemGraphUtils.hpp @@ -0,0 +1,87 @@ +// Copyright 2002 - 2008, 2010, 2011 National Technology Engineering +// Solutions of Sandia, LLC (NTESS). Under the terms of Contract +// DE-NA0003525 with NTESS, the U.S. Government retains certain rights +// in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// * Neither the name of NTESS nor the names of its contributors +// may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef stk_unit_tests_elem_elem_graph_utils_hpp +#define stk_unit_tests_elem_elem_graph_utils_hpp + +#include "stk_mesh/baseImpl/elementGraph/ElemElemGraph.hpp" +#include "stk_mesh/base/ForEachEntity.hpp" + +namespace stk { +namespace unit_test { + +inline +void verify_no_graph_edges(const stk::mesh::BulkData& bulk) +{ + const stk::mesh::ElemElemGraph& eeGraph = bulk.get_face_adjacent_element_graph(); + stk::mesh::for_each_entity_run(bulk, stk::topology::ELEM_RANK, bulk.mesh_meta_data().locally_owned_part(), + [&eeGraph](const stk::mesh::BulkData& mesh, stk::mesh::Entity elem) { + stk::mesh::impl::LocalId elemLocalId = eeGraph.get_local_element_id(elem); + stk::mesh::GraphEdgesForElement graphEdges = eeGraph.get_edges_for_element(elemLocalId); + EXPECT_EQ(0u, graphEdges.size()); + }); +} + +inline +void verify_graph_edge_exists(const stk::mesh::ElemElemGraph& eeGraph, + stk::mesh::impl::LocalId elem1LocalId, + stk::mesh::impl::LocalId elem2LocalId) +{ + stk::mesh::GraphEdgesForElement graphEdges = eeGraph.get_edges_for_element(elem1LocalId); + bool foundIt = false; + for(const stk::mesh::GraphEdge& graphEdge : graphEdges) { + if (graphEdge.elem2() == elem2LocalId) { + foundIt = true; + break; + } + } + EXPECT_TRUE(foundIt); +} + +inline +void verify_graph_edge_between_elems(const stk::mesh::BulkData& bulk, + stk::mesh::Entity elem1, stk::mesh::Entity elem2) +{ + const stk::mesh::ElemElemGraph& eeGraph = bulk.get_face_adjacent_element_graph(); + stk::mesh::impl::LocalId elem1LocalId = eeGraph.get_local_element_id(elem1); + stk::mesh::impl::LocalId elem2LocalId = eeGraph.get_local_element_id(elem2); + + verify_graph_edge_exists(eeGraph, elem1LocalId, elem2LocalId); + verify_graph_edge_exists(eeGraph, elem2LocalId, elem1LocalId); +} + +} // namespace unit_test +} // namespace stk + +#endif diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestAura.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestAura.cpp index 2300b69b1895..0d998d4488ec 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestAura.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestAura.cpp @@ -36,7 +36,10 @@ #include #include // for BulkData #include +#include +#include #include +#include #include // for declare_element #include #include "mpi.h" // for MPI_COMM_WORLD, etc @@ -50,6 +53,7 @@ #include "stk_mesh/base/MeshBuilder.hpp" #include "stk_unit_test_utils/BuildMesh.hpp" #include "UnitTestTextMeshFixture.hpp" +#include "TestElemElemGraphUtils.hpp" namespace stk { namespace mesh { class Part; } } @@ -104,6 +108,54 @@ void expect_nodes_1_to_8_no_longer_valid_on_p1(const stk::mesh::BulkData& bulk) } } +TEST(BulkDataTest, cleanupAura_nominal) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD) != 2) { GTEST_SKIP(); } + + std::shared_ptr bulkPtr = build_mesh(MPI_COMM_WORLD, stk::mesh::BulkData::AUTO_AURA); + stk::mesh::BulkData& bulk = *bulkPtr; + stk::io::fill_mesh("generated:1x1x2|sideset:Z", bulk); + + bulk.modification_begin(); + stk::mesh::impl::AuraGhosting auraGhosting; + EXPECT_NO_THROW(auraGhosting.remove_aura(bulk)); + bulk.modification_end(); +} + +TEST(BulkDataTest, cleanupAura_deletedFaceOnOtherProc) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD) != 2) { GTEST_SKIP(); } + + std::shared_ptr bulkPtr = build_mesh(MPI_COMM_WORLD, stk::mesh::BulkData::AUTO_AURA); + stk::mesh::BulkData& bulk = *bulkPtr; + stk::io::fill_mesh("generated:1x1x2|sideset:Z", bulk); + + bulk.modification_begin(); + if (bulk.parallel_rank() == 0) { + stk::mesh::Entity elem2 = bulk.get_entity(stk::topology::ELEM_RANK, 2); + EXPECT_TRUE(bulk.is_valid(elem2)); + EXPECT_TRUE(bulk.bucket(elem2).in_aura()); + ASSERT_EQ(1u, bulk.num_connectivity(elem2, stk::topology::FACE_RANK)); + stk::mesh::Entity face = bulk.begin(elem2, stk::topology::FACE_RANK)[0]; + EXPECT_TRUE(bulk.bucket(face).in_aura()); + } + + if (bulk.parallel_rank() == 1) { + stk::mesh::Entity elem2 = bulk.get_entity(stk::topology::ELEM_RANK, 2); + EXPECT_TRUE(bulk.is_valid(elem2)); + ASSERT_EQ(1u, bulk.num_connectivity(elem2, stk::topology::FACE_RANK)); + stk::mesh::Entity face = bulk.begin(elem2, stk::topology::FACE_RANK)[0]; + stk::mesh::ConnectivityOrdinal faceOrd = bulk.begin_ordinals(elem2, stk::topology::FACE_RANK)[0]; + EXPECT_TRUE(bulk.bucket(face).owned()); + bulk.destroy_relation(elem2, face, faceOrd); + EXPECT_TRUE(bulk.destroy_entity(face)); + } + + stk::mesh::impl::AuraGhosting auraGhosting; + EXPECT_NO_THROW(auraGhosting.remove_aura(bulk)); + bulk.modification_end(); +} + TEST(BulkDataTest, destroyDependentGhostsConnectedToDeletedShared) { if (stk::parallel_machine_size(MPI_COMM_WORLD) != 2) { GTEST_SKIP(); } @@ -149,16 +201,18 @@ stk::mesh::Part& setupDavidNobleTestCaseTkt12837(stk::mesh::BulkData& bulk) stk::mesh::EntityId elemId3 = 3; // p2 stk::mesh::EntityId elemId4 = 4; // p1 - if(bulk.parallel_rank() == 0) + if(bulk.parallel_size()==1 || bulk.parallel_rank() == 0) { stk::mesh::declare_element(bulk, block_1, elemId1, elem1_nodes); stk::mesh::Entity node1 = bulk.get_entity(stk::topology::NODE_RANK, 1); stk::mesh::Entity node2 = bulk.get_entity(stk::topology::NODE_RANK, 2); - bulk.add_node_sharing(node1, 1); - bulk.add_node_sharing(node1, 2); - bulk.add_node_sharing(node2, 1); + if (bulk.parallel_size() == 3) { + bulk.add_node_sharing(node1, 1); + bulk.add_node_sharing(node1, 2); + bulk.add_node_sharing(node2, 1); + } } - else if(bulk.parallel_rank() == 1) + if(bulk.parallel_size()==1 || bulk.parallel_rank() == 1) { stk::mesh::declare_element(bulk, block_1, elemId2, elem2_nodes); stk::mesh::declare_element(bulk, block_1, elemId4, elem4_nodes); @@ -166,20 +220,24 @@ stk::mesh::Part& setupDavidNobleTestCaseTkt12837(stk::mesh::BulkData& bulk) stk::mesh::Entity node1 = bulk.get_entity(stk::topology::NODE_RANK, 1); stk::mesh::Entity node2 = bulk.get_entity(stk::topology::NODE_RANK, 2); stk::mesh::Entity node6 = bulk.get_entity(stk::topology::NODE_RANK, 6); - bulk.add_node_sharing(node1, 2); - bulk.add_node_sharing(node6, 2); + if (bulk.parallel_size() == 3) { + bulk.add_node_sharing(node1, 2); + bulk.add_node_sharing(node6, 2); - bulk.add_node_sharing(node1, 0); - bulk.add_node_sharing(node2, 0); + bulk.add_node_sharing(node1, 0); + bulk.add_node_sharing(node2, 0); + } } - else + if(bulk.parallel_size()==1 || bulk.parallel_rank() == 2) { stk::mesh::declare_element(bulk, block_1, elemId3, elem3_nodes); stk::mesh::Entity node1 = bulk.get_entity(stk::topology::NODE_RANK, 1); stk::mesh::Entity node6 = bulk.get_entity(stk::topology::NODE_RANK, 6); - bulk.add_node_sharing(node1, 0); - bulk.add_node_sharing(node1, 1); - bulk.add_node_sharing(node6, 1); + if (bulk.parallel_size() == 3) { + bulk.add_node_sharing(node1, 0); + bulk.add_node_sharing(node1, 1); + bulk.add_node_sharing(node6, 1); + } } bulk.modification_end(); @@ -369,6 +427,65 @@ TEST(BulkDataTest, removeElemPartWithNodeSharedWithOneProcAndAuraToAnotherProc) } } +TEST(BulkDataTest, disconnectReconnectElem_AddNewSharedSide_checkGraph) +{ + const int numProcs = stk::parallel_machine_size(MPI_COMM_WORLD); + if (numProcs != 1 && numProcs != 3) { GTEST_SKIP(); } + + std::shared_ptr bulkPtr = build_mesh(2, MPI_COMM_WORLD); + stk::mesh::BulkData& bulk = *bulkPtr; + + setupDavidNobleTestCaseTkt12837(bulk); + bulk.initialize_face_adjacent_element_graph(); + + stk::mesh::Entity elem1 = bulk.get_entity(stk::topology::ELEMENT_RANK, 1); + stk::mesh::Entity elem2 = bulk.get_entity(stk::topology::ELEMENT_RANK, 2); + stk::mesh::Entity elem4 = bulk.get_entity(stk::topology::ELEMENT_RANK, 4); + stk::mesh::Entity node1 = bulk.get_entity(stk::topology::NODE_RANK, 1); + + if (bulk.parallel_size()==1 || bulk.parallel_rank() == 1) { + stk::unit_test::verify_graph_edge_between_elems(bulk, elem2, elem4); + } + +{ +std::ostringstream os; +os<<"P"<(elem1, sideOrd); + } + + if(bulk.parallel_size()==1 || bulk.parallel_rank() == 1) + { + stk::mesh::ConnectivityOrdinal nodeOrd = 0; + bulk.destroy_relation(elem2, node1, nodeOrd); + bulk.declare_relation(elem2, node1, nodeOrd); + unsigned sideOrd = 0; + bulk.declare_element_side(elem2, sideOrd); + } + +{ +stk::parallel_machine_barrier(bulk.parallel()); +std::ostringstream os; +os<<"P"< // for BulkData +#include // for BulkData #include #include // for declare_element #include "stk_mesh/base/Bucket.hpp" // for Bucket @@ -161,7 +162,7 @@ class AuraToSharedToAura : public TestTextMeshAura2d const stk::mesh::MetaData& meta = get_meta(); stk::mesh::PartVector triParts = {&meta.get_topology_root_part(stk::topology::TRI_3_2D)}; - stk::mesh::EntityId elemId = 3; + const stk::mesh::EntityId elemId = 3; stk::mesh::EntityIdVector nodeIds = {1,2,4}; const int otherProc = 1 - get_bulk().parallel_rank(); @@ -201,6 +202,33 @@ class AuraToSharedToAura : public TestTextMeshAura2d EXPECT_TRUE(get_bulk().in_ghost(get_bulk().aura_ghosting(), node1)); EXPECT_FALSE(get_bulk().in_shared(node1)); EXPECT_TRUE(1 == get_bulk().parallel_owner_rank(node1)); + + const stk::mesh::ElemElemGraph& eeGraph = get_bulk().get_face_adjacent_element_graph(); + + stk::mesh::Entity elem3 = get_bulk().get_entity(stk::topology::ELEM_RANK, elemId); + ASSERT_TRUE(get_bulk().is_valid(elem3)); + + if (get_bulk().parallel_rank() == 0) { + EXPECT_TRUE(get_bulk().bucket(elem3).in_aura()); + constexpr bool requireValidId = false; + stk::mesh::impl::LocalId elem3LocalId = eeGraph.get_local_element_id(elem3, requireValidId); + EXPECT_EQ(stk::mesh::impl::INVALID_LOCAL_ID, elem3LocalId); + } + + if (get_bulk().parallel_rank() == 1) { + EXPECT_TRUE(get_bulk().bucket(elem3).owned()); + constexpr bool requireValidId = true; + stk::mesh::Entity elem2 = get_bulk().get_entity(stk::topology::ELEM_RANK, 2); + stk::mesh::impl::LocalId elem2LocalId = eeGraph.get_local_element_id(elem2, requireValidId); + stk::mesh::impl::LocalId elem3LocalId = eeGraph.get_local_element_id(elem3, requireValidId); + constexpr size_t numConnectedElems = 1; + EXPECT_EQ(numConnectedElems, eeGraph.get_num_connected_elems(elem3)); + stk::mesh::GraphEdgesForElement graphEdges = eeGraph.get_edges_for_element(elem3LocalId); + ASSERT_EQ(1u, graphEdges.size()); + const stk::mesh::GraphEdge& graphEdge = graphEdges[0]; + EXPECT_EQ(elem3LocalId, graphEdge.elem1()); + EXPECT_EQ(elem2LocalId, graphEdge.elem2()); + } } }; @@ -236,13 +264,6 @@ class Aura2DTri : public TestTextMeshAura2d EXPECT_TRUE(get_bulk().destroy_relation(elem2, node3, ord)); get_bulk().declare_relation(elem2, node6, ord); } -{ -stk::parallel_machine_barrier(get_bulk().parallel()); -std::ostringstream os; -os<<"P"< #include // for BucketRepository #include -#include #include #include #include diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestSidePolarity.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestSidePolarity.cpp index 0e1a02a40e06..e99175a302a6 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestSidePolarity.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestSidePolarity.cpp @@ -19,9 +19,6 @@ #include #include "stk_mesh/base/ExodusTranslator.hpp" -#include "stk_mesh/baseImpl/elementGraph/ElemElemGraph.hpp" -#include "stk_mesh/baseImpl/elementGraph/ElemElemGraphImpl.hpp" -#include "stk_mesh/baseImpl/elementGraph/GraphEdgeData.hpp" class TestTextMesh : public stk::unit_test_util::MeshFixture { diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestSideSet.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestSideSet.cpp index 3486f87b50b9..f6709e5c838d 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestSideSet.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestSideSet.cpp @@ -15,7 +15,7 @@ #include #include #include -#include "stk_mesh/baseImpl/elementGraph/ElemElemGraphImpl.hpp" +#include "TestElemElemGraphUtils.hpp" namespace { using stk::unit_test_util::build_mesh; @@ -1563,6 +1563,7 @@ TEST(DeclareElementSide, destroyElemAndReconnectElem_sidesBetweenTwoTriangles) //if the elem-elem-graph correctly knows that elements 1 and 4 share a //graph edge, then there should still be just 1 side between them. + stk::unit_test::verify_graph_edge_between_elems(*bulk, elem1, elem4); EXPECT_EQ(1u, stk::mesh::count_entities(*bulk, meta.side_rank(), meta.universal_part())); } @@ -1711,3 +1712,59 @@ TEST(Skinning, createAllSidesForBlock_separatePartForInteriorSides) EXPECT_EQ(4u, stk::mesh::count_entities(bulk, stk::topology::FACE_RANK, interiorSkin)); } +TEST(CreateAndConvert, read_write_shell_4_all_face_sides) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD) != 1) { GTEST_SKIP(); } + + std::shared_ptr bulk = stk::mesh::MeshBuilder(MPI_COMM_WORLD).set_spatial_dimension(3).create(); + + const std::string meshDesc = + "0,1,SHELL_QUAD_4, 1,2,3,4, block_1 \ + |sideset:name=surface_1; data=1,1, 1,2, 1,3, 1,4, 1,5, 1,6; split=topology"; + + std::vector coords = {0,0,0, 1,0,0, 1,1,0, 0,1,0}; + auto fullDesc = stk::unit_test_util::get_full_text_mesh_desc(meshDesc, coords); + stk::io::StkMeshIoBroker ioBroker; + ioBroker.set_enable_all_face_sides_shell_topo(true); + stk::io::fill_mesh("textmesh:" + fullDesc, *bulk, ioBroker); + + stk::mesh::EntityVector entities; + stk::mesh::get_entities(*bulk, stk::topology::ELEM_RANK, entities); + + for (auto entity : entities) { + EXPECT_EQ(4u, bulk->num_nodes(entity)) << bulk->entity_key(entity); + EXPECT_EQ(0u, bulk->num_edges(entity)) << bulk->entity_key(entity); + EXPECT_EQ(6u, bulk->num_faces(entity)) << bulk->entity_key(entity); + EXPECT_EQ(6u, bulk->num_sides(entity)) << bulk->entity_key(entity); + } + + EXPECT_EQ(0u, stk::mesh::count_selected_entities(bulk->mesh_meta_data().locally_owned_part(), bulk->buckets(stk::topology::EDGE_RANK))); + EXPECT_EQ(6u, stk::mesh::count_selected_entities(bulk->mesh_meta_data().locally_owned_part(), bulk->buckets(stk::topology::FACE_RANK))); + + std::string fileName("shell_quad4_all_face_sides_test.g"); + stk::io::write_mesh(fileName, ioBroker); + + std::shared_ptr newBulk = stk::mesh::MeshBuilder(MPI_COMM_WORLD).set_spatial_dimension(3).create(); + stk::io::StkMeshIoBroker newIoBroker; + newIoBroker.set_bulk_data(*newBulk); + size_t index = newIoBroker.add_mesh_database(fileName, stk::io::READ_MESH); + newIoBroker.set_active_mesh(index); + newIoBroker.set_enable_all_face_sides_shell_topo(true); + newIoBroker.create_input_mesh(); + newIoBroker.populate_bulk_data(); + + ASSERT_EQ(newIoBroker.bulk_data_ptr().get(), newBulk.get()); + + stk::mesh::get_entities(*newBulk, stk::topology::ELEM_RANK, entities); + for (auto entity : entities) { + EXPECT_EQ(4u, newBulk->num_nodes(entity)) << newBulk->entity_key(entity); + EXPECT_EQ(0u, newBulk->num_edges(entity)) << newBulk->entity_key(entity); + EXPECT_EQ(6u, newBulk->num_faces(entity)) << newBulk->entity_key(entity); + EXPECT_EQ(6u, newBulk->num_sides(entity)) << newBulk->entity_key(entity); + } + + EXPECT_EQ(0u, stk::mesh::count_selected_entities(newBulk->mesh_meta_data().locally_owned_part(), newBulk->buckets(stk::topology::EDGE_RANK))); + EXPECT_EQ(6u, stk::mesh::count_selected_entities(newBulk->mesh_meta_data().locally_owned_part(), newBulk->buckets(stk::topology::FACE_RANK))); + + unlink(fileName.c_str()); +} diff --git a/packages/stk/stk_unit_tests/stk_mesh/face_creation/TwoHexesTwoProcsEGWithPermutations.cpp b/packages/stk/stk_unit_tests/stk_mesh/face_creation/TwoHexesTwoProcsEGWithPermutations.cpp index ff354592d13f..b86ec6886149 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/face_creation/TwoHexesTwoProcsEGWithPermutations.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/face_creation/TwoHexesTwoProcsEGWithPermutations.cpp @@ -4,7 +4,6 @@ #include #include #include "FaceCreatorFixture.hpp" -#include namespace { diff --git a/packages/stk/stk_unit_tests/stk_mesh/face_creation/TwoHexesTwoProcsElemGraph.cpp b/packages/stk/stk_unit_tests/stk_mesh/face_creation/TwoHexesTwoProcsElemGraph.cpp index d8fbff50449a..a356534fc105 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/face_creation/TwoHexesTwoProcsElemGraph.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/face_creation/TwoHexesTwoProcsElemGraph.cpp @@ -4,7 +4,6 @@ #include #include #include "FaceCreatorFixture.hpp" -#include namespace { diff --git a/packages/stk/stk_unit_tests/stk_mesh/face_creation/skin_mesh/UnitTestSkinMeshCoincidentElements.cpp b/packages/stk/stk_unit_tests/stk_mesh/face_creation/skin_mesh/UnitTestSkinMeshCoincidentElements.cpp index 9859095f4384..29bd6a4c1df6 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/face_creation/skin_mesh/UnitTestSkinMeshCoincidentElements.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/face_creation/skin_mesh/UnitTestSkinMeshCoincidentElements.cpp @@ -27,8 +27,6 @@ int get_other_proc(MPI_Comm comm) return stk::parallel_machine_size(comm) - stk::parallel_machine_rank(comm) - 1; } -// void create_exposed_boundary_sides(BulkData &bulkData, const Selector& blocksToSkin, Part& partToPutSidesInto) - class CoincidentElements: public stk::unit_test_util::MeshTestFixture { protected: @@ -58,8 +56,11 @@ class CoincidentElements: public stk::unit_test_util::MeshTestFixture } void make_nodes_shared(const stk::mesh::EntityIdVector &nodes) { - for(const stk::mesh::EntityId nodeId : nodes) - get_bulk().add_node_sharing(get_bulk().get_entity(stk::topology::NODE_RANK, nodeId), get_other_proc(get_comm())); + if (get_bulk().parallel_size() > 1) { + for(const stk::mesh::EntityId nodeId : nodes) { + get_bulk().add_node_sharing(get_bulk().get_entity(stk::topology::NODE_RANK, nodeId), get_other_proc(get_comm())); + } + } } private: bool is_element_created_on_this_proc(int elementIndex) diff --git a/packages/stk/stk_unit_tests/stk_mesh/ngp/NgpMeshTest.cpp b/packages/stk/stk_unit_tests/stk_mesh/ngp/NgpMeshTest.cpp index 4266734f1e94..b95d67c4c016 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/ngp/NgpMeshTest.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/ngp/NgpMeshTest.cpp @@ -54,6 +54,8 @@ #include +using NgpMeshDefaultMemSpace = stk::mesh::NgpMeshDefaultMemSpace; + class NgpMeshTest : public stk::mesh::fixtures::TestHexFixture { public: @@ -74,12 +76,37 @@ class NgpMeshTest : public stk::mesh::fixtures::TestHexFixture numNodesVec.copy_device_to_host(); ASSERT_EQ(8u, numNodesVec[0]); } + + template + void run_get_nodes_using_FastMeshIndex_test() + { + setup_mesh(1, 1, 4); + + stk::NgpVector numNodesVec("numNodes", 1); + + stk::mesh::NgpMeshT & ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); + Kokkos::parallel_for(stk::ngp::DeviceRangePolicy(0, 1), + KOKKOS_LAMBDA(const int i) + { + stk::mesh::NgpMesh::ConnectedNodes nodes = ngpMesh.get_nodes(stk::topology::ELEM_RANK, stk::mesh::FastMeshIndex{0,0}); + numNodesVec.device_get(0) = nodes.size(); + }); + + numNodesVec.copy_device_to_host(); + ASSERT_EQ(8u, numNodesVec[0]); + } }; + TEST_F(NgpMeshTest, get_nodes_using_FastMeshIndex) { run_get_nodes_using_FastMeshIndex_test(); } +TEST_F(NgpMeshTest, get_nodes_using_FastMeshIndex_custom_NgpMemSpace) +{ + run_get_nodes_using_FastMeshIndex_test(); +} + class NgpMeshRankLimit : public stk::mesh::fixtures::TestHexFixture {}; TEST_F(NgpMeshRankLimit, tooManyRanksThrowWithMessage) @@ -97,6 +124,21 @@ TEST_F(NgpMeshRankLimit, tooManyRanksThrowWithMessage) } } +TEST_F(NgpMeshRankLimit, tooManyRanksThrowWithMessage_custom_NgpMemSpace) +{ + setup_mesh(1,1,1, {"NODE","EDGE","FACE","ELEM","CONSTRAINT","JULIA"}); + + try { + stk::mesh::get_updated_ngp_mesh(get_bulk()); + FAIL()<< "expected throw but didn't throw"; + } + catch(std::exception& e) { + std::string expectedMsg("stk::mesh::NgpMesh: too many entity ranks (6). Required to be less-or-equal stk::topology::NUM_RANKS"); + std::string msg(e.what()); + EXPECT_TRUE((msg.find(expectedMsg) != std::string::npos)); + } +} + class EntityIndexSpace : public stk::mesh::fixtures::TestHexFixture {}; TEST_F(EntityIndexSpace, accessingLocalData_useLocalOffset) @@ -168,8 +210,6 @@ void check_volatile_fast_shared_comm_map_values_on_device(const stk::mesh::NgpMe } } -using HostCommMapIndices = Kokkos::View; - NGP_TEST_F(NgpMeshTest, volatileFastSharedCommMap) { if (stk::parallel_machine_size(MPI_COMM_WORLD) == 1) { GTEST_SKIP(); } @@ -180,7 +220,25 @@ NGP_TEST_F(NgpMeshTest, volatileFastSharedCommMap) std::vector comm_procs = get_bulk().all_sharing_procs(stk::topology::NODE_RANK); for (int proc : comm_procs) { - stk::mesh::DeviceCommMapIndices::HostMirror hostNgpMeshIndices = get_bulk().volatile_fast_shared_comm_map(stk::topology::NODE_RANK, proc); + stk::mesh::HostCommMapIndices hostNgpMeshIndices = get_bulk().volatile_fast_shared_comm_map(stk::topology::NODE_RANK, proc); + stk::mesh::DeviceCommMapIndices deviceNgpMeshIndices("deviceNgpMeshIndices", hostNgpMeshIndices.extent(0)); + + Kokkos::deep_copy(deviceNgpMeshIndices, hostNgpMeshIndices); + check_volatile_fast_shared_comm_map_values_on_device(ngpMesh, proc, deviceNgpMeshIndices); + } +} + +NGP_TEST_F(NgpMeshTest, volatileFastSharedCommMap_custom_NgpMemSpace) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD) == 1) { GTEST_SKIP(); } + + setup_mesh(1, 1, 4); + + stk::mesh::NgpMeshT & ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); + std::vector comm_procs = get_bulk().all_sharing_procs(stk::topology::NODE_RANK); + + for (int proc : comm_procs) { + stk::mesh::HostCommMapIndices hostNgpMeshIndices = get_bulk().volatile_fast_shared_comm_map(stk::topology::NODE_RANK, proc); stk::mesh::DeviceCommMapIndices deviceNgpMeshIndices("deviceNgpMeshIndices", hostNgpMeshIndices.extent(0)); Kokkos::deep_copy(deviceNgpMeshIndices, hostNgpMeshIndices); diff --git a/packages/stk/stk_unit_tests/stk_mesh/ngp/TestNgpMeshUpdate.cpp b/packages/stk/stk_unit_tests/stk_mesh/ngp/TestNgpMeshUpdate.cpp index f0f9eb33e4a4..2dd63a22b895 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/ngp/TestNgpMeshUpdate.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/ngp/TestNgpMeshUpdate.cpp @@ -12,6 +12,8 @@ namespace { +using NgpMeshDefaultMemSpace = stk::mesh::NgpMeshDefaultMemSpace; + class UpdateNgpMesh : public stk::unit_test_util::MeshFixture { public: @@ -42,6 +44,23 @@ TEST_F(UpdateNgpMesh, explicitUpdate) EXPECT_TRUE(ngpMesh->is_up_to_date()); } +TEST_F(UpdateNgpMesh, explicitUpdate_custom_NgpMemSpace) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD) > 1) { GTEST_SKIP(); } + setup_test_mesh(); + + stk::mesh::NgpMeshT * ngpMesh = &stk::mesh::get_updated_ngp_mesh(get_bulk()); + + get_bulk().modification_begin(); + stk::mesh::Entity node1 = get_bulk().get_entity(stk::topology::NODE_RANK, 1); + get_bulk().change_entity_parts(node1, stk::mesh::ConstPartVector{extraPart}); + get_bulk().modification_end(); + + EXPECT_FALSE(ngpMesh->is_up_to_date()); + ngpMesh = &stk::mesh::get_updated_ngp_mesh(get_bulk()); + EXPECT_TRUE(ngpMesh->is_up_to_date()); +} + TEST_F(UpdateNgpMesh, referenceGetsUpdated) { if (stk::parallel_machine_size(MPI_COMM_WORLD) > 1) { GTEST_SKIP(); } @@ -61,6 +80,25 @@ TEST_F(UpdateNgpMesh, referenceGetsUpdated) EXPECT_TRUE(ngpMesh.is_up_to_date()); } +TEST_F(UpdateNgpMesh, referenceGetsUpdated_custom_NgpMemSpace) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD) > 1) { GTEST_SKIP(); } + setup_test_mesh(); + + // If storing a persistent reference, call the get_updated_ngp_mesh() function + // to ensure that it is synchronized with BulkData + stk::mesh::NgpMeshT & ngpMesh = stk::mesh::get_updated_ngp_mesh(get_bulk()); + + get_bulk().modification_begin(); + stk::mesh::Entity node1 = get_bulk().get_entity(stk::topology::NODE_RANK, 1); + get_bulk().change_entity_parts(node1, stk::mesh::ConstPartVector{extraPart}); + get_bulk().modification_end(); + + EXPECT_FALSE(ngpMesh.is_up_to_date()); + stk::mesh::get_updated_ngp_mesh(get_bulk()); // Trigger update + EXPECT_TRUE(ngpMesh.is_up_to_date()); +} + TEST_F(UpdateNgpMesh, OnlyOneDeviceMesh_InternalAndExternal) { setup_test_mesh(); @@ -75,6 +113,20 @@ TEST_F(UpdateNgpMesh, OnlyOneDeviceMesh_InternalAndExternal) #endif } +TEST_F(UpdateNgpMesh, OnlyOneDeviceMesh_InternalAndExternal_custom_NgpMemSpace) +{ + setup_test_mesh(); + + // Create first NgpMesh inside BulkData + stk::mesh::get_updated_ngp_mesh(get_bulk()); + +#ifdef STK_USE_DEVICE_MESH + EXPECT_THROW(stk::mesh::NgpMeshT secondNgpMesh(get_bulk()), std::logic_error); +#else + EXPECT_NO_THROW(stk::mesh::NgpMeshT secondNgpMesh(get_bulk())); +#endif +} + TEST_F(UpdateNgpMesh, OnlyOneDeviceMesh_TwoExternal) { setup_test_mesh(); @@ -88,6 +140,19 @@ TEST_F(UpdateNgpMesh, OnlyOneDeviceMesh_TwoExternal) #endif } +TEST_F(UpdateNgpMesh, OnlyOneDeviceMesh_TwoExternal_custom_NgpMemSpace) +{ + setup_test_mesh(); + + stk::mesh::NgpMeshT firstNgpMesh(get_bulk()); + +#ifdef STK_USE_DEVICE_MESH + EXPECT_THROW(stk::mesh::NgpMeshT secondNgpMesh(get_bulk()), std::logic_error); +#else + EXPECT_NO_THROW(stk::mesh::NgpMeshT secondNgpMesh(get_bulk())); +#endif +} + class BucketLayoutModification : public stk::unit_test_util::MeshFixture { public: diff --git a/packages/stk/stk_unit_tests/stk_mesh/ngp/ngpFieldBLASTest.cpp b/packages/stk/stk_unit_tests/stk_mesh/ngp/ngpFieldBLASTest.cpp index c257449706fa..29fba1dca5a5 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/ngp/ngpFieldBLASTest.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/ngp/ngpFieldBLASTest.cpp @@ -1337,6 +1337,117 @@ TEST_F(NgpFieldBLASNode, field_swap_no_selector) #endif +#ifdef STK_USE_DEVICE_MESH + +TEST_F(NgpFieldBLASNode, field_amax_device) +{ + if (get_parallel_size() > 2) GTEST_SKIP(); + + stk::mesh::Selector selectRule(*stkField1); + ngp_field_test_utils::set_field_data_on_host(get_bulk(), *stkField1, selectRule, &func1); + stkField1->sync_to_device(); + + double hostAMaxVal = 0.0; + + stk::mesh::EntityVector nodes; + get_bulk().get_entities(stk::topology::NODE_RANK, selectRule, nodes); + for (auto& n : nodes) { + double* myVal = static_cast(stk::mesh::field_data(*stkField1, n)); + const int numComponents = stk::mesh::field_scalars_per_entity(*stkField1, n); + for (int i = 0; i < numComponents; ++i) { + hostAMaxVal = std::max(hostAMaxVal, myVal[i]); + } + } + + double globalHostMax = hostAMaxVal; + stk::all_reduce_max(get_bulk().parallel(), &hostAMaxVal, &globalHostMax, 1u); + + double devAmaxVal = 0.0; + stk::mesh::field_amax(devAmaxVal, *stkField1, selectRule, stk::ngp::ExecSpace()); + + EXPECT_EQ(globalHostMax, devAmaxVal); +} + +TEST_F(NgpFieldBLASNode, field_amax_host) +{ + if (get_parallel_size() > 2) GTEST_SKIP(); + + stk::mesh::Selector selectRule(*stkField1); + ngp_field_test_utils::set_field_data_on_host(get_bulk(), *stkField1, selectRule, &func1); + + double hostAMaxVal = 0.0; + + stk::mesh::EntityVector nodes; + get_bulk().get_entities(stk::topology::NODE_RANK, selectRule, nodes); + for (auto& n : nodes) { + double* myVal = static_cast(stk::mesh::field_data(*stkField1, n)); + const int numComponents = stk::mesh::field_scalars_per_entity(*stkField1, n); + for (int i = 0; i < numComponents; ++i) { + hostAMaxVal = std::max(hostAMaxVal, myVal[i]); + } + } + + double globalHostMax = hostAMaxVal; + stk::all_reduce_max(get_bulk().parallel(), &hostAMaxVal, &globalHostMax, 1u); + + double devAmaxVal = 0.0; + stk::mesh::field_amax(devAmaxVal, *stkField1, selectRule, stk::ngp::HostExecSpace()); + + EXPECT_EQ(globalHostMax, devAmaxVal); +} +#else + +TEST_F(NgpFieldBLASNode, field_amax_exec_space) +{ + if (get_parallel_size() != 1) GTEST_SKIP(); + + stk::mesh::Selector selectRule(*stkField1); + ngp_field_test_utils::set_field_data_on_host(get_bulk(), *stkField1, selectRule, &func1); + + double hostAMaxVal = 0.0; + + stk::mesh::EntityVector nodes; + get_bulk().get_entities(stk::topology::NODE_RANK, selectRule, nodes); + for (auto& n : nodes) { + double* myVal = static_cast(stk::mesh::field_data(*stkField1, n)); + const int numComponents = stk::mesh::field_scalars_per_entity(*stkField1, n); + for (int i = 0; i < numComponents; ++i) { + hostAMaxVal = std::max(hostAMaxVal, myVal[i]); + } + } + + double devAmaxVal = 0.0; + stk::mesh::field_amax(devAmaxVal, *stkField1, selectRule, stk::ngp::ExecSpace()); + + EXPECT_EQ(hostAMaxVal, devAmaxVal); +} + +TEST_F(NgpFieldBLASNode, field_amax_no_selector) +{ + if (get_parallel_size() != 1) GTEST_SKIP(); + + stk::mesh::Selector selectRule(*stkField1); + ngp_field_test_utils::set_field_data_on_host(get_bulk(), *stkField1, selectRule, &func1); + + double hostAMaxVal = 0.0; + + stk::mesh::EntityVector nodes; + get_bulk().get_entities(stk::topology::NODE_RANK, selectRule, nodes); + for (auto& n : nodes) { + double* myVal = static_cast(stk::mesh::field_data(*stkField1, n)); + const int numComponents = stk::mesh::field_scalars_per_entity(*stkField1, n); + for (int i = 0; i < numComponents; ++i) { + hostAMaxVal = std::max(hostAMaxVal, myVal[i]); + } + } + + double devAmaxVal = 0.0; + stk::mesh::field_amax(devAmaxVal, *stkField1, stk::ngp::ExecSpace()); + + EXPECT_EQ(hostAMaxVal, devAmaxVal); +} + +#endif } diff --git a/packages/stk/stk_unit_tests/stk_search/UnitTestCoarseSearch.cpp b/packages/stk/stk_unit_tests/stk_search/UnitTestCoarseSearch.cpp index bca87004fe8a..79f8e9d121de 100644 --- a/packages/stk/stk_unit_tests/stk_search/UnitTestCoarseSearch.cpp +++ b/packages/stk/stk_unit_tests/stk_search/UnitTestCoarseSearch.cpp @@ -694,14 +694,18 @@ void test_ident_proc_with_search_with_views(stk::search::SearchMethod searchMeth IdentProc id1(1, 0); IdentProc id2(1, 1); - BoxIdentProcViewType boxes("", 1); + BoxIdentProcViewType boxes("boxes", 1); + auto hostBoxes = Kokkos::create_mirror_view(boxes); + if (procId == 0) { - boxes(0) = {box1, id1}; + hostBoxes(0) = {box1, id1}; } else if (procId == 1) { - boxes(0) = {box2, id2}; + hostBoxes(0) = {box2, id2}; } - SearchResultsViewType searchResults("", 3); + Kokkos::deep_copy(boxes, hostBoxes); + + SearchResultsViewType searchResults("searchResults", 3); auto execSpace = ExecSpace{}; bool enforceSearchResultSymmetry = true; @@ -710,7 +714,10 @@ void test_ident_proc_with_search_with_views(stk::search::SearchMethod searchMeth coarse_search(boxes, boxes, searchMethod, comm, searchResults, execSpace, enforceSearchResultSymmetry, autoSwapDomainAndRange, sortSearchResults); - SearchResultsViewType goldResults("", 3); + auto hostSearchResults = Kokkos::create_mirror_view(searchResults); + Kokkos::deep_copy(hostSearchResults, searchResults); + + SearchResultsViewType::HostMirror goldResults("goldResults", 3); IdentProc goldId1(1, 0); IdentProc goldId2(1, 1); @@ -730,7 +737,7 @@ void test_ident_proc_with_search_with_views(stk::search::SearchMethod searchMeth Kokkos::sort(goldResults, stk::search::Comparator()); for (size_t i = 0; i < goldResults.extent(0); i++) { - EXPECT_EQ(goldResults[i], searchResults[i]) + EXPECT_EQ(goldResults[i], hostSearchResults[i]) << "Test comparison for proc " << procId << " failed for comparsion #" << i << std::endl; } } diff --git a/packages/stk/stk_unit_tests/stk_search/UnitTestCoarseSearchTwoBox.cpp b/packages/stk/stk_unit_tests/stk_search/UnitTestCoarseSearchTwoBox.cpp index cc8a6635672e..25ced2655de8 100644 --- a/packages/stk/stk_unit_tests/stk_search/UnitTestCoarseSearchTwoBox.cpp +++ b/packages/stk/stk_unit_tests/stk_search/UnitTestCoarseSearchTwoBox.cpp @@ -291,8 +291,8 @@ void device_local_runTwoBoxTest(stk::search::SearchMethod searchMethod, const do ASSERT_EQ(intersections.extent(0), expectedNumOverlap); for (unsigned i = 0; i < expectedNumOverlap; ++i) { - EXPECT_EQ(intersections(i).domainIdent, 1); - EXPECT_EQ(intersections(i).rangeIdent, 2); + EXPECT_EQ(hostIntersections(i).domainIdent, 1); + EXPECT_EQ(hostIntersections(i).rangeIdent, 2); } } diff --git a/packages/stk/stk_unit_tests/stk_search/UnitTestCoarseSearchTwoSpheres.cpp b/packages/stk/stk_unit_tests/stk_search/UnitTestCoarseSearchTwoSpheres.cpp index cd3431a63ccd..0ee81aab8b1c 100644 --- a/packages/stk/stk_unit_tests/stk_search/UnitTestCoarseSearchTwoSpheres.cpp +++ b/packages/stk/stk_unit_tests/stk_search/UnitTestCoarseSearchTwoSpheres.cpp @@ -294,8 +294,8 @@ void device_local_runTwoSpheresTest(stk::search::SearchMethod searchMethod, cons ASSERT_EQ(intersections.extent(0), expectedNumOverlap); for (unsigned i = 0; i < expectedNumOverlap; ++i) { - EXPECT_EQ(intersections(i).domainIdent, 1); - EXPECT_EQ(intersections(i).rangeIdent, 2); + EXPECT_EQ(hostIntersections(i).domainIdent, 1); + EXPECT_EQ(hostIntersections(i).rangeIdent, 2); } } diff --git a/packages/stk/stk_unit_tests/stk_search/UnitTestDeviceMPIUtils.cpp b/packages/stk/stk_unit_tests/stk_search/UnitTestDeviceMPIUtils.cpp index 97d804b6107e..b5333dfdc3b7 100644 --- a/packages/stk/stk_unit_tests/stk_search/UnitTestDeviceMPIUtils.cpp +++ b/packages/stk/stk_unit_tests/stk_search/UnitTestDeviceMPIUtils.cpp @@ -62,7 +62,7 @@ void test_device_buffers_set_data() Kokkos::parallel_for("set_buffer_vals", policy, setFunc); - auto buffersHost = Kokkos::create_mirror_view_and_copy(ExecutionSpace{}, buffers.buffers); + auto buffersHost = Kokkos::create_mirror_view_and_copy(Kokkos::DefaultHostExecutionSpace{}, buffers.buffers); for (int i=0; i < totalSize; ++i) { EXPECT_EQ(buffersHost(i), i); @@ -315,4 +315,4 @@ TEST(DeviceDataExchangeUnknownPattern, AllToAllSkipSender) TEST(DeviceDataExchangeUnknownPattern, AllToAllSkipReceiver) { test_device_data_exchange_all_to_all_skip_receiver(4, 0); -} \ No newline at end of file +} diff --git a/packages/stk/stk_unit_tests/stk_search/UnitTestParallelConsistencyUtils.cpp b/packages/stk/stk_unit_tests/stk_search/UnitTestParallelConsistencyUtils.cpp index b8060bf2a823..776f6e5d540a 100644 --- a/packages/stk/stk_unit_tests/stk_search/UnitTestParallelConsistencyUtils.cpp +++ b/packages/stk/stk_unit_tests/stk_search/UnitTestParallelConsistencyUtils.cpp @@ -27,14 +27,16 @@ TEST(ParallelConsistencyUtils, ProcBoundingBoxView1Proc) int myrank = stk::parallel_machine_rank(stk::parallel_machine_world()); Kokkos::View boxIdentProcs("box_ident_procs", 2); + auto boxIdentProcsHost = Kokkos::create_mirror_view(boxIdentProcs); double delta = 0.5; double x0 = delta * myrank; - boxIdentProcs(0) = BoxIdentProcType{BoxType(x0, 0, 0, x0 + delta, delta, delta), IdentProcType(0, myrank)}; - boxIdentProcs(1) = BoxIdentProcType{BoxType(x0, delta, 0, x0 + delta, 2*delta, delta), IdentProcType(1, myrank)}; + boxIdentProcsHost(0) = BoxIdentProcType{BoxType(x0, 0, 0, x0 + delta, delta, delta), IdentProcType(0, myrank)}; + boxIdentProcsHost(1) = BoxIdentProcType{BoxType(x0, delta, 0, x0 + delta, 2*delta, delta), IdentProcType(1, myrank)}; + Kokkos::deep_copy(boxIdentProcs, boxIdentProcsHost); Kokkos::View procBoxes = stk::search::gather_all_processor_superset_domain_boxes(boxIdentProcs, execSpace, stk::parallel_machine_world()); - auto procBoxesHost = Kokkos::create_mirror_view_and_copy(execSpace, procBoxes); + auto procBoxesHost = Kokkos::create_mirror_view_and_copy(Kokkos::DefaultHostExecutionSpace{}, procBoxes); EXPECT_EQ(procBoxesHost.extent(0), 1u); EXPECT_EQ(procBoxesHost(0), BoxType(0, 0, 0, delta, 2*delta, delta)); @@ -54,12 +56,14 @@ TEST(ParallelConsistencyUtils, ProcBoundingBoxView1ProcSphere) int myrank = stk::parallel_machine_rank(stk::parallel_machine_world()); Kokkos::View boxIdentProcs("box_ident_procs", 2); - boxIdentProcs(0) = BoxIdentProcType{BoxType({0, 0, 0}, 1), IdentProcType(0, myrank)}; - boxIdentProcs(1) = BoxIdentProcType{BoxType({1, 0, 0}, 1), IdentProcType(1, myrank)}; + auto boxIdentProcsHost = Kokkos::create_mirror_view(boxIdentProcs); + boxIdentProcsHost(0) = BoxIdentProcType{BoxType({0, 0, 0}, 1), IdentProcType(0, myrank)}; + boxIdentProcsHost(1) = BoxIdentProcType{BoxType({1, 0, 0}, 1), IdentProcType(1, myrank)}; + Kokkos::deep_copy(boxIdentProcs, boxIdentProcsHost); Kokkos::View*, ExecutionSpace> procBoxes = stk::search::gather_all_processor_superset_domain_boxes(boxIdentProcs, execSpace, stk::parallel_machine_world()); - auto procBoxesHost = Kokkos::create_mirror_view_and_copy(execSpace, procBoxes); + auto procBoxesHost = Kokkos::create_mirror_view_and_copy(Kokkos::DefaultHostExecutionSpace{}, procBoxes); EXPECT_EQ(procBoxesHost.extent(0), 1u); EXPECT_EQ(procBoxesHost(0), stk::search::Box(-1, -1, -1, 2, 1, 1)); @@ -76,14 +80,16 @@ TEST(ParallelConsistencyUtils, ProcBoundingBoxView2Proc) int myrank = stk::parallel_machine_rank(stk::parallel_machine_world()); Kokkos::View boxIdentProcs("box_ident_procs", 2); + auto boxIdentProcsHost = Kokkos::create_mirror_view(boxIdentProcs); double delta = 0.5; double x0 = delta * myrank; - boxIdentProcs(0) = BoxIdentProcType{BoxType(x0, 0, 0, x0 + delta, delta, delta), IdentProcType(0, myrank)}; - boxIdentProcs(1) = BoxIdentProcType{BoxType(x0, delta, 0, x0 + delta, 2*delta, delta), IdentProcType(1, myrank)}; + boxIdentProcsHost(0) = BoxIdentProcType{BoxType(x0, 0, 0, x0 + delta, delta, delta), IdentProcType(0, myrank)}; + boxIdentProcsHost(1) = BoxIdentProcType{BoxType(x0, delta, 0, x0 + delta, 2*delta, delta), IdentProcType(1, myrank)}; + Kokkos::deep_copy(boxIdentProcs, boxIdentProcsHost); Kokkos::View procBoxes = stk::search::gather_all_processor_superset_domain_boxes(boxIdentProcs, execSpace, stk::parallel_machine_world()); - auto procBoxesHost = Kokkos::create_mirror_view_and_copy(execSpace, procBoxes); + auto procBoxesHost = Kokkos::create_mirror_view_and_copy(Kokkos::DefaultHostExecutionSpace{}, procBoxes); EXPECT_EQ(procBoxesHost.extent(0), 2u); EXPECT_EQ(procBoxesHost(0), BoxType(0, 0, 0, delta, 2*delta, delta)); @@ -103,15 +109,17 @@ TEST(ParallelConsistencyUtils, ProcBoundingBoxView4Proc) int i = myrank % 2; int j = myrank / 2; Kokkos::View boxIdentProcs("box_ident_procs", 1); + auto hostBoxIdentProcs = Kokkos::create_mirror_view(boxIdentProcs); double delta = 0.5; double x0 = delta * i; double y0 = delta * j; - boxIdentProcs(0) = BoxIdentProcType{BoxType(x0, y0, 0, x0 + delta, y0 + delta, delta), IdentProcType(0, myrank)}; + hostBoxIdentProcs(0) = BoxIdentProcType{BoxType(x0, y0, 0, x0 + delta, y0 + delta, delta), IdentProcType(0, myrank)}; + Kokkos::deep_copy(boxIdentProcs, hostBoxIdentProcs); Kokkos::View procBoxes = stk::search::gather_all_processor_superset_domain_boxes(boxIdentProcs, execSpace, stk::parallel_machine_world()); - auto procBoxesHost = Kokkos::create_mirror_view_and_copy(execSpace, procBoxes); + auto procBoxesHost = Kokkos::create_mirror_view_and_copy(Kokkos::DefaultHostExecutionSpace{}, procBoxes); EXPECT_EQ(procBoxesHost.extent(0), 4u); EXPECT_EQ(procBoxesHost(0), BoxType(0, 0, 0, delta, delta, delta)); diff --git a/packages/stk/stk_unit_tests/stk_topology/utest_c/unit_test_shell_quad_all_face_sides.cpp b/packages/stk/stk_unit_tests/stk_topology/utest_c/unit_test_shell_quad_all_face_sides.cpp index 2f47304494f7..3f8370e837db 100644 --- a/packages/stk/stk_unit_tests/stk_topology/utest_c/unit_test_shell_quad_all_face_sides.cpp +++ b/packages/stk/stk_unit_tests/stk_topology/utest_c/unit_test_shell_quad_all_face_sides.cpp @@ -79,7 +79,7 @@ TEST(stk_topology, shell_shell_quad4_all_face_sides) stk::topology t = stk::topology::SHELL_QUAD_4_ALL_FACE_SIDES; EXPECT_TRUE(t.is_valid()); - EXPECT_TRUE(t.has_homogeneous_faces()); + EXPECT_FALSE(t.has_homogeneous_faces()); EXPECT_TRUE(t.is_shell()); EXPECT_EQ(t.rank(),stk::topology::ELEMENT_RANK); @@ -139,7 +139,7 @@ void check_shell_quad_4_all_face_sides_on_device() Kokkos::parallel_for(stk::ngp::DeviceRangePolicy(0, 1), KOKKOS_LAMBDA(const int i) { NGP_EXPECT_TRUE(t.is_valid()); - NGP_EXPECT_TRUE(t.has_homogeneous_faces()); + NGP_EXPECT_FALSE(t.has_homogeneous_faces()); NGP_EXPECT_TRUE(t.is_shell()); NGP_EXPECT_EQ(t.rank(),stk::topology::ELEMENT_RANK); @@ -230,7 +230,7 @@ TEST(stk_topology, shell_shell_quad8_all_face_sides) stk::topology t = stk::topology::SHELL_QUAD_8_ALL_FACE_SIDES; EXPECT_TRUE(t.is_valid()); - EXPECT_TRUE(t.has_homogeneous_faces()); + EXPECT_FALSE(t.has_homogeneous_faces()); EXPECT_TRUE(t.is_shell()); EXPECT_EQ(t.rank(),stk::topology::ELEMENT_RANK); @@ -290,7 +290,7 @@ void check_shell_quad_8_all_face_sides_on_device() Kokkos::parallel_for(stk::ngp::DeviceRangePolicy(0, 1), KOKKOS_LAMBDA(const int i) { NGP_EXPECT_TRUE(t.is_valid()); - NGP_EXPECT_TRUE(t.has_homogeneous_faces()); + NGP_EXPECT_FALSE(t.has_homogeneous_faces()); NGP_EXPECT_TRUE(t.is_shell()); NGP_EXPECT_EQ(t.rank(),stk::topology::ELEMENT_RANK); @@ -377,7 +377,7 @@ TEST(stk_topology, shell_shell_quad9_all_face_sides) stk::topology t = stk::topology::SHELL_QUAD_9_ALL_FACE_SIDES; EXPECT_TRUE(t.is_valid()); - EXPECT_TRUE(t.has_homogeneous_faces()); + EXPECT_FALSE(t.has_homogeneous_faces()); EXPECT_TRUE(t.is_shell()); EXPECT_EQ(t.rank(),stk::topology::ELEMENT_RANK); @@ -437,7 +437,7 @@ void check_shell_quad_9_all_face_sides_on_device() Kokkos::parallel_for(stk::ngp::DeviceRangePolicy(0, 1), KOKKOS_LAMBDA(const int i) { NGP_EXPECT_TRUE(t.is_valid()); - NGP_EXPECT_TRUE(t.has_homogeneous_faces()); + NGP_EXPECT_FALSE(t.has_homogeneous_faces()); NGP_EXPECT_TRUE(t.is_shell()); NGP_EXPECT_EQ(t.rank(),stk::topology::ELEMENT_RANK); diff --git a/packages/stk/stk_unit_tests/stk_topology/utest_c/unit_test_shell_tri_all_face_sides.cpp b/packages/stk/stk_unit_tests/stk_topology/utest_c/unit_test_shell_tri_all_face_sides.cpp index f0678301ecd6..eb357fe92c4a 100644 --- a/packages/stk/stk_unit_tests/stk_topology/utest_c/unit_test_shell_tri_all_face_sides.cpp +++ b/packages/stk/stk_unit_tests/stk_topology/utest_c/unit_test_shell_tri_all_face_sides.cpp @@ -76,7 +76,7 @@ TEST(stk_topology, shell_tri_3_all_face_sides) stk::topology t = stk::topology::SHELL_TRI_3_ALL_FACE_SIDES; EXPECT_TRUE(t.is_valid()); - EXPECT_TRUE(t.has_homogeneous_faces()); + EXPECT_FALSE(t.has_homogeneous_faces()); EXPECT_TRUE(t.is_shell()); EXPECT_EQ(t.rank(),stk::topology::ELEMENT_RANK); @@ -133,7 +133,7 @@ void check_shell_tri_3_all_face_sides_on_device() Kokkos::parallel_for(stk::ngp::DeviceRangePolicy(0, 1), KOKKOS_LAMBDA(const int i) { NGP_EXPECT_TRUE(t.is_valid()); - NGP_EXPECT_TRUE(t.has_homogeneous_faces()); + NGP_EXPECT_FALSE(t.has_homogeneous_faces()); NGP_EXPECT_TRUE(t.is_shell()); NGP_EXPECT_EQ(t.rank(),stk::topology::ELEMENT_RANK); @@ -219,7 +219,7 @@ TEST(stk_topology, shell_tri_4_all_face_sides) stk::topology t = stk::topology::SHELL_TRI_4_ALL_FACE_SIDES; EXPECT_TRUE(t.is_valid()); - EXPECT_TRUE(t.has_homogeneous_faces()); + EXPECT_FALSE(t.has_homogeneous_faces()); EXPECT_TRUE(t.is_shell()); EXPECT_EQ(t.rank(),stk::topology::ELEMENT_RANK); @@ -276,7 +276,7 @@ void check_shell_tri_4_all_face_sides_on_device() Kokkos::parallel_for(stk::ngp::DeviceRangePolicy(0, 1), KOKKOS_LAMBDA(const int i) { NGP_EXPECT_TRUE(t.is_valid()); - NGP_EXPECT_TRUE(t.has_homogeneous_faces()); + NGP_EXPECT_FALSE(t.has_homogeneous_faces()); NGP_EXPECT_TRUE(t.is_shell()); NGP_EXPECT_EQ(t.rank(),stk::topology::ELEMENT_RANK); @@ -362,7 +362,7 @@ TEST(stk_topology, shell_tri_6_all_face_sides) stk::topology t = stk::topology::SHELL_TRI_6_ALL_FACE_SIDES; EXPECT_TRUE(t.is_valid()); - EXPECT_TRUE(t.has_homogeneous_faces()); + EXPECT_FALSE(t.has_homogeneous_faces()); EXPECT_TRUE(t.is_shell()); EXPECT_EQ(t.rank(),stk::topology::ELEMENT_RANK); @@ -419,7 +419,7 @@ void check_shell_tri_6_all_face_sides_on_device() Kokkos::parallel_for(stk::ngp::DeviceRangePolicy(0, 1), KOKKOS_LAMBDA(const int i) { NGP_EXPECT_TRUE(t.is_valid()); - NGP_EXPECT_TRUE(t.has_homogeneous_faces()); + NGP_EXPECT_FALSE(t.has_homogeneous_faces()); NGP_EXPECT_TRUE(t.is_shell()); NGP_EXPECT_EQ(t.rank(),stk::topology::ELEMENT_RANK); diff --git a/packages/stk/stk_unit_tests/stk_util/environment/UnitTestOutputLog.cpp b/packages/stk/stk_unit_tests/stk_util/environment/UnitTestOutputLog.cpp index e67573b9f4d4..fa2d5aa69aee 100644 --- a/packages/stk/stk_unit_tests/stk_util/environment/UnitTestOutputLog.cpp +++ b/packages/stk/stk_unit_tests/stk_util/environment/UnitTestOutputLog.cpp @@ -35,8 +35,7 @@ #include "gtest/gtest.h" #include "stk_util/parallel/Parallel.hpp" #include "stk_util/environment/OutputLog.hpp" -#include "stk_util/environment/EnvData.hpp" -#include "stk_util/environment/Env.hpp" +#include "stk_util/parallel/OutputStreams.hpp" #include #include #include @@ -147,11 +146,11 @@ TEST_F(TestOutputStreams, LogViaOutputP0) if (stk::parallel_machine_size(MPI_COMM_WORLD) > 1) { GTEST_SKIP(); } stk::bind_output_streams("log=\"myfile.log\""); - stk::EnvData::instance().m_outputP0 = stk::get_log_ostream("log"); + stk::set_outputP0(stk::get_log_ostream("log")); ASSERT_EQ((std::string("myfile.log") == stk::get_log_path("log")), true); - sierra::Env::outputP0() << "This is a test" << std::endl; + stk::outputP0() << "This is a test" << std::endl; stk::bind_output_streams("log=\"\""); diff --git a/packages/stk/stk_unit_tests/stk_util/parallel/UnitTestOutputStreams.cpp b/packages/stk/stk_unit_tests/stk_util/parallel/UnitTestOutputStreams.cpp new file mode 100644 index 000000000000..c6d5923d4226 --- /dev/null +++ b/packages/stk/stk_unit_tests/stk_util/parallel/UnitTestOutputStreams.cpp @@ -0,0 +1,106 @@ +// Copyright 2002 - 2008, 2010, 2011 National Technology Engineering +// Solutions of Sandia, LLC (NTESS). Under the terms of Contract +// DE-NA0003525 with NTESS, the U.S. Government retains certain rights +// in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// * Neither the name of NTESS nor the names of its contributors +// may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include "gtest/gtest.h" +#include +#include +#include +#include + +TEST(stkOutputStreams, set_outputP0) +{ + std::ostringstream oss; + stk::set_outputP0(&oss); + std::string expected("hello world"); + stk::outputP0() << expected; + + const int myProc = stk::parallel_machine_rank(MPI_COMM_WORLD); + if (myProc == 0) { + EXPECT_EQ(expected, oss.str()); + } + else { + EXPECT_EQ(std::string(""), oss.str()); + } + + stk::reset_default_output_streams(); +} + +TEST(stkOutputStreams, outputP0_np2) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD) != 2) { GTEST_SKIP(); } + + const int myProc = stk::parallel_machine_rank(MPI_COMM_WORLD); + + stk::reset_default_output_streams(); + + testing::internal::CaptureStdout(); + + std::string expected("hello world"); + stk::outputP0() << expected; + + std::string stdoutString = testing::internal::GetCapturedStdout(); + if (myProc == 0) { + EXPECT_EQ(expected, stdoutString); + } + else { + EXPECT_EQ(std::string(""), stdoutString); + } + + stk::reset_default_output_streams(); +} + +TEST(stkOutputStreams, output_flush) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD) != 2) { GTEST_SKIP(); } + + const int myProc = stk::parallel_machine_rank(MPI_COMM_WORLD); + + stk::reset_default_output_streams(); + + std::ostringstream oss; + stk::set_outputP0(&oss); + + stk::output() << ""; + + stk::output_flush(); + + if (myProc == 0) { + EXPECT_EQ(std::string("\n\n"), oss.str()); + } + else { + EXPECT_EQ(std::string(""), oss.str()); + } + + stk::reset_default_output_streams(); +} diff --git a/packages/stk/stk_util/stk_util/Version.hpp b/packages/stk/stk_util/stk_util/Version.hpp index f021530e66ee..244712c23833 100644 --- a/packages/stk/stk_util/stk_util/Version.hpp +++ b/packages/stk/stk_util/stk_util/Version.hpp @@ -44,7 +44,7 @@ //See the file CHANGELOG.md for a listing that shows the //correspondence between version numbers and API changes. -#define STK_VERSION 5210502 +#define STK_VERSION 5210600 namespace stk diff --git a/packages/stk/stk_util/stk_util/environment/LogWithTimeAndMemory.cpp b/packages/stk/stk_util/stk_util/environment/LogWithTimeAndMemory.cpp index 38e9b3878713..76293956ee3e 100644 --- a/packages/stk/stk_util/stk_util/environment/LogWithTimeAndMemory.cpp +++ b/packages/stk/stk_util/stk_util/environment/LogWithTimeAndMemory.cpp @@ -11,7 +11,7 @@ namespace stk { -void log_with_time_and_memory(MPI_Comm communicator, const std::string &message) +void log_with_time_and_memory(MPI_Comm communicator, const std::string &message, std::ostream& ostrm) { size_t hwm_max = 0, hwm_min = 0, hwm_avg = 0; stk::get_memory_high_water_mark_across_processors(communicator, hwm_max, hwm_min, hwm_avg); @@ -19,9 +19,9 @@ void log_with_time_and_memory(MPI_Comm communicator, const std::string &message) static double startTime = stk::wall_time(); double now = stk::wall_time(); - sierra::Env::outputP0() << "[time:" << std::right << std::fixed << std::setprecision(3) << std::setw(10) - << now-startTime << " s, hwm:" << std::setfill(' ') << std::right << std::setw(8) - << stk::human_bytes(hwm_avg) << "] "<< message << std::endl; + ostrm << "[time:" << std::right << std::fixed << std::setprecision(3) << std::setw(10) + << now-startTime << " s, hwm:" << std::setfill(' ') << std::right << std::setw(8) + << stk::human_bytes(hwm_avg) << "] "<< message << std::endl; } } diff --git a/packages/stk/stk_util/stk_util/environment/LogWithTimeAndMemory.hpp b/packages/stk/stk_util/stk_util/environment/LogWithTimeAndMemory.hpp index 65e59ad4850f..5a710c59fca5 100644 --- a/packages/stk/stk_util/stk_util/environment/LogWithTimeAndMemory.hpp +++ b/packages/stk/stk_util/stk_util/environment/LogWithTimeAndMemory.hpp @@ -2,11 +2,12 @@ #define STK_STK_UTIL_STK_UTIL_ENVIRONMENT_LOGWITHTIMEANDMEMORY_HPP_ #include "stk_util/parallel/Parallel.hpp" // for MPI_Comm +#include "stk_util/environment/Env.hpp" #include // for string namespace stk { -void log_with_time_and_memory(MPI_Comm communicator, const std::string &message); +void log_with_time_and_memory(MPI_Comm communicator, const std::string &message, std::ostream& ostrm = sierra::Env::outputP0()); } diff --git a/packages/stk/stk_util/stk_util/parallel/CMakeLists.txt b/packages/stk/stk_util/stk_util/parallel/CMakeLists.txt index e5a99525b73a..aa3f3c313ccd 100644 --- a/packages/stk/stk_util/stk_util/parallel/CMakeLists.txt +++ b/packages/stk/stk_util/stk_util/parallel/CMakeLists.txt @@ -44,6 +44,7 @@ ELSE() FILE(GLOB HEADERS CommBuffer.hpp + OutputStreams.hpp Parallel.hpp ParallelComm.hpp ParallelReduce.hpp @@ -53,6 +54,7 @@ FILE(GLOB HEADERS ) FILE(GLOB SOURCES CommBuffer.cpp + OutputStreams.cpp Parallel.cpp ParallelComm.cpp ParallelReduce.cpp diff --git a/packages/stk/stk_util/stk_util/parallel/OutputStreams.cpp b/packages/stk/stk_util/stk_util/parallel/OutputStreams.cpp new file mode 100644 index 000000000000..b99379794fea --- /dev/null +++ b/packages/stk/stk_util/stk_util/parallel/OutputStreams.cpp @@ -0,0 +1,120 @@ +// Copyright 2002 - 2008, 2010, 2011 National Technology Engineering +// Solutions of Sandia, LLC (NTESS). Under the terms of Contract +// DE-NA0003525 with NTESS, the U.S. Government retains certain rights +// in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// * Neither the name of NTESS nor the names of its contributors +// may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include +#include +#include +#include +#include +#include +#include + +namespace stk { + +struct OutputStreams +{ + OutputStreams(ParallelMachine comm); + ~OutputStreams(); + static OutputStreams& instance(ParallelMachine comm = MPI_COMM_WORLD); // CHECK: ALLOW MPI_COMM_WORLD + + null_streambuf m_nullBuf; + std::ostream m_outputNull; + std::ostream* m_outputP0; + std::ostringstream m_output; + ParallelMachine m_comm; +}; + +static std::unique_ptr s_staticOutputStreams; + +OutputStreams::OutputStreams(ParallelMachine comm) +: m_nullBuf(), + m_outputNull(&m_nullBuf), + m_outputP0(&std::cout), + m_output(), + m_comm(comm) +{ + if (stk::parallel_machine_rank(m_comm) != 0) { + m_outputP0 = &m_outputNull; + } +} + +OutputStreams::~OutputStreams() +{ +} + +OutputStreams& OutputStreams::instance(ParallelMachine comm) +{ + if (s_staticOutputStreams == nullptr) { + s_staticOutputStreams = std::make_unique(comm); + } + return *s_staticOutputStreams; +} + +std::ostream& outputP0() +{ + return *OutputStreams::instance().m_outputP0; +} + +std::ostream& outputNull() +{ + return OutputStreams::instance().m_outputNull; +} + +std::ostream& output() +{ + return OutputStreams::instance().m_output; +} + +void output_flush() +{ + std::ostringstream& oss = OutputStreams::instance().m_output; + stk::all_write_string(OutputStreams::instance().m_comm, outputP0(), oss.str()); + oss.str(""); +} + +void set_outputP0(std::ostream* ostreamPtr, ParallelMachine comm) +{ + reset_default_output_streams(comm); + if (stk::parallel_machine_rank(comm) == 0) { + OutputStreams::instance().m_outputP0 = ostreamPtr; + } +} + +void reset_default_output_streams(ParallelMachine comm) +{ + s_staticOutputStreams = std::make_unique(comm); +} + +} + diff --git a/packages/stk/stk_util/stk_util/parallel/OutputStreams.hpp b/packages/stk/stk_util/stk_util/parallel/OutputStreams.hpp new file mode 100644 index 000000000000..624a0479ab2a --- /dev/null +++ b/packages/stk/stk_util/stk_util/parallel/OutputStreams.hpp @@ -0,0 +1,73 @@ +// Copyright 2002 - 2008, 2010, 2011 National Technology Engineering +// Solutions of Sandia, LLC (NTESS). Under the terms of Contract +// DE-NA0003525 with NTESS, the U.S. Government retains certain rights +// in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// * Neither the name of NTESS nor the names of its contributors +// may be used to endorse or promote products derived from this +// software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#ifndef STK_UTIL_PARALLEL_OutputStreams_hpp +#define STK_UTIL_PARALLEL_OutputStreams_hpp + +#include +#include + +namespace stk { + +// outputP0() defaults to std::cout on MPI rank 0 (of comm-world) +// and a 'null' stream (which discards everything) on other ranks. +// +// If default stream (or comm-world) is not suitable, it can be altered +// with set_outputP0(..) below. +// +std::ostream& outputP0(); + +std::ostream& outputNull(); + +// output() is an ostream that holds output until output_flush() is +// called. +// +std::ostream& output(); + +// output_flush() sends all output in the 'output()' stream on each +// mpi rank to 'outputP0()'. +// output_flush() must be called on each mpi rank in the communicator +// +void output_flush(); + +void set_outputP0(std::ostream* ostreamPtr, ParallelMachine comm = MPI_COMM_WORLD); // CHECK: ALLOW MPI_COMM_WORLD + +// if you fear that the output streams are in a bad state, +// this resets them to their defaults +void reset_default_output_streams(ParallelMachine comm = MPI_COMM_WORLD); // CHECK: ALLOW MPI_COMM_WORLD + +} + +#endif // STK_UTIL_PARALLEL_OutputStreams_hpp + diff --git a/packages/stk/stk_util/stk_util/registry/ProductRegistry.cpp b/packages/stk/stk_util/stk_util/registry/ProductRegistry.cpp index d1acaca9193b..d1396ef1b150 100644 --- a/packages/stk/stk_util/stk_util/registry/ProductRegistry.cpp +++ b/packages/stk/stk_util/stk_util/registry/ProductRegistry.cpp @@ -42,7 +42,7 @@ //In Sierra, STK_VERSION_STRING is provided on the compile line by bake. //For Trilinos stk snapshots, the following macro definition gets populated with //the real version string by the trilinos_snapshot.sh script. -#define STK_VERSION_STRING "5.21.5-699-g38edc8e6" +#define STK_VERSION_STRING "5.21.6-340-g20e31875" #endif namespace stk { diff --git a/packages/stk/stk_util/stk_util/stk_kokkos_macros.h b/packages/stk/stk_util/stk_util/stk_kokkos_macros.h index 5d93320fc5d5..bfc4e6e03edf 100644 --- a/packages/stk/stk_util/stk_util/stk_kokkos_macros.h +++ b/packages/stk/stk_util/stk_util/stk_kokkos_macros.h @@ -22,4 +22,8 @@ #define STK_INLINE_FUNCTION KOKKOS_INLINE_FUNCTION #define STK_FUNCTION KOKKOS_FUNCTION +#if defined KOKKOS_ENABLE_IMPL_HIP_UNIFIED_MEMORY +#define STK_UNIFIED_MEMORY +#endif + #endif