From 9f0045769ccba9cf138513d87c7b8ff879d0f0b9 Mon Sep 17 00:00:00 2001 From: Jesus Bonilla Date: Wed, 2 Mar 2022 17:37:24 -0700 Subject: [PATCH 01/21] Fixed normal/tangential BC set up in panzer * Added the following patches for a special case arising in the construction of normal/tangential BC imposed at internal side sets: * Modified getUniversalSubcellElements to keep track of ghosted elements where BC need to be imposed. * Modified computeSidesetNodeNormals to remove the sides where BC need to be imposed, but the relevant neighboring element is ghosted. --- .../src/Panzer_STK_SetupUtilities.cpp | 9 ++++++++- .../src/Panzer_STK_SetupUtilities.hpp | 12 ++++++++++-- .../src/Panzer_STK_SurfaceNodeNormals.cpp | 18 ++++++++++++++++-- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/packages/panzer/adapters-stk/src/Panzer_STK_SetupUtilities.cpp b/packages/panzer/adapters-stk/src/Panzer_STK_SetupUtilities.cpp index 47477fea629b..b1d627751966 100644 --- a/packages/panzer/adapters-stk/src/Panzer_STK_SetupUtilities.cpp +++ b/packages/panzer/adapters-stk/src/Panzer_STK_SetupUtilities.cpp @@ -361,7 +361,8 @@ void getSubcellElements(const panzer_stk::STK_Interface & mesh, const std::string & blockId, const std::vector & entities, std::vector & localEntityIds, - std::vector & elements) + std::vector & elements, + std::vector & missingElementIndices) { // for verifying that an element is in specified block stk::mesh::Part * blockPart = mesh.getElementBlockPart(blockId); @@ -370,9 +371,11 @@ void getSubcellElements(const panzer_stk::STK_Interface & mesh, // loop over each entitiy extracting elements and local entity ID that // are containted in specified block. + std::size_t entityIndex =-1; std::vector::const_iterator entityItr; for(entityItr=entities.begin();entityItr!=entities.end();++entityItr) { stk::mesh::Entity entity = *entityItr; + entityIndex += 1; const size_t num_rels = bulkData.num_elements(entity); stk::mesh::Entity const* relations = bulkData.begin_elements(entity); @@ -389,6 +392,10 @@ void getSubcellElements(const panzer_stk::STK_Interface & mesh, // add element and Side ID to output vectors elements.push_back(element); localEntityIds.push_back(entityId); + } else if(!inBlock && (num_rels == 1)) { + // add index of side whose neighbor element in blockPart does not belong + // to the current processor + missingElementIndices.push_back(entityIndex); } } } diff --git a/packages/panzer/adapters-stk/src/Panzer_STK_SetupUtilities.hpp b/packages/panzer/adapters-stk/src/Panzer_STK_SetupUtilities.hpp index f2e1a0772c7c..864cc570a050 100644 --- a/packages/panzer/adapters-stk/src/Panzer_STK_SetupUtilities.hpp +++ b/packages/panzer/adapters-stk/src/Panzer_STK_SetupUtilities.hpp @@ -182,7 +182,10 @@ void getSubcellElements(const panzer_stk::STK_Interface & mesh, /** This function loops over the passed in set of entities and looks * at their related elements. It is then determined which elements * belong in the requested element block, and what the local ID of - * the entitiy is. This will return both local and ghosted entities. + * the entitiy is. It also collects the element indices related to + * the set of entities that do not belong to the requested element + * block and its neighbor is ghosted. This will return both local + * and ghosted entities. * * \param[in] mesh STK mesh interface * \param[in] blockId Requested element block identifier @@ -194,6 +197,10 @@ void getSubcellElements(const panzer_stk::STK_Interface & mesh, * \param[out] elements On output this will contain the elements associated * with each entity in the requested block. Assumed that on input * elements.size()==0 + * \param[out] missingElementIndices On output this will contain the elements + * associated with each entity in the passed set, but it is not in the + * requested block and its neighbor belonging the to the block is a + * ghost element. Assumed that on input entities.size()==0 * * \note Some elements may be repeated in the lists, however the * local entity ID should be distinct for each of those. @@ -202,7 +209,8 @@ void getUniversalSubcellElements(const panzer_stk::STK_Interface & mesh, const std::string & blockId, const std::vector & entities, std::vector & localEntityIds, - std::vector & elements); + std::vector & elements, + std::vector & missingElementIndices); /** This function loops over the passed in set of "Sides" and looks * at there related elements. It is then determined which elements diff --git a/packages/panzer/adapters-stk/src/Panzer_STK_SurfaceNodeNormals.cpp b/packages/panzer/adapters-stk/src/Panzer_STK_SurfaceNodeNormals.cpp index 65368a77b7a9..44d23241c76c 100644 --- a/packages/panzer/adapters-stk/src/Panzer_STK_SurfaceNodeNormals.cpp +++ b/packages/panzer/adapters-stk/src/Panzer_STK_SurfaceNodeNormals.cpp @@ -91,9 +91,16 @@ namespace panzer_stk { std::vector sides; stk::mesh::get_selected_entities(mySelector,bulkData->buckets(metaData->side_rank()),sides); + std::vector missingElementIndices; std::vector localSideTopoIDs; std::vector parentElements; - panzer_stk::workset_utils::getUniversalSubcellElements(*mesh,elementBlockName,sides,localSideTopoIDs,parentElements); + panzer_stk::workset_utils::getUniversalSubcellElements(*mesh,elementBlockName,sides,localSideTopoIDs,parentElements,missingElementIndices); + + // Delete all sides whose neighboring element in elementBlockName is not in the current process + std::vector::reverse_iterator index; + for(index=missingElementIndices.rbegin(); index != missingElementIndices.rend(); ++index) { + sides.erase(sides.begin()+*index); + } if (pout != NULL) { for (std::size_t i=0; i < localSideTopoIDs.size(); ++i) { @@ -258,9 +265,16 @@ namespace panzer_stk { RCP parentTopology = mesh->getCellTopology(elementBlockName); + std::vector missingElementIndices; std::vector localSideTopoIDs; std::vector parentElements; - panzer_stk::workset_utils::getUniversalSubcellElements(*mesh,elementBlockName,sides,localSideTopoIDs,parentElements); + panzer_stk::workset_utils::getUniversalSubcellElements(*mesh,elementBlockName,sides,localSideTopoIDs,parentElements,missingElementIndices); + + // Delete all sides whose neighboring element in elementBlockName is not in the current process + std::vector::reverse_iterator index; + for(index=missingElementIndices.rbegin(); index != missingElementIndices.rend(); ++index) { + sides.erase(sides.begin()+*index); + } std::vector::const_iterator side = sides.begin(); std::vector::const_iterator sideID = localSideTopoIDs.begin(); From a96d4f35f1a835396235e95e763966e70ab80503 Mon Sep 17 00:00:00 2001 From: Jesus Bonilla Date: Thu, 10 Mar 2022 09:51:57 -0700 Subject: [PATCH 02/21] Fixed normal/tangential BC set up in panzer * Minor corrections --- .../src/Panzer_STK_SetupUtilities.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/panzer/adapters-stk/src/Panzer_STK_SetupUtilities.cpp b/packages/panzer/adapters-stk/src/Panzer_STK_SetupUtilities.cpp index b1d627751966..415c2e073fef 100644 --- a/packages/panzer/adapters-stk/src/Panzer_STK_SetupUtilities.cpp +++ b/packages/panzer/adapters-stk/src/Panzer_STK_SetupUtilities.cpp @@ -361,8 +361,7 @@ void getSubcellElements(const panzer_stk::STK_Interface & mesh, const std::string & blockId, const std::vector & entities, std::vector & localEntityIds, - std::vector & elements, - std::vector & missingElementIndices) + std::vector & elements) { // for verifying that an element is in specified block stk::mesh::Part * blockPart = mesh.getElementBlockPart(blockId); @@ -371,11 +370,9 @@ void getSubcellElements(const panzer_stk::STK_Interface & mesh, // loop over each entitiy extracting elements and local entity ID that // are containted in specified block. - std::size_t entityIndex =-1; std::vector::const_iterator entityItr; for(entityItr=entities.begin();entityItr!=entities.end();++entityItr) { stk::mesh::Entity entity = *entityItr; - entityIndex += 1; const size_t num_rels = bulkData.num_elements(entity); stk::mesh::Entity const* relations = bulkData.begin_elements(entity); @@ -392,10 +389,6 @@ void getSubcellElements(const panzer_stk::STK_Interface & mesh, // add element and Side ID to output vectors elements.push_back(element); localEntityIds.push_back(entityId); - } else if(!inBlock && (num_rels == 1)) { - // add index of side whose neighbor element in blockPart does not belong - // to the current processor - missingElementIndices.push_back(entityIndex); } } } @@ -405,7 +398,8 @@ void getUniversalSubcellElements(const panzer_stk::STK_Interface & mesh, const std::string & blockId, const std::vector & entities, std::vector & localEntityIds, - std::vector & elements) + std::vector & elements, + std::vector & missingElementIndices) { // for verifying that an element is in specified block stk::mesh::Part * blockPart = mesh.getElementBlockPart(blockId); @@ -414,9 +408,11 @@ void getUniversalSubcellElements(const panzer_stk::STK_Interface & mesh, // loop over each entitiy extracting elements and local entity ID that // are containted in specified block. + std::size_t entityIndex =-1; std::vector::const_iterator entityItr; for(entityItr=entities.begin();entityItr!=entities.end();++entityItr) { stk::mesh::Entity entity = *entityItr; + entityIndex += 1; const size_t num_rels = bulkData.num_elements(entity); stk::mesh::Entity const* element_rels = bulkData.begin_elements(entity); @@ -433,6 +429,10 @@ void getUniversalSubcellElements(const panzer_stk::STK_Interface & mesh, // add element and Side ID to output vectors elements.push_back(element); localEntityIds.push_back(entityId); + } else if(!inBlock && (num_rels == 1)) { + // add index of side whose neighbor element in blockPart does not belong + // to the current processor + missingElementIndices.push_back(entityIndex); } } } From ee3ce3c39ccac581c99a43ebbe0c823237ccab7c Mon Sep 17 00:00:00 2001 From: iyamazaki Date: Fri, 13 May 2022 01:59:32 -0600 Subject: [PATCH 03/21] ShyLU_node,FastILU : 1. update FastILU to improve compute time (not FastILDL or FastIC) 2. add an option to run standard SpTRSV on host for solve --- .../src/Ifpack2_Details_FastILU_Base_decl.hpp | 7 +- .../src/Ifpack2_Details_FastILU_Base_def.hpp | 35 +- .../ifpack2/src/Ifpack2_Details_Fic_def.hpp | 4 +- .../ifpack2/src/Ifpack2_Details_Fildl_def.hpp | 4 +- .../ifpack2/src/Ifpack2_Details_Filu_def.hpp | 8 +- packages/ifpack2/test/belos/CMakeLists.txt | 27 + .../belos/test_FIC_tfqmr_small_sym_mm.xml | 1 + .../test_FIC_tfqmr_small_sym_mm_schwarz.xml | 26 + .../test_FIC_tfqmr_small_sym_mm_sptrsv.xml | 1 + .../belos/test_FILDL_tfqmr_small_sym_mm.xml | 1 + .../test_FILDL_tfqmr_small_sym_mm_schwarz.xml | 26 + .../test_FILDL_tfqmr_small_sym_mm_sptrsv.xml | 1 + .../belos/test_FILU_tfqmr_small_sym_mm.xml | 1 + .../test_FILU_tfqmr_small_sym_mm_schwarz.xml | 26 + .../test_FILU_tfqmr_small_sym_mm_sptrsv.xml | 1 + .../shylu_node/fastilu/src/shylu_fastic.hpp | 7 +- .../shylu_node/fastilu/src/shylu_fastildl.hpp | 13 +- .../shylu_node/fastilu/src/shylu_fastilu.hpp | 490 ++++++++++++------ .../shylu_node/fastilu/src/shylu_fastutil.hpp | 15 + 19 files changed, 526 insertions(+), 168 deletions(-) create mode 100644 packages/ifpack2/test/belos/test_FIC_tfqmr_small_sym_mm_schwarz.xml create mode 100644 packages/ifpack2/test/belos/test_FILDL_tfqmr_small_sym_mm_schwarz.xml create mode 100644 packages/ifpack2/test/belos/test_FILU_tfqmr_small_sym_mm_schwarz.xml create mode 100644 packages/shylu/shylu_node/fastilu/src/shylu_fastutil.hpp diff --git a/packages/ifpack2/src/Ifpack2_Details_FastILU_Base_decl.hpp b/packages/ifpack2/src/Ifpack2_Details_FastILU_Base_decl.hpp index 67012dee858c..b0c43399cfd6 100644 --- a/packages/ifpack2/src/Ifpack2_Details_FastILU_Base_decl.hpp +++ b/packages/ifpack2/src/Ifpack2_Details_FastILU_Base_decl.hpp @@ -53,7 +53,8 @@ #include #include #include -#include "Ifpack2_Details_CanChangeMatrix.hpp" +#include +#include namespace Ifpack2 { @@ -201,13 +202,15 @@ template { Params() {} Params(const Teuchos::ParameterList& pL, std::string precType); - bool standard_sptrsv; + FastILU::SpTRSV sptrsv_algo; int nFact; int nTrisol; int level; + int blkSize; double omega; double shift; bool guessFlag; + int blockSizeILU; int blockSize; static Params getDefaults(); }; diff --git a/packages/ifpack2/src/Ifpack2_Details_FastILU_Base_def.hpp b/packages/ifpack2/src/Ifpack2_Details_FastILU_Base_def.hpp index a34bedbdef58..6ea64efa9c85 100644 --- a/packages/ifpack2/src/Ifpack2_Details_FastILU_Base_def.hpp +++ b/packages/ifpack2/src/Ifpack2_Details_FastILU_Base_def.hpp @@ -330,14 +330,15 @@ FastILU_Base:: Params::getDefaults() { Params p; - p.standard_sptrsv = false; + p.sptrsv_algo = FastILU::SpTRSV::Fast; p.nFact = 5; p.nTrisol = 1; p.level = 0; p.omega = 0.5; p.shift = 0; p.guessFlag = true; - p.blockSize = 1; + p.blockSizeILU = 1; // # of nonzeros / thread, for fastILU + p.blockSize = 1; // # of rows / thread, for SpTRSV return p; } @@ -363,10 +364,21 @@ Params::Params(const Teuchos::ParameterList& pL, std::string precType) else TYPE_ERROR("sweeps", "int"); } + bool standard_sptrsv = false; if(pL.isParameter("standard triangular solve")) { standard_sptrsv = pL.get("standard triangular solve"); } + bool standard_sptrsv_host = false; + if(pL.isParameter("host standard triangular solve")) + { + standard_sptrsv_host = pL.get("host standard triangular solve"); + } + if (standard_sptrsv_host) { + sptrsv_algo = FastILU::SpTRSV::StandardHost; + } else if (standard_sptrsv) { + sptrsv_algo = FastILU::SpTRSV::Standard; + } //"triangular solve iterations" aka nTrisol if(pL.isParameter("triangular solve iterations")) @@ -433,12 +445,23 @@ Params::Params(const Teuchos::ParameterList& pL, std::string precType) TYPE_ERROR("guess", "bool"); } //"block size" aka blkSz - if(pL.isParameter("block size")) + if(pL.isParameter("block size for ILU")) + { + if(pL.isType("block size for ILU")) + { + blockSizeILU = pL.get("block size for ILU"); + CHECK_VALUE("block size for ILU", blockSizeILU, blockSizeILU < 1, "must have a value of at least 1"); + } + else + TYPE_ERROR("block size for ILU", "int"); + } + //"block size" aka blkSz + if(pL.isParameter("block size for SpTRSV")) { - if(pL.isType("block size")) - blockSize = pL.get("block size"); + if(pL.isType("block size for SpTRSV")) + blockSize = pL.get("block size for SpTRSV"); else - TYPE_ERROR("block size", "int"); + TYPE_ERROR("block size for SpTRSV", "int"); } #undef CHECK_VALUE #undef TYPE_ERROR diff --git a/packages/ifpack2/src/Ifpack2_Details_Fic_def.hpp b/packages/ifpack2/src/Ifpack2_Details_Fic_def.hpp index 829d9efb6dba..220e5756497a 100644 --- a/packages/ifpack2/src/Ifpack2_Details_Fic_def.hpp +++ b/packages/ifpack2/src/Ifpack2_Details_Fic_def.hpp @@ -87,8 +87,8 @@ initLocalPrec() { auto nRows = this->mat_->getLocalNumRows(); auto& p = this->params_; - localPrec_ = Teuchos::rcp(new LocalFIC(this->localRowPtrs_, this->localColInds_, this->localValues_, nRows, p.standard_sptrsv, - p.nFact, p.nTrisol, p.level, p.omega, p.shift, p.guessFlag ? 1 : 0, p.blockSize)); + localPrec_ = Teuchos::rcp(new LocalFIC(this->localRowPtrs_, this->localColInds_, this->localValues_, nRows, (p.sptrsv_algo != FastILU::SpTRSV::Fast), + p.nFact, p.nTrisol, p.level, p.omega, p.shift, p.guessFlag ? 1 : 0, p.blockSizeILU, p.blockSize)); localPrec_->initialize(); this->initTime_ = localPrec_->getInitializeTime(); } diff --git a/packages/ifpack2/src/Ifpack2_Details_Fildl_def.hpp b/packages/ifpack2/src/Ifpack2_Details_Fildl_def.hpp index c8d610acb1f1..4dc9a9ee148e 100644 --- a/packages/ifpack2/src/Ifpack2_Details_Fildl_def.hpp +++ b/packages/ifpack2/src/Ifpack2_Details_Fildl_def.hpp @@ -87,8 +87,8 @@ initLocalPrec() { auto nRows = this->mat_->getLocalNumRows(); auto& p = this->params_; - localPrec_ = Teuchos::rcp(new LocalFILDL(this->localRowPtrs_, this->localColInds_, this->localValues_, nRows, p.standard_sptrsv, - p.nFact, p.nTrisol, p.level, p.omega, p.shift, p.guessFlag ? 1 : 0, p.blockSize)); + localPrec_ = Teuchos::rcp(new LocalFILDL(this->localRowPtrs_, this->localColInds_, this->localValues_, nRows, (p.sptrsv_algo != FastILU::SpTRSV::Fast), + p.nFact, p.nTrisol, p.level, p.omega, p.shift, p.guessFlag ? 1 : 0, p.blockSizeILU, p.blockSize)); localPrec_->initialize(); this->initTime_ = localPrec_->getInitializeTime(); } diff --git a/packages/ifpack2/src/Ifpack2_Details_Filu_def.hpp b/packages/ifpack2/src/Ifpack2_Details_Filu_def.hpp index 93c53fc9e301..9c41eb47f46a 100644 --- a/packages/ifpack2/src/Ifpack2_Details_Filu_def.hpp +++ b/packages/ifpack2/src/Ifpack2_Details_Filu_def.hpp @@ -94,8 +94,8 @@ initLocalPrec() { auto nRows = this->mat_->getLocalNumRows(); auto& p = this->params_; - localPrec_ = Teuchos::rcp(new LocalFILU(this->localRowPtrs_, this->localColInds_, this->localValues_, nRows, p.standard_sptrsv, - p.nFact, p.nTrisol, p.level, p.omega, p.shift, p.guessFlag ? 1 : 0, p.blockSize)); + localPrec_ = Teuchos::rcp(new LocalFILU(this->localRowPtrs_, this->localColInds_, this->localValues_, nRows, p.sptrsv_algo, + p.nFact, p.nTrisol, p.level, p.omega, p.shift, p.guessFlag ? 1 : 0, p.blockSizeILU, p.blockSize)); localPrec_->initialize(); this->initTime_ = localPrec_->getInitializeTime(); } @@ -105,8 +105,12 @@ void Filu:: computeLocalPrec() { //update values in local prec (until compute(), values aren't needed) +Kokkos::Timer timer; localPrec_->setValues(this->localValues_); +std::cout << " * setValues = " << timer.seconds() << std::endl; +timer.reset(); localPrec_->compute(); +std::cout << " * compute = " << timer.seconds() << std::endl; this->computeTime_ = localPrec_->getComputeTime(); } diff --git a/packages/ifpack2/test/belos/CMakeLists.txt b/packages/ifpack2/test/belos/CMakeLists.txt index f6aace57e775..30ff131108a9 100644 --- a/packages/ifpack2/test/belos/CMakeLists.txt +++ b/packages/ifpack2/test/belos/CMakeLists.txt @@ -86,10 +86,13 @@ TRIBITS_COPY_FILES_TO_BINARY_DIR(Ifpack2BelosCopyFiles test_tfqmr_small_sym_mm.xml test_FILU_tfqmr_small_sym_mm.xml test_FILU_tfqmr_small_sym_mm_sptrsv.xml + test_FILU_tfqmr_small_sym_mm_schwarz.xml test_FIC_tfqmr_small_sym_mm.xml test_FIC_tfqmr_small_sym_mm_sptrsv.xml + test_FIC_tfqmr_small_sym_mm_schwarz.xml test_FILDL_tfqmr_small_sym_mm.xml test_FILDL_tfqmr_small_sym_mm_sptrsv.xml + test_FILDL_tfqmr_small_sym_mm_schwarz.xml test_ILUT_tfqmr_calore1_mm.xml 5w.mtx 5w.vec @@ -550,6 +553,14 @@ IF(Tpetra_INST_DOUBLE AND Ifpack2_ENABLE_ShyLU_NodeFastILU) NUM_MPI_PROCS 1 STANDARD_PASS_OUTPUT ) + TRIBITS_ADD_TEST( + tif_belos + NAME FILU_small_sym_schwarz + ARGS "--xml_file=test_FILU_tfqmr_small_sym_mm_schwarz.xml" + COMM serial mpi + NUM_MPI_PROCS 1 + STANDARD_PASS_OUTPUT + ) TRIBITS_ADD_TEST( tif_belos NAME FIC_small_sym @@ -566,6 +577,14 @@ IF(Tpetra_INST_DOUBLE AND Ifpack2_ENABLE_ShyLU_NodeFastILU) NUM_MPI_PROCS 1 STANDARD_PASS_OUTPUT ) + TRIBITS_ADD_TEST( + tif_belos + NAME FIC_small_sym_schwarz + ARGS "--xml_file=test_FIC_tfqmr_small_sym_mm_schwarz.xml" + COMM serial mpi + NUM_MPI_PROCS 1 + STANDARD_PASS_OUTPUT + ) TRIBITS_ADD_TEST( tif_belos NAME FILDL_small_sym @@ -582,6 +601,14 @@ IF(Tpetra_INST_DOUBLE AND Ifpack2_ENABLE_ShyLU_NodeFastILU) NUM_MPI_PROCS 1 STANDARD_PASS_OUTPUT ) + TRIBITS_ADD_TEST( + tif_belos + NAME FILDL_small_sym_schwarz + ARGS "--xml_file=test_FILDL_tfqmr_small_sym_mm_schwarz.xml" + COMM serial mpi + NUM_MPI_PROCS 1 + STANDARD_PASS_OUTPUT + ) #small_sym_sing TRIBITS_ADD_TEST( tif_belos diff --git a/packages/ifpack2/test/belos/test_FIC_tfqmr_small_sym_mm.xml b/packages/ifpack2/test/belos/test_FIC_tfqmr_small_sym_mm.xml index a92d3d980251..29bb29104a1d 100644 --- a/packages/ifpack2/test/belos/test_FIC_tfqmr_small_sym_mm.xml +++ b/packages/ifpack2/test/belos/test_FIC_tfqmr_small_sym_mm.xml @@ -11,6 +11,7 @@ + diff --git a/packages/ifpack2/test/belos/test_FIC_tfqmr_small_sym_mm_schwarz.xml b/packages/ifpack2/test/belos/test_FIC_tfqmr_small_sym_mm_schwarz.xml new file mode 100644 index 000000000000..163847c54acb --- /dev/null +++ b/packages/ifpack2/test/belos/test_FIC_tfqmr_small_sym_mm_schwarz.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/ifpack2/test/belos/test_FIC_tfqmr_small_sym_mm_sptrsv.xml b/packages/ifpack2/test/belos/test_FIC_tfqmr_small_sym_mm_sptrsv.xml index 81156a2a2fbe..bc8e4909314c 100644 --- a/packages/ifpack2/test/belos/test_FIC_tfqmr_small_sym_mm_sptrsv.xml +++ b/packages/ifpack2/test/belos/test_FIC_tfqmr_small_sym_mm_sptrsv.xml @@ -11,6 +11,7 @@ + diff --git a/packages/ifpack2/test/belos/test_FILDL_tfqmr_small_sym_mm.xml b/packages/ifpack2/test/belos/test_FILDL_tfqmr_small_sym_mm.xml index 8f84a9a41a03..2ad229ee7090 100644 --- a/packages/ifpack2/test/belos/test_FILDL_tfqmr_small_sym_mm.xml +++ b/packages/ifpack2/test/belos/test_FILDL_tfqmr_small_sym_mm.xml @@ -11,6 +11,7 @@ + diff --git a/packages/ifpack2/test/belos/test_FILDL_tfqmr_small_sym_mm_schwarz.xml b/packages/ifpack2/test/belos/test_FILDL_tfqmr_small_sym_mm_schwarz.xml new file mode 100644 index 000000000000..ab50b83a8b74 --- /dev/null +++ b/packages/ifpack2/test/belos/test_FILDL_tfqmr_small_sym_mm_schwarz.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/ifpack2/test/belos/test_FILDL_tfqmr_small_sym_mm_sptrsv.xml b/packages/ifpack2/test/belos/test_FILDL_tfqmr_small_sym_mm_sptrsv.xml index 912ee758d80f..205763a114fc 100644 --- a/packages/ifpack2/test/belos/test_FILDL_tfqmr_small_sym_mm_sptrsv.xml +++ b/packages/ifpack2/test/belos/test_FILDL_tfqmr_small_sym_mm_sptrsv.xml @@ -11,6 +11,7 @@ + diff --git a/packages/ifpack2/test/belos/test_FILU_tfqmr_small_sym_mm.xml b/packages/ifpack2/test/belos/test_FILU_tfqmr_small_sym_mm.xml index 0699c90eed97..4c0b965f6aa8 100644 --- a/packages/ifpack2/test/belos/test_FILU_tfqmr_small_sym_mm.xml +++ b/packages/ifpack2/test/belos/test_FILU_tfqmr_small_sym_mm.xml @@ -11,6 +11,7 @@ + diff --git a/packages/ifpack2/test/belos/test_FILU_tfqmr_small_sym_mm_schwarz.xml b/packages/ifpack2/test/belos/test_FILU_tfqmr_small_sym_mm_schwarz.xml new file mode 100644 index 000000000000..ac926d0ac2f3 --- /dev/null +++ b/packages/ifpack2/test/belos/test_FILU_tfqmr_small_sym_mm_schwarz.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/ifpack2/test/belos/test_FILU_tfqmr_small_sym_mm_sptrsv.xml b/packages/ifpack2/test/belos/test_FILU_tfqmr_small_sym_mm_sptrsv.xml index 5d6536174089..70161f9542a6 100644 --- a/packages/ifpack2/test/belos/test_FILU_tfqmr_small_sym_mm_sptrsv.xml +++ b/packages/ifpack2/test/belos/test_FILU_tfqmr_small_sym_mm_sptrsv.xml @@ -11,6 +11,7 @@ + diff --git a/packages/shylu/shylu_node/fastilu/src/shylu_fastic.hpp b/packages/shylu/shylu_node/fastilu/src/shylu_fastic.hpp index 367ebe662fe7..a5eb74096a66 100644 --- a/packages/shylu/shylu_node/fastilu/src/shylu_fastic.hpp +++ b/packages/shylu/shylu_node/fastilu/src/shylu_fastic.hpp @@ -97,6 +97,7 @@ class FastICPrec Ordinal nFact; Ordinal nTrisol; Ordinal level; + Ordinal blkSzIC; Ordinal blkSz; Scalar omega; Scalar shift; @@ -157,7 +158,7 @@ class FastICPrec public: FastICPrec(OrdinalArray &aRowMapIn, OrdinalArray &aColIdxIn, ScalarArray &aValIn, Ordinal nRow_, bool standard_sptrsv_, - Ordinal nFact_, Ordinal nTrisol_, Ordinal level_, Scalar omega_, Scalar shift_, Ordinal guessFlag_, Ordinal blkSz_) + Ordinal nFact_, Ordinal nTrisol_, Ordinal level_, Scalar omega_, Scalar shift_, Ordinal guessFlag_, Ordinal blkSzIC_, Ordinal blkSz_) { nRows = nRow_; standard_sptrsv = standard_sptrsv_; @@ -179,6 +180,7 @@ class FastICPrec omega = omega_; guessFlag = guessFlag_; shift = shift_; + blkSzIC = blkSzIC_; blkSz = blkSz_; const Scalar one = STS::one(); @@ -194,7 +196,7 @@ class FastICPrec if (level > 0) { initGuessPrec = Teuchos::rcp(new FastPrec(aRowMapIn, aColIdxIn, aValIn, nRow_, standard_sptrsv, 3, 5, - level_-1, omega_, shift_, guessFlag_, blkSz_)); + level_-1, omega_, shift_, guessFlag_, blkSzIC_, blkSz_)); } } @@ -832,7 +834,6 @@ class FastICPrec initGuessPrec->compute(); } numericILU(); - Ordinal blkSzIC = 4096; FastICFunctor icFunctor(aRowMap_[nRows], blkSzIC, aRowMap, aColIdx, aRowIdx, aVal, lRowMap, lColIdx, lVal, diagElems, omega); ExecSpace().fence(); diff --git a/packages/shylu/shylu_node/fastilu/src/shylu_fastildl.hpp b/packages/shylu/shylu_node/fastilu/src/shylu_fastildl.hpp index a79cd16592c3..2dfe3f90a05b 100644 --- a/packages/shylu/shylu_node/fastilu/src/shylu_fastildl.hpp +++ b/packages/shylu/shylu_node/fastilu/src/shylu_fastildl.hpp @@ -100,6 +100,7 @@ class FastILDLPrec Ordinal nTrisol; Ordinal level; Ordinal blkSz; + Ordinal blkSzILDL; Scalar omega; Scalar shift; @@ -163,7 +164,7 @@ class FastILDLPrec public: FastILDLPrec(OrdinalArray &aRowMapIn, OrdinalArray &aColIdxIn, ScalarArray &aValIn, Ordinal nRow_, bool standard_sptrsv_, - Ordinal nFact_, Ordinal nTrisol_, Ordinal level_, Scalar omega_, Scalar shift_, Ordinal guessFlag_, Ordinal blkSz_) + Ordinal nFact_, Ordinal nTrisol_, Ordinal level_, Scalar omega_, Scalar shift_, Ordinal guessFlag_, Ordinal blkSzILDL_, Ordinal blkSz_) { nRows = nRow_; standard_sptrsv = standard_sptrsv_; @@ -185,6 +186,7 @@ class FastILDLPrec omega = omega_; guessFlag = guessFlag_; shift = shift_; + blkSzILDL = blkSzILDL_; blkSz = blkSz_; const Scalar one = Kokkos::ArithTraits::one(); @@ -200,7 +202,7 @@ class FastILDLPrec if (level > 0) { initGuessPrec = Teuchos::rcp(new FastPrec(aRowMapIn, aColIdxIn, aValIn, nRow_, standard_sptrsv, 3, 5, - level_-1, omega_, shift_, guessFlag_, blkSz_)); + level_-1, omega_, shift_, guessFlag_, blkSzILDL_, blkSz_)); } } @@ -814,12 +816,11 @@ class FastILDLPrec Kokkos::Timer timer; numericILU(); - Ordinal blkSzILDLt = 4096; - FastILDLFunctor ildltFunctor(aRowMap_[nRows], blkSzILDLt, + FastILDLFunctor ildltFunctor(aRowMap_[nRows], blkSzILDL, aRowMap, aColIdx, aRowIdx, aVal, lRowMap, lColIdx, lVal, diagElems, omega); - Ordinal extent = aRowMap_[nRows]/blkSzILDLt; - if (aRowMap_[nRows]%blkSzILDLt != 0) + Ordinal extent = aRowMap_[nRows]/blkSzILDL; + if (aRowMap_[nRows]%blkSzILDL != 0) { extent++; } diff --git a/packages/shylu/shylu_node/fastilu/src/shylu_fastilu.hpp b/packages/shylu/shylu_node/fastilu/src/shylu_fastilu.hpp index b03e79d6ddcd..4d83557b6f75 100644 --- a/packages/shylu/shylu_node/fastilu/src/shylu_fastilu.hpp +++ b/packages/shylu/shylu_node/fastilu/src/shylu_fastilu.hpp @@ -57,7 +57,10 @@ #include #include #include +#include #include +#include +#include //whether to print extra debug output at runtime to stdout //comment out next line to disable @@ -132,6 +135,7 @@ class FastILUPrec Ordinal nFact; Ordinal nTrisol; Ordinal level; + Ordinal blkSzILU; Ordinal blkSz; Scalar omega; //Underrelaxation parameter Scalar shift; //Manteuffel Shift @@ -158,8 +162,17 @@ class FastILUPrec ScalarArray utVal; OrdinalArray utColIdx; OrdinalArray utRowMap; - - //Pointer to the original host copy of A. + // mirrors + ScalarArrayMirror utVal_; + OrdinalArrayMirror utColIdx_; + OrdinalArrayMirror utRowMap_; + + //Pointer to the copy of input A. + // device + ScalarArray aValIn; + OrdinalArray aRowMapIn; + OrdinalArray aColIdxIn; + // host ScalarArrayMirror aValHost; OrdinalArrayMirror aRowMapHost; OrdinalArrayMirror aColIdxHost; @@ -191,7 +204,8 @@ class FastILUPrec // forward/backwar substitution for standard SpTrsv using MemSpace = typename ExecSpace::memory_space; using KernelHandle = KokkosKernels::Experimental::KokkosKernelsHandle ; - bool standard_sptrsv; + FastILU::SpTRSV sptrsv_algo; + KernelHandle khL; KernelHandle khU; @@ -200,9 +214,9 @@ class FastILUPrec //TODO:convert to parallel. void transposeU() { - auto utRowMap_ = Kokkos::create_mirror(utRowMap); - auto utColIdx_ = Kokkos::create_mirror(utColIdx); - auto utVal_ = Kokkos::create_mirror(utVal); + utRowMap_ = Kokkos::create_mirror(utRowMap); + utColIdx_ = Kokkos::create_mirror(utColIdx); + utVal_ = Kokkos::create_mirror(utVal); //Count the elements in each row of Ut auto temp = OrdinalArrayHost("temp", nRows + 1); @@ -432,6 +446,9 @@ class FastILUPrec aColIdx_ = Kokkos::create_mirror(aColIdx); aRowIdx_ = Kokkos::create_mirror(aRowIdx); + aVal = ScalarArray("aVal", aColIdx.extent(0)); + aVal_ = Kokkos::create_mirror(aVal); + Ordinal aRowPtr = 0; aRowMap_[0] = aRowPtr; for (i = 0; i < nRows; i++) @@ -456,6 +473,12 @@ class FastILUPrec } aRowMap_[i+1] = aRowPtr; } + // sort based on ColIdx, RowIdx stays the same (do we need this?) + using host_space = Kokkos::HostSpace::execution_space; + KokkosKernels::sort_crs_matrix + (aRowMap_, aColIdx_, aVal_); + host_space().fence(); + Kokkos::deep_copy(aRowMap, aRowMap_); Kokkos::deep_copy(aColIdx, aColIdx_); Kokkos::deep_copy(aRowIdx, aRowIdx_); @@ -482,47 +505,75 @@ class FastILUPrec lColIdx = OrdinalArray("lColIdx", lRowMap_[nRows]); uColIdx = OrdinalArray("uColIdx", uRowMap_[nRows]); utColIdx = OrdinalArray("utColIdx", uRowMap_[nRows]); + + lVal = ScalarArray("lVal", lRowMap_[nRows]); + uVal = ScalarArray("uVal", uRowMap_[nRows]); + utVal = ScalarArray("utVal", uRowMap_[nRows]); } void numericILU() { - aVal = ScalarArray("aVal", aColIdx.extent(0)); - aVal_ = Kokkos::create_mirror(aVal); + const Scalar zero = STS::zero(); + #ifdef FASTILU_TIMER + Kokkos::Timer Timer; + #endif + //Sort each row of A by ColIdx + KokkosKernels::sort_crs_matrix(aRowMapIn, aColIdxIn, aValIn); + ExecSpace().fence(); + //Copy the host matrix into the initialized a; - for (Ordinal i = 0; i < nRows; i++) - { - for(Ordinal k = aRowMap_[i]; k < aRowMap_[i+1]; k++) - { - Ordinal col = aColIdx_[k]; - #ifdef FASTILU_DEBUG_OUTPUT - std::cout << "col =" << col << std::endl; - #endif - for(Ordinal aHostPtr = aRowMapHost[i]; aHostPtr < aRowMapHost[i+1]; aHostPtr++) - { - if (col == aColIdxHost[aHostPtr]) - { - aVal_[k] = aValHost[aHostPtr]; - break; - } - } - } - } + FastILUPrec_Functor functor(aValIn, aRowMapIn, aColIdxIn, aVal, diagFact, aRowMap, aColIdx, aRowIdx); + Kokkos::RangePolicy copy_policy (0, nRows); + Kokkos::parallel_for( + "numericILU::copyVals", copy_policy, functor); + ExecSpace().fence(); + #ifdef FASTILU_TIMER + std::cout << " + copy values " << Timer.seconds() << std::endl; + Timer.reset(); + #endif - lVal = ScalarArray("lVal", lRowMap_[nRows]); - uVal = ScalarArray("uVal", uRowMap_[nRows]); - utVal = ScalarArray("utVal", uRowMap_[nRows]); - applyDiagonalScaling(); - applyManteuffelShift(); + // applyDiagonalScaling + Kokkos::RangePolicy get_policy (0, nRows); + Kokkos::parallel_for( + "numericILU::getDiags", get_policy, functor); + ExecSpace().fence(); + + Kokkos::RangePolicy scale_policy (0, nRows); + Kokkos::parallel_for( + "numericILU::diagScal", scale_policy, functor); + Kokkos::deep_copy(aVal_, aVal); + + // applyShift + if (shift != zero) { + applyManteuffelShift(); + } + #ifdef FASTILU_TIMER + std::cout << " + apply shift/scale " << Timer.seconds() << std::endl; + Timer.reset(); + #endif Kokkos::deep_copy(aVal, aVal_); + #ifdef FASTILU_TIMER + std::cout << " + deep copy " << Timer.seconds() << std::endl; + Timer.reset(); + #endif + #ifdef FASTILU_DEBUG_OUTPUT std::cout << "**Finished diagonal scaling" << std::endl; #endif fillL(); + #ifdef FASTILU_TIMER + std::cout << " + fill L " << Timer.seconds() << std::endl; + Timer.reset(); + #endif #ifdef FASTILU_DEBUG_OUTPUT std::cout << "**Finished copying L" << std::endl; #endif fillU(); + #ifdef FASTILU_TIMER + std::cout << " + fill U " << Timer.seconds() << std::endl; + Timer.reset(); + #endif #ifdef FASTILU_DEBUG_OUTPUT std::cout << "**Finished copying U" << std::endl; std::cout << "nnz L = " << lRowMap_[nRows] << std::endl; @@ -557,38 +608,11 @@ class FastILUPrec //Put the initial guess into L. void fillL() { - lVal_ = Kokkos::create_mirror(lVal); - lColIdx_ = Kokkos::create_mirror(lColIdx); - - auto diagElems_ = Kokkos::create_mirror(diagElems); - Ordinal lPtr = 0; - for (Ordinal i = 0; i < nRows; i++) - { - for (Ordinal k = aRowMap_[i]; k < aRowMap_[i+1]; k++) - { - Ordinal row = i; - Ordinal col = aColIdx_[k]; - - if (row >= col) - { - if (row == col) - { - diagElems_[row] = aVal_[k]; - lVal_[lPtr] = 1.0; - lColIdx_[lPtr] = aColIdx_[k]; - lPtr++; - } - else - { - lVal_[lPtr] = aVal_[k]; - lColIdx_[lPtr] = aColIdx_[k]; - lPtr++; - } - } - } - } - assert(lPtr == lRowMap[nRows]); - Kokkos::deep_copy(diagElems, diagElems_); + FastILUPrec_Functor functor(aVal, aRowMap, aColIdx, lVal, lRowMap, lColIdx, diagElems); + Kokkos::RangePolicy getL_policy (0, nRows); + Kokkos::parallel_for( + "numericILU::getLower", getL_policy, functor); + ExecSpace().fence(); if ((level > 0) && (guessFlag !=0)) { @@ -596,40 +620,26 @@ class FastILUPrec OrdinalArray lGColIdx; ScalarArray lGVal; ScalarArray gD; - Ordinal lGPtr = 0; initGuessPrec->getL(lGRowMap, lGColIdx, lGVal); initGuessPrec->getD(gD); - Kokkos::deep_copy(diagElems, gD); - auto lGColIdx_ = Kokkos::create_mirror(lGColIdx); - auto lGVal_ = Kokkos::create_mirror(lGVal); - Kokkos::deep_copy(lGColIdx_, lGColIdx); - Kokkos::deep_copy(lGVal_, lGVal); - for (Ordinal i = 0; i < nRows; i++) - { - #ifdef SHYLU_DEBUG - Ordinal check = lGPtr; - #endif - for (Ordinal k = lRowMap_[i]; k < lRowMap_[i+1]; k++) - { - //Ordinal row = i; - Ordinal col = lColIdx_[k]; - if (col == lGColIdx_[lGPtr]) - { - lVal_[k] = lGVal_[lGPtr]; - lGPtr++; - } - } - #ifdef SHYLU_DEBUG - Ordinal rowLen = lGPtr - check; - assert(rowLen == lGRowMap[i+1] - lGRowMap[i]); - #endif - } + // copy LG into L + FastILUPrec_Functor functorG(lGVal, lGRowMap, lGColIdx, lVal, lRowMap, lColIdx); + Kokkos::RangePolicy copy_policy (0, nRows); + Kokkos::parallel_for( + "numericILU::copyVals(G)", copy_policy, functorG); + ExecSpace().fence(); + } + if (sptrsv_algo == FastILU::SpTRSV::StandardHost) { + // in case calling trsv + lVal_ = Kokkos::create_mirror(lVal); + lColIdx_ = Kokkos::create_mirror(lColIdx); + Kokkos::deep_copy(lColIdx_, lColIdx); + Kokkos::deep_copy(lVal_, lVal); } - Kokkos::deep_copy(lColIdx, lColIdx_); - Kokkos::deep_copy(lVal, lVal_); } + //Initialize rowMap and colIdx arrays of U void countU() { @@ -687,45 +697,28 @@ class FastILUPrec } } } + Kokkos::deep_copy(uRowMap, uRowMap_); + Kokkos::deep_copy(uColIdx, uColIdx_); + Kokkos::deep_copy(uVal, uVal_); + if ((level > 0) && (guessFlag !=0)) { OrdinalArray uGRowMap; OrdinalArray uGColIdx; ScalarArray uGVal; ScalarArray gD; - Ordinal uGPtr = 0; initGuessPrec->getU(uGRowMap, uGColIdx, uGVal); initGuessPrec->getD(gD); - Kokkos::deep_copy(diagElems, gD); - auto uGColIdx_ = Kokkos::create_mirror(uGColIdx); - auto uGVal_ = Kokkos::create_mirror(uGVal); - Kokkos::deep_copy(uGColIdx_, uGColIdx); - Kokkos::deep_copy(uGVal_, uGVal); - for (Ordinal i = 0; i < nRows; i++) - { - #ifdef SHYLU_DEBUG - Ordinal check = uGPtr; - #endif - for (Ordinal k = uRowMap_[i]; k < uRowMap_[i+1]; k++) - { - //unused: Ordinal row = i; - Ordinal col = uColIdx_[k]; - if (col == uGColIdx_[uGPtr]) - { - uVal_[k] = uGVal_[uGPtr]; - uGPtr++; - } - } - #ifdef SHYLU_DEBUG - assert((uGPtr - check) == (uGRowMap[i+1] - uGRowMap[i])); - #endif - } + // copy UG into U + FastILUPrec_Functor functorG(uGVal, uGRowMap, uGColIdx, uVal, uRowMap, uColIdx); + Kokkos::RangePolicy copy_policy (0, nRows); + Kokkos::parallel_for( + "numericILU::copyVals(G)", copy_policy, functorG); + ExecSpace().fence(); } - Kokkos::deep_copy(uColIdx, uColIdx_); - Kokkos::deep_copy(uVal, uVal_); } void getL(OrdinalArray &lRowMapOut, OrdinalArray &lColIdxOut, ScalarArray &lValOut) @@ -763,9 +756,6 @@ class FastILUPrec if (aColIdx_[k] == i) { diagFact_[i] = one/(RTS::sqrt(STS::abs(aVal_[k]))); - #ifdef FASTILU_DEBUG_OUTPUT - std::cout << "diagFact["< 0) { - initGuessPrec = Teuchos::rcp(new FastPrec(aRowMapIn, aColIdxIn, aValIn, nRow_, standard_sptrsv, 3, 5, - level_-1, omega_, shift_, guessFlag_, blkSz_)); + initGuessPrec = Teuchos::rcp(new FastPrec(aRowMapIn_, aColIdxIn_, aValIn_, nRow_, sptrsv_algo_, 3, 5, + level_-1, omega_, shift_, guessFlag_, blkSzILU_, blkSz_)); } } + // internal functors + struct CopySortedValsTag {}; + struct CopyValsTag {}; + struct GetDiagsTag {}; + struct DiagScalTag {}; + + struct GetLowerTag{}; + struct GetUpperTag{}; + struct FastILUPrec_Functor + { + FastILUPrec_Functor(ScalarArray aValIn_, OrdinalArray aRowMapIn_, OrdinalArray aColIdxIn_, + ScalarArray aVal_, RealArray diagFact_, OrdinalArray aRowMap_, OrdinalArray aColIdx_, OrdinalArray aRowIdx_) : + aValIn (aValIn_), + aRowMapIn (aRowMapIn_), + aColIdxIn (aColIdxIn_), + aVal (aVal_), + diagFact (diagFact_), + aRowMap (aRowMap_), + aColIdx (aColIdx_), + aRowIdx (aRowIdx_) + {} + + // just calling CopySortedValsTag + FastILUPrec_Functor(ScalarArray aValIn_, OrdinalArray aRowMapIn_, OrdinalArray aColIdxIn_, + ScalarArray aVal_, OrdinalArray aRowMap_, OrdinalArray aColIdx_) : + aValIn (aValIn_), + aRowMapIn (aRowMapIn_), + aColIdxIn (aColIdxIn_), + aVal (aVal_), + aRowMap (aRowMap_), + aColIdx (aColIdx_) + {} + + // just calling GetLowerTag + FastILUPrec_Functor(ScalarArray aVal_, OrdinalArray aRowMap_, OrdinalArray aColIdx_, + ScalarArray lVal_, OrdinalArray lRowMap_, OrdinalArray lColIdx_, + ScalarArray diagElems_) : + aVal (aVal_), + diagElems (diagElems_), + aRowMap (aRowMap_), + aColIdx (aColIdx_), + lVal (lVal_), + lRowMap (lRowMap_), + lColIdx (lColIdx_) + {} + + // functor to load values + // both matrices are sorted and, "a" (with fills) contains "aIn" (original) + KOKKOS_INLINE_FUNCTION + void operator()(const CopySortedValsTag &, const int i) const { + Ordinal aPtr = aRowMapIn[i]; + for(Ordinal k = aRowMap[i]; k < aRowMap[i+1]; k++) + { + Ordinal col = aColIdx[k]; + if (col == aColIdxIn[aPtr]) + { + aVal[k] = aValIn[aPtr]; + aPtr++; + } + } + } + + // functor to load values + KOKKOS_INLINE_FUNCTION + void operator()(const CopyValsTag &, const int i) const { + for(Ordinal k = aRowMap[i]; k < aRowMap[i+1]; k++) + { + Ordinal col = aColIdx[k]; + for(Ordinal aPtr = aRowMapIn[i]; aPtr < aRowMapIn[i+1]; aPtr++) + { + if (col == aColIdxIn[aPtr]) + { + aVal[k] = aValIn[aPtr]; + break; + } + } + } + + } + + // functor to extract diagonals (inverted) + KOKKOS_INLINE_FUNCTION + void operator()(const GetDiagsTag &, const int i) const { + const Real one = RTS::one(); + for(int k = aRowMap[i]; k < aRowMap[i+1]; k++) + { + aRowIdx[k] = i; + if (aColIdx[k] == i) + { + diagFact[i] = one/(RTS::sqrt(STS::abs(aVal[k]))); + } + } + } + + // functor to apply diagonal scaling + KOKKOS_INLINE_FUNCTION + void operator()(const DiagScalTag &, const int i) const { + for (int k = aRowMap[i]; k < aRowMap[i+1]; k++) + { + int row = aRowIdx[k]; + int col = aColIdx[k]; + + Real sc1 = diagFact[row]; + Real sc2 = diagFact[col]; + aVal[k] = aVal[k]*sc1*sc2; + } + } + + // ---------------------------------------------------------- + // functor to extract L & diagongals + KOKKOS_INLINE_FUNCTION + void operator()(const GetLowerTag &, const int i) const { + Ordinal lPtr = lRowMap[i]; + for (Ordinal k = aRowMap[i]; k < aRowMap[i+1]; k++) + { + Ordinal row = i; + Ordinal col = aColIdx[k]; + + if (row >= col) + { + if (row == col) + { + diagElems[row] = aVal[k]; + } + lVal[lPtr] = aVal[k]; + lColIdx[lPtr] = col; + lPtr++; + } + } + } + + + // member variables + // + input matrix + ScalarArray aValIn; + OrdinalArray aRowMapIn; + OrdinalArray aColIdxIn; + // + output matrix + ScalarArray aVal; + ScalarArray diagElems; + RealArray diagFact; + OrdinalArray aRowMap; + OrdinalArray aColIdx; + OrdinalArray aRowIdx; + // + output L matrix + ScalarArray lVal; + OrdinalArray lRowMap; + OrdinalArray lColIdx; + }; + //Symbolic Factorization Phase void initialize() { @@ -960,13 +1105,14 @@ class FastILUPrec } - void setValues(ScalarArray& aValsIn) + void setValues(ScalarArray& aValIn_) { - this->aValHost = Kokkos::create_mirror(aValsIn); - Kokkos::deep_copy(this->aValHost, aValsIn); + this->aValIn = aValIn_; + this->aValHost = Kokkos::create_mirror(aValIn_); + Kokkos::deep_copy(this->aValHost, aValIn_); if(!initGuessPrec.is_null()) { - initGuessPrec->setValues(aValsIn); + initGuessPrec->setValues(aValIn_); } } @@ -977,12 +1123,24 @@ class FastILUPrec void compute() { Kokkos::Timer timer; + #ifdef FASTILU_TIMER + std::cout << " >> compute <<" << std::endl; + Kokkos::Timer Timer; + Kokkos::Timer Timer2; + #endif if ((level > 0) && (guessFlag !=0)) { initGuessPrec->compute(); } + #ifdef FASTILU_TIMER + std::cout << " > initGuess " << Timer.seconds() << std::endl; + Timer.reset(); + #endif numericILU(); - Ordinal blkSzILU = 4096; + #ifdef FASTILU_TIMER + std::cout << " > numericILU " << Timer.seconds() << std::endl; + Timer.reset(); + #endif FastILUFunctor iluFunctor(aRowMap_[nRows], blkSzILU, aRowMap, aColIdx, aRowIdx, aVal, lRowMap, lColIdx, lVal, uRowMap, uColIdx, uVal, diagElems, omega); @@ -991,22 +1149,29 @@ class FastILUPrec { extent++; } - //Ordinal extent = aRowMap[nRows]; - ExecSpace().fence(); + //ExecSpace().fence(); for (int i = 0; i < nFact; i++) { Kokkos::parallel_for(extent, iluFunctor); } - //ExecSpace().fence(); + ExecSpace().fence(); + #ifdef FASTILU_TIMER + std::cout << " > iluFunctor (" << nFact << ") " << Timer.seconds() << std::endl; + Timer.reset(); + #endif // transposee u on host (need to copy to & from host) double t = timer.seconds(); transposeU(); computeTime = t; + #ifdef FASTILU_TIMER + std::cout << " > transposeU " << Timer.seconds() << std::endl; + Timer.reset(); + #endif - if (standard_sptrsv) { + if (sptrsv_algo == FastILU::SpTRSV::Standard) { #if defined(KOKKOSKERNELS_ENABLE_TPL_CUSPARSE) KokkosSparse::Experimental::SPTRSVAlgorithm algo = KokkosSparse::Experimental::SPTRSVAlgorithm::SPTRSV_CUSPARSE; #else @@ -1026,7 +1191,14 @@ class FastILUPrec #else KokkosSparse::Experimental::sptrsv_symbolic(&khU, utRowMap, utColIdx); #endif + #ifdef FASTILU_TIMER + std::cout << " > sptrsv_symbolic : nnz(L)=" << lColIdx.extent(0) << " nnz(U)=" << utColIdx.extent(0) + << ", " << Timer.seconds() << " seconds" << std::endl; + #endif } + #ifdef FASTILU_TIMER + std::cout << " >> compute done " << Timer2.seconds() << " <<" << std::endl << std::endl; + #endif return; } @@ -1041,10 +1213,38 @@ class FastILUPrec ExecSpace().fence(); Kokkos::parallel_for(nRows, parCopyFunctor); ExecSpace().fence(); - //apply D applyD(x, xTemp); - if (standard_sptrsv) { + if (sptrsv_algo == FastILU::SpTRSV::StandardHost) { + using crsmat_t = KokkosSparse::CrsMatrix; + using graph_t = typename crsmat_t::StaticCrsGraphType; + + // wrap x and y into 2D views + typedef Kokkos::View Scalar2dArray; + Scalar2dArray x2d (const_cast(xTemp.data()), nRows, 1); + Scalar2dArray y2d (const_cast(y.data()), nRows, 1); + auto x_ = Kokkos::create_mirror(x2d); + auto y_ = Kokkos::create_mirror(y2d); + + // wrap L into crsmat on host + graph_t static_graphL(lColIdx_, lRowMap_); + crsmat_t crsmatL("CrsMatrix", nRows, lVal_, static_graphL); + + // wrap U into crsmat on host + graph_t static_graphU(utColIdx_, utRowMap_); + crsmat_t crsmatU("CrsMatrix", nRows, utVal_, static_graphU); + + // copy x to host + Kokkos::deep_copy(x_, x2d); + + // solve with L + KokkosSparse::trsv ("L", "N", "N", crsmatL, x_, y_); + // solve with U + KokkosSparse::trsv ("U", "N", "N", crsmatU, y_, x_); + + // copy x to device + Kokkos::deep_copy(x2d, x_); + } else if (sptrsv_algo == FastILU::SpTRSV::Standard) { // solve with L KokkosSparse::Experimental::sptrsv_solve(&khL, lRowMap, lColIdx, lVal, xTemp, y); // solve with U diff --git a/packages/shylu/shylu_node/fastilu/src/shylu_fastutil.hpp b/packages/shylu/shylu_node/fastilu/src/shylu_fastutil.hpp new file mode 100644 index 000000000000..0c3aa72e6a83 --- /dev/null +++ b/packages/shylu/shylu_node/fastilu/src/shylu_fastutil.hpp @@ -0,0 +1,15 @@ +#ifndef __SHYLU_FASTUTIL_HPP__ +#define __SHYLU_FASTUTIL_HPP__ + +namespace FastILU { + + enum class SpTRSV { + Standard, + StandardHost, + Fast + }; + +} + +#endif + From 52510826c87b1c609ecf21e8a21bd9c60f37fac5 Mon Sep 17 00:00:00 2001 From: iyamazaki Date: Fri, 13 May 2022 03:15:46 -0600 Subject: [PATCH 04/21] ShyLU_node,FastILU : test with SpTRSV on host --- .../belos/5w_bel_tif_FILU_sptrsv_host.xml | 23 +++++++++++++++++++ packages/ifpack2/test/belos/CMakeLists.txt | 9 ++++++++ 2 files changed, 32 insertions(+) create mode 100644 packages/ifpack2/test/belos/5w_bel_tif_FILU_sptrsv_host.xml diff --git a/packages/ifpack2/test/belos/5w_bel_tif_FILU_sptrsv_host.xml b/packages/ifpack2/test/belos/5w_bel_tif_FILU_sptrsv_host.xml new file mode 100644 index 000000000000..9a329752c037 --- /dev/null +++ b/packages/ifpack2/test/belos/5w_bel_tif_FILU_sptrsv_host.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/ifpack2/test/belos/CMakeLists.txt b/packages/ifpack2/test/belos/CMakeLists.txt index 30ff131108a9..09111005f186 100644 --- a/packages/ifpack2/test/belos/CMakeLists.txt +++ b/packages/ifpack2/test/belos/CMakeLists.txt @@ -99,6 +99,7 @@ TRIBITS_COPY_FILES_TO_BINARY_DIR(Ifpack2BelosCopyFiles 5w_bel_tif_ILUT.xml 5w_bel_tif_FILU.xml 5w_bel_tif_FILU_sptrsv.xml + 5w_bel_tif_FILU_sptrsv_host.xml 5w_bel_tif_FILU_schwarz.xml 5w_bel_tif_FIC.xml 5w_bel_tif_FIC_sptrsv.xml @@ -480,6 +481,14 @@ IF(Tpetra_INST_DOUBLE AND Ifpack2_ENABLE_ShyLU_NodeFastILU) NUM_MPI_PROCS 1 STANDARD_PASS_OUTPUT ) + TRIBITS_ADD_TEST( + tif_belos + NAME FILU_5w_sptrsv_host + ARGS "--xml_file=5w_bel_tif_FILU_sptrsv_host.xml" + COMM serial mpi + NUM_MPI_PROCS 1 + STANDARD_PASS_OUTPUT + ) TRIBITS_ADD_TEST( tif_belos NAME FILU_5w_schwarz From 3177373d22504770cb2cdb9f16e6914e478cf729 Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Thu, 12 May 2022 16:48:59 -0600 Subject: [PATCH 05/21] Add CMakeLists.txt for building Intrelab --- .../intrepid/matlab/intrelab/CMakeLists.txt | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 packages/intrepid/matlab/intrelab/CMakeLists.txt diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt new file mode 100644 index 000000000000..57e1aa5fb7bc --- /dev/null +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -0,0 +1,142 @@ +# +# This CMakeLists.txt file configures the Intrepid / Matlab interface. +# +# This interface has dependencies on Trilinos packages. +# +# Note that the Trilinos install can be either a RELEASE +# or a DEBUG install; for performance, the RELEASE install +# is recommended. +# + +PROJECT(Intrelab) +CMAKE_MINIMUM_REQUIRED(VERSION 3.10) + +# --> ACTION: define Trilinos install directory +set(TRILINOS_INSTALL_DIR "/Users/pakuber/Compadre/Trilinos-new/pthread/install_release") +set(CMAKE_PREFIX_PATH ${TRILINOS_INSTALL_DIR} ${CMAKE_PREFIX_PATH}) + +# --> ACTION: define Matlab binary directory +set(MATLAB_BIN_DIR "/Applications/MATLAB_R2020a.app/bin/") + +# --> ACTION: define install directory (full path or relative to the intrelab directory) +set(INST_DIR "install") +set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/${INST_DIR}") + + +FIND_PACKAGE(Trilinos REQUIRED) + +# set Matlab mex path with -largeArrayDims option +set(MEX "${MATLAB_BIN_DIR}/mex") +message(STATUS "MEX: ${MEX}") + +# set compilers to Trilinos compilers +set(CMAKE_CXX_COMPILER ${Trilinos_CXX_COMPILER}) +set(CMAKE_C_COMPILER ${Trilinos_C_COMPILER}) +#set(ENV{CXX} ${CMAKE_CXX_COMPILER}) + +# set flags to Trilinos flags +set(CMAKE_CXX_FLAGS ${Trilinos_CXX_COMPILER_FLAGS}) + +# Trilinos doesn't propagate its C++ standard +set(CMAKE_CXX_STANDARD 17) +set(MEX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") +set(MEX_LDFLAGS "${CMAKE_SHARED_LINKER_FLAGS}") +if (APPLE) + # Trilinos doesn't propagate its sysroot + message(STATUS "${CMAKE_OSX_SYSROOT} Minimum OS X deployment version: ${CMAKE_OSX_DEPLOYMENT_TARGET}") + set(MEX_FLAGS "--sysroot=${CMAKE_OSX_SYSROOT} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET} ${MEX_FLAGS}") + #set(MEX_FLAGS "-isysroot ${MEX_FLAGS}") + set(MEX_LDFLAGS "--sysroot=${CMAKE_OSX_SYSROOT} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET} ${CMAKE_SHARED_LINKER_FLAGS}") + set(MEX_LDFLAGS "--sysroot=${CMAKE_OSX_SYSROOT} ${CMAKE_SHARED_LINKER_FLAGS}") + message(STATUS "link: ${CMAKE_SYSROOT_LINK}") +endif(APPLE) + + +if (Trilinos_INCLUDE_DIRS) + set(Trilinos_INCLUDE_DIRS "-I${Trilinos_INCLUDE_DIRS}") +endif() +if (Trilinos_TPL_INCLUDE_DIRS) + set(Trilinos_TPL_INCLUDE_DIRS "-I${Trilinos_TPL_INCLUDE_DIRS}") +endif() +if (Trilinos_LIBRARY_DIRS) + set(Trilinos_LIBRARY_DIRS "-L${Trilinos_LIBRARY_DIRS}") +endif() +if (Trilinos_TPL_LIBRARY_DIRS) + set(Trilinos_TPL_LIBRARY_DIRS "-L${Trilinos_TPL_LIBRARY_DIRS}") +endif() + +set(l_Trilinos "") +foreach(alib ${Trilinos_LIBRARIES}) + set(l_Trilinos "${l_Trilinos} -l${alib}") +endforeach() +#message(STATUS "${l_Trilinos}") + +#message(STATUS "${Trilinos_TPL_LIBRARIES}") +set(l_Trilinos_TPL "") +foreach(alib ${Trilinos_TPL_LIBRARIES}) + if (APPLE) + string(FIND ${alib} ".tbd" alib_result) + # make sure .tbd not found in library name + else() + set(alib_result -1) + endif(APPLE) + if (alib_result LESS 0) + set(l_Trilinos_TPL "${l_Trilinos_TPL} -l${alib}") + else() + get_filename_component(libname ${alib} NAME_WLE) + string(SUBSTRING ${libname} 3 -1 reduced_libname) + set(l_Trilinos_TPL "${l_Trilinos_TPL} -l${reduced_libname}") + endif() +endforeach() +#message(STATUS "${l_Trilinos_TPL}") + +#set(ll SEPARATE_ARGUMENTS(${l_Trilinos})) +separate_arguments(ll UNIX_COMMAND ${l_Trilinos}) +set(l_Trilinos ${ll}) +#message(STATUS "${ll}") + +#message(STATUS "${Trilinos_TPL_LIBRARIES}") +separate_arguments(ll UNIX_COMMAND ${l_Trilinos_TPL}) +set(l_Trilinos_TPL ${ll}) +#message(STATUS "${ll}") + +if(APPLE) + set(MEX_EXTENSION "mexmaci64") +else() + set(MEX_EXTENSION "mexa64") +endif(APPLE) + +add_custom_target(build_m2i_helpers + ALL + COMMAND "${MEX}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" -c ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp" + BYPRODUCTS m2i_helpers.o + VERBATIM + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + +function(make_mex fname) + + add_custom_target(build_${fname} + ALL + COMMAND "${MEX}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" -c ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp" + BYPRODUCTS ${fname}.o + VERBATIM + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + + add_custom_target(link_${fname} + ALL + #COMMAND "${MEX}" "-v" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} ${Trilinos_LIBRARY_DIRS} ${Trilinos_TPL_LIBRARY_DIRS} ${l_Trilinos} ${l_Trilinos_TPL} "${CMAKE_CURRENT_BINARY_DIR}/${fname}.o" "${CMAKE_CURRENT_BINARY_DIR}/m2i_helpers.o" + #COMMAND "${MEX}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} ${Trilinos_LIBRARY_DIRS} ${Trilinos_TPL_LIBRARY_DIRS} ${l_Trilinos} ${l_Trilinos_TPL} "${CMAKE_CURRENT_BINARY_DIR}/${fname}.o" "${CMAKE_CURRENT_BINARY_DIR}/m2i_helpers.o" + COMMAND "${MEX}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} ${Trilinos_LIBRARY_DIRS} ${Trilinos_TPL_LIBRARY_DIRS} ${l_Trilinos} ${l_Trilinos_TPL} "${CMAKE_CURRENT_BINARY_DIR}/${fname}.o" "${CMAKE_CURRENT_BINARY_DIR}/m2i_helpers.o" + DEPENDS build_${fname} build_m2i_helpers + BYPRODUCTS ${fname}.${MEX_EXTENSION} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + + install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${fname}.${MEX_EXTENSION} DESTINATION ${CMAKE_INSTALL_PREFIX}) + +endfunction(make_mex) + +set(MOBJS "intrepid_setJacobian;intrepid_setJacobianInv;intrepid_setJacobianDet;intrepid_getNumCubaturePoints;intrepid_getCubature;intrepid_getBasisValues;intrepid_computeCellMeasure;intrepid_HGRADtransformGRAD;intrepid_HGRADtransformVALUE;intrepid_multiplyMeasure;intrepid_integrate;intrepid_mapToPhysicalFrame;intrepid_mapToReferenceFrame;intrepid_scalarMultiplyDataField;intrepid_scalarMultiplyDataData;intrepid_dataIntegral;intrepid_evaluate;intrepid_multiplyVectorDataField;intrepid_dotMultiplyDataField;intrepid_vectorMultiplyDataField;intrepid_dotMultiplyDataData;intrepid_computeEdgeMeasure;intrepid_computeFaceMeasure;intrepid_getCellDeviatoricMat;intrepid_getCellVolumetricMat;intrepid_getPhysicalSideNormals;intrepid_mapToReferenceSubcell;intrepid_tensorMultiplyDataData;intrepid_tensorMultiplyDataField;defGrad;evaluateVectorField;evaluateVectorGradField;externalForceElastostaticsTL;geometricBmat;intrepid_det;intrepid_inverse;intrepid_transpose;materialBmat;strainEulerianLagrangian;stress;tangentStiffnessElastostaticsTL;tensorMultiplyDataField;myMatVecProductDataField;myMatVecProductDataData") + +foreach(fname ${MOBJS}) + make_mex(${fname}) +endforeach() From 82ec04966cc8d7c5636f8365ff6d27ffe4c0be26 Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Fri, 13 May 2022 07:56:20 -0600 Subject: [PATCH 06/21] Refactor dependencies to reuse existing compilation work --- .../intrepid/matlab/intrelab/CMakeLists.txt | 63 ++++++++++--------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index 57e1aa5fb7bc..a1ac1569dc32 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -32,7 +32,6 @@ message(STATUS "MEX: ${MEX}") # set compilers to Trilinos compilers set(CMAKE_CXX_COMPILER ${Trilinos_CXX_COMPILER}) set(CMAKE_C_COMPILER ${Trilinos_C_COMPILER}) -#set(ENV{CXX} ${CMAKE_CXX_COMPILER}) # set flags to Trilinos flags set(CMAKE_CXX_FLAGS ${Trilinos_CXX_COMPILER_FLAGS}) @@ -40,15 +39,10 @@ set(CMAKE_CXX_FLAGS ${Trilinos_CXX_COMPILER_FLAGS}) # Trilinos doesn't propagate its C++ standard set(CMAKE_CXX_STANDARD 17) set(MEX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") -set(MEX_LDFLAGS "${CMAKE_SHARED_LINKER_FLAGS}") if (APPLE) # Trilinos doesn't propagate its sysroot message(STATUS "${CMAKE_OSX_SYSROOT} Minimum OS X deployment version: ${CMAKE_OSX_DEPLOYMENT_TARGET}") set(MEX_FLAGS "--sysroot=${CMAKE_OSX_SYSROOT} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET} ${MEX_FLAGS}") - #set(MEX_FLAGS "-isysroot ${MEX_FLAGS}") - set(MEX_LDFLAGS "--sysroot=${CMAKE_OSX_SYSROOT} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET} ${CMAKE_SHARED_LINKER_FLAGS}") - set(MEX_LDFLAGS "--sysroot=${CMAKE_OSX_SYSROOT} ${CMAKE_SHARED_LINKER_FLAGS}") - message(STATUS "link: ${CMAKE_SYSROOT_LINK}") endif(APPLE) @@ -69,9 +63,7 @@ set(l_Trilinos "") foreach(alib ${Trilinos_LIBRARIES}) set(l_Trilinos "${l_Trilinos} -l${alib}") endforeach() -#message(STATUS "${l_Trilinos}") -#message(STATUS "${Trilinos_TPL_LIBRARIES}") set(l_Trilinos_TPL "") foreach(alib ${Trilinos_TPL_LIBRARIES}) if (APPLE) @@ -88,17 +80,12 @@ foreach(alib ${Trilinos_TPL_LIBRARIES}) set(l_Trilinos_TPL "${l_Trilinos_TPL} -l${reduced_libname}") endif() endforeach() -#message(STATUS "${l_Trilinos_TPL}") -#set(ll SEPARATE_ARGUMENTS(${l_Trilinos})) separate_arguments(ll UNIX_COMMAND ${l_Trilinos}) set(l_Trilinos ${ll}) -#message(STATUS "${ll}") -#message(STATUS "${Trilinos_TPL_LIBRARIES}") separate_arguments(ll UNIX_COMMAND ${l_Trilinos_TPL}) set(l_Trilinos_TPL ${ll}) -#message(STATUS "${ll}") if(APPLE) set(MEX_EXTENSION "mexmaci64") @@ -106,30 +93,29 @@ else() set(MEX_EXTENSION "mexa64") endif(APPLE) -add_custom_target(build_m2i_helpers - ALL +# create objs folder +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/objs) +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o COMMAND "${MEX}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" -c ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp" - BYPRODUCTS m2i_helpers.o - VERBATIM - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/objs) function(make_mex fname) - add_custom_target(build_${fname} - ALL + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o COMMAND "${MEX}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" -c ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp" - BYPRODUCTS ${fname}.o - VERBATIM - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/objs + ) - add_custom_target(link_${fname} - ALL - #COMMAND "${MEX}" "-v" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} ${Trilinos_LIBRARY_DIRS} ${Trilinos_TPL_LIBRARY_DIRS} ${l_Trilinos} ${l_Trilinos_TPL} "${CMAKE_CURRENT_BINARY_DIR}/${fname}.o" "${CMAKE_CURRENT_BINARY_DIR}/m2i_helpers.o" - #COMMAND "${MEX}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} ${Trilinos_LIBRARY_DIRS} ${Trilinos_TPL_LIBRARY_DIRS} ${l_Trilinos} ${l_Trilinos_TPL} "${CMAKE_CURRENT_BINARY_DIR}/${fname}.o" "${CMAKE_CURRENT_BINARY_DIR}/m2i_helpers.o" - COMMAND "${MEX}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} ${Trilinos_LIBRARY_DIRS} ${Trilinos_TPL_LIBRARY_DIRS} ${l_Trilinos} ${l_Trilinos_TPL} "${CMAKE_CURRENT_BINARY_DIR}/${fname}.o" "${CMAKE_CURRENT_BINARY_DIR}/m2i_helpers.o" - DEPENDS build_${fname} build_m2i_helpers + add_custom_command(OUTPUT ${fname}.${MEX_EXTENSION} + COMMAND "${MEX}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} ${Trilinos_LIBRARY_DIRS} ${Trilinos_TPL_LIBRARY_DIRS} ${l_Trilinos} ${l_Trilinos_TPL} "${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o" "${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o" + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o BYPRODUCTS ${fname}.${MEX_EXTENSION} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${fname}.${MEX_EXTENSION} DESTINATION ${CMAKE_INSTALL_PREFIX}) @@ -137,6 +123,23 @@ endfunction(make_mex) set(MOBJS "intrepid_setJacobian;intrepid_setJacobianInv;intrepid_setJacobianDet;intrepid_getNumCubaturePoints;intrepid_getCubature;intrepid_getBasisValues;intrepid_computeCellMeasure;intrepid_HGRADtransformGRAD;intrepid_HGRADtransformVALUE;intrepid_multiplyMeasure;intrepid_integrate;intrepid_mapToPhysicalFrame;intrepid_mapToReferenceFrame;intrepid_scalarMultiplyDataField;intrepid_scalarMultiplyDataData;intrepid_dataIntegral;intrepid_evaluate;intrepid_multiplyVectorDataField;intrepid_dotMultiplyDataField;intrepid_vectorMultiplyDataField;intrepid_dotMultiplyDataData;intrepid_computeEdgeMeasure;intrepid_computeFaceMeasure;intrepid_getCellDeviatoricMat;intrepid_getCellVolumetricMat;intrepid_getPhysicalSideNormals;intrepid_mapToReferenceSubcell;intrepid_tensorMultiplyDataData;intrepid_tensorMultiplyDataField;defGrad;evaluateVectorField;evaluateVectorGradField;externalForceElastostaticsTL;geometricBmat;intrepid_det;intrepid_inverse;intrepid_transpose;materialBmat;strainEulerianLagrangian;stress;tangentStiffnessElastostaticsTL;tensorMultiplyDataField;myMatVecProductDataField;myMatVecProductDataData") +# dummy targets to build up dependencies +add_custom_target(m2i_helpers + ALL + COMMAND # left intentionally blank + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o + ) foreach(fname ${MOBJS}) make_mex(${fname}) + # builds dependency chain + add_custom_target(${fname} + ALL + COMMAND # left intentionally blank + #DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${fname}.${MEX_EXTENSION} + DEPENDS m2i_helpers ${fname}.${MEX_EXTENSION} + ) endforeach() + +if(APPLE) + message("\"*.dylib was built for newer macOS version (*.*) than being linked (10.9)\" type warnings can be safely ignored. MEX compiler specifies a -mmacosx-min-version=10.9, which can not be overridden.") +endif(APPLE) From b72d58149e56c08ac86728e80c156d668b4f56a5 Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Fri, 13 May 2022 20:03:52 -0600 Subject: [PATCH 07/21] Remove unneeded '-mmacosx-version-min=' flag --- packages/intrepid/matlab/intrelab/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index a1ac1569dc32..c08d10461a2c 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -41,8 +41,8 @@ set(CMAKE_CXX_STANDARD 17) set(MEX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") if (APPLE) # Trilinos doesn't propagate its sysroot - message(STATUS "${CMAKE_OSX_SYSROOT} Minimum OS X deployment version: ${CMAKE_OSX_DEPLOYMENT_TARGET}") - set(MEX_FLAGS "--sysroot=${CMAKE_OSX_SYSROOT} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET} ${MEX_FLAGS}") + message(STATUS "CMAKE_OSX_SYSROOT: ${CMAKE_OSX_SYSROOT}") + set(MEX_FLAGS "--sysroot=${CMAKE_OSX_SYSROOT} ${MEX_FLAGS}") endif(APPLE) From b0fc8de6dcc5e80650dc34255d6b043b9f36079b Mon Sep 17 00:00:00 2001 From: iyamazaki Date: Sat, 14 May 2022 23:41:04 -0600 Subject: [PATCH 08/21] ShyLU_node,FastILU : replace two boolean parameters "standard triangular solve" and "host standard triangular solve" with a string parameter "triangular solve type" --- .../src/Ifpack2_Details_FastILU_Base_decl.hpp | 3 +++ .../src/Ifpack2_Details_FastILU_Base_def.hpp | 21 ++++++++----------- .../ifpack2/src/Ifpack2_Details_Fic_decl.hpp | 3 +++ .../ifpack2/src/Ifpack2_Details_Fic_def.hpp | 7 +++++++ .../src/Ifpack2_Details_Fildl_decl.hpp | 3 +++ .../ifpack2/src/Ifpack2_Details_Fildl_def.hpp | 7 +++++++ .../ifpack2/src/Ifpack2_Details_Filu_decl.hpp | 3 +++ .../ifpack2/src/Ifpack2_Details_Filu_def.hpp | 7 +++++++ .../test/belos/5w_bel_tif_FIC_schwarz.xml | 2 +- .../test/belos/5w_bel_tif_FIC_sptrsv.xml | 2 +- .../test/belos/5w_bel_tif_FILDL_schwarz.xml | 2 +- .../test/belos/5w_bel_tif_FILDL_sptrsv.xml | 2 +- .../test/belos/5w_bel_tif_FILU_schwarz.xml | 2 +- .../test/belos/5w_bel_tif_FILU_sptrsv.xml | 2 +- .../belos/5w_bel_tif_FILU_sptrsv_host.xml | 2 +- .../test/belos/test_FIC_calore1_mm_sptrsv.xml | 3 +-- .../belos/test_FIC_small_sym_sing_sptrsv.xml | 2 +- .../test_FIC_tfqmr_small_sym_mm_schwarz.xml | 8 +++---- .../test_FIC_tfqmr_small_sym_mm_sptrsv.xml | 2 +- .../belos/test_FILDL_calore1_mm_sptrsv.xml | 2 +- .../test_FILDL_small_sym_sing_sptrsv.xml | 2 +- .../test_FILDL_tfqmr_small_sym_mm_schwarz.xml | 8 +++---- .../test_FILDL_tfqmr_small_sym_mm_sptrsv.xml | 2 +- .../belos/test_FILU_calore1_mm_sptrsv.xml | 2 +- .../belos/test_FILU_small_sym_sing_sptrsv.xml | 2 +- .../test_FILU_tfqmr_small_sym_mm_schwarz.xml | 8 +++---- .../test_FILU_tfqmr_small_sym_mm_sptrsv.xml | 2 +- .../shylu_node/fastilu/src/shylu_fastic.hpp | 8 ++++++- .../shylu_node/fastilu/src/shylu_fastildl.hpp | 8 ++++++- .../shylu_node/fastilu/src/shylu_fastilu.hpp | 15 ++++++++++++- 30 files changed, 98 insertions(+), 44 deletions(-) diff --git a/packages/ifpack2/src/Ifpack2_Details_FastILU_Base_decl.hpp b/packages/ifpack2/src/Ifpack2_Details_FastILU_Base_decl.hpp index b0c43399cfd6..25d1d7a78126 100644 --- a/packages/ifpack2/src/Ifpack2_Details_FastILU_Base_decl.hpp +++ b/packages/ifpack2/src/Ifpack2_Details_FastILU_Base_decl.hpp @@ -163,6 +163,9 @@ template //! Get the "sweeps" parameter virtual int getSweeps() const = 0; + //! Get the name of triangular solve algorithm + virtual std::string getSpTrsvType() const = 0; + //! Get the "triangular solve iterations" parameter virtual int getNTrisol() const = 0; diff --git a/packages/ifpack2/src/Ifpack2_Details_FastILU_Base_def.hpp b/packages/ifpack2/src/Ifpack2_Details_FastILU_Base_def.hpp index 6ea64efa9c85..8f750876346d 100644 --- a/packages/ifpack2/src/Ifpack2_Details_FastILU_Base_def.hpp +++ b/packages/ifpack2/src/Ifpack2_Details_FastILU_Base_def.hpp @@ -294,7 +294,10 @@ std::string FastILU_Base::description os << "Initialized: " << (isInitialized() ? "true" : "false") << ", "; os << "Computed: " << (isComputed() ? "true" : "false") << ", "; os << "Sweeps: " << getSweeps() << ", "; - os << "# of triangular solve iterations: " << getNTrisol() << ", "; + os << "Triangular solve type: " << getSpTrsvType() << ", "; + if (getSpTrsvType() == "Fast") { + os << "# of triangular solve iterations: " << getNTrisol() << ", "; + } if(mat_.is_null()) { os << "Matrix: null"; @@ -364,19 +367,13 @@ Params::Params(const Teuchos::ParameterList& pL, std::string precType) else TYPE_ERROR("sweeps", "int"); } - bool standard_sptrsv = false; - if(pL.isParameter("standard triangular solve")) - { - standard_sptrsv = pL.get("standard triangular solve"); - } - bool standard_sptrsv_host = false; - if(pL.isParameter("host standard triangular solve")) - { - standard_sptrsv_host = pL.get("host standard triangular solve"); + std::string sptrsv_type = "Fast"; + if(pL.isParameter("triangular solve type")) { + sptrsv_type = pL.get ("triangular solve type"); } - if (standard_sptrsv_host) { + if (sptrsv_type == "Standard Host") { sptrsv_algo = FastILU::SpTRSV::StandardHost; - } else if (standard_sptrsv) { + } else if (sptrsv_type == "Standard") { sptrsv_algo = FastILU::SpTRSV::Standard; } diff --git a/packages/ifpack2/src/Ifpack2_Details_Fic_decl.hpp b/packages/ifpack2/src/Ifpack2_Details_Fic_decl.hpp index e3ec25f82992..11b4c3023889 100644 --- a/packages/ifpack2/src/Ifpack2_Details_Fic_decl.hpp +++ b/packages/ifpack2/src/Ifpack2_Details_Fic_decl.hpp @@ -74,6 +74,9 @@ class Fic : public FastILU_Base //! Get the sweeps (\"nFact\") from localPrec_ int getSweeps() const; + //! Get the name of triangular solve algorithm + std::string getSpTrsvType() const; + //! Get the number of triangular solves (\"nTrisol\") from localPrec_ int getNTrisol() const; diff --git a/packages/ifpack2/src/Ifpack2_Details_Fic_def.hpp b/packages/ifpack2/src/Ifpack2_Details_Fic_def.hpp index 220e5756497a..c44432e22768 100644 --- a/packages/ifpack2/src/Ifpack2_Details_Fic_def.hpp +++ b/packages/ifpack2/src/Ifpack2_Details_Fic_def.hpp @@ -67,6 +67,13 @@ getSweeps() const return localPrec_->getNFact(); } +template +std::string Fic:: +getSpTrsvType() const +{ + return localPrec_->getSpTrsvType(); +} + template int Fic:: getNTrisol() const diff --git a/packages/ifpack2/src/Ifpack2_Details_Fildl_decl.hpp b/packages/ifpack2/src/Ifpack2_Details_Fildl_decl.hpp index 8e9b0a919acf..52cf841dedfe 100644 --- a/packages/ifpack2/src/Ifpack2_Details_Fildl_decl.hpp +++ b/packages/ifpack2/src/Ifpack2_Details_Fildl_decl.hpp @@ -74,6 +74,9 @@ class Fildl : public FastILU_Base //! Get the sweeps (\"nFact\") from localPrec_ int getSweeps() const; + //! Get the name of triangular solve algorithm + std::string getSpTrsvType() const; + //! Get the number of triangular solves (\"nTrisol\") from localPrec_ int getNTrisol() const; diff --git a/packages/ifpack2/src/Ifpack2_Details_Fildl_def.hpp b/packages/ifpack2/src/Ifpack2_Details_Fildl_def.hpp index 4dc9a9ee148e..460511686819 100644 --- a/packages/ifpack2/src/Ifpack2_Details_Fildl_def.hpp +++ b/packages/ifpack2/src/Ifpack2_Details_Fildl_def.hpp @@ -67,6 +67,13 @@ getSweeps() const return localPrec_->getNFact(); } +template +std::string Fildl:: +getSpTrsvType() const +{ + return localPrec_->getSpTrsvType(); +} + template int Fildl:: getNTrisol() const diff --git a/packages/ifpack2/src/Ifpack2_Details_Filu_decl.hpp b/packages/ifpack2/src/Ifpack2_Details_Filu_decl.hpp index 5fd2890e8cb2..3a13c2246e4d 100644 --- a/packages/ifpack2/src/Ifpack2_Details_Filu_decl.hpp +++ b/packages/ifpack2/src/Ifpack2_Details_Filu_decl.hpp @@ -74,6 +74,9 @@ class Filu : public FastILU_Base //! Get the sweeps (\"nFact\") from localPrec_ int getSweeps() const; + //! Get the name of triangular solve algorithm + std::string getSpTrsvType() const; + //! Get the number of triangular solves (\"nTrisol\") from localPrec_ int getNTrisol() const; diff --git a/packages/ifpack2/src/Ifpack2_Details_Filu_def.hpp b/packages/ifpack2/src/Ifpack2_Details_Filu_def.hpp index 9c41eb47f46a..4854443e7591 100644 --- a/packages/ifpack2/src/Ifpack2_Details_Filu_def.hpp +++ b/packages/ifpack2/src/Ifpack2_Details_Filu_def.hpp @@ -67,6 +67,13 @@ getSweeps() const return localPrec_->getNFact(); } +template +std::string Filu:: +getSpTrsvType() const +{ + return localPrec_->getSpTrsvType(); +} + template int Filu:: getNTrisol() const diff --git a/packages/ifpack2/test/belos/5w_bel_tif_FIC_schwarz.xml b/packages/ifpack2/test/belos/5w_bel_tif_FIC_schwarz.xml index f79d2db2e6d1..d7e2ed691b1a 100644 --- a/packages/ifpack2/test/belos/5w_bel_tif_FIC_schwarz.xml +++ b/packages/ifpack2/test/belos/5w_bel_tif_FIC_schwarz.xml @@ -21,7 +21,7 @@ - + diff --git a/packages/ifpack2/test/belos/5w_bel_tif_FIC_sptrsv.xml b/packages/ifpack2/test/belos/5w_bel_tif_FIC_sptrsv.xml index 9804931d5e59..5b3cfe8c8b75 100644 --- a/packages/ifpack2/test/belos/5w_bel_tif_FIC_sptrsv.xml +++ b/packages/ifpack2/test/belos/5w_bel_tif_FIC_sptrsv.xml @@ -16,7 +16,7 @@ - + diff --git a/packages/ifpack2/test/belos/5w_bel_tif_FILDL_schwarz.xml b/packages/ifpack2/test/belos/5w_bel_tif_FILDL_schwarz.xml index a439dd43b81a..87347f96d6d9 100644 --- a/packages/ifpack2/test/belos/5w_bel_tif_FILDL_schwarz.xml +++ b/packages/ifpack2/test/belos/5w_bel_tif_FILDL_schwarz.xml @@ -21,7 +21,7 @@ - + diff --git a/packages/ifpack2/test/belos/5w_bel_tif_FILDL_sptrsv.xml b/packages/ifpack2/test/belos/5w_bel_tif_FILDL_sptrsv.xml index 933921f9351e..5a3a77b19133 100644 --- a/packages/ifpack2/test/belos/5w_bel_tif_FILDL_sptrsv.xml +++ b/packages/ifpack2/test/belos/5w_bel_tif_FILDL_sptrsv.xml @@ -16,7 +16,7 @@ - + diff --git a/packages/ifpack2/test/belos/5w_bel_tif_FILU_schwarz.xml b/packages/ifpack2/test/belos/5w_bel_tif_FILU_schwarz.xml index a439dd43b81a..87347f96d6d9 100644 --- a/packages/ifpack2/test/belos/5w_bel_tif_FILU_schwarz.xml +++ b/packages/ifpack2/test/belos/5w_bel_tif_FILU_schwarz.xml @@ -21,7 +21,7 @@ - + diff --git a/packages/ifpack2/test/belos/5w_bel_tif_FILU_sptrsv.xml b/packages/ifpack2/test/belos/5w_bel_tif_FILU_sptrsv.xml index 825008f21a77..62ecabf1ca6b 100644 --- a/packages/ifpack2/test/belos/5w_bel_tif_FILU_sptrsv.xml +++ b/packages/ifpack2/test/belos/5w_bel_tif_FILU_sptrsv.xml @@ -16,7 +16,7 @@ - + diff --git a/packages/ifpack2/test/belos/5w_bel_tif_FILU_sptrsv_host.xml b/packages/ifpack2/test/belos/5w_bel_tif_FILU_sptrsv_host.xml index 9a329752c037..64e9197216c1 100644 --- a/packages/ifpack2/test/belos/5w_bel_tif_FILU_sptrsv_host.xml +++ b/packages/ifpack2/test/belos/5w_bel_tif_FILU_sptrsv_host.xml @@ -16,7 +16,7 @@ - + diff --git a/packages/ifpack2/test/belos/test_FIC_calore1_mm_sptrsv.xml b/packages/ifpack2/test/belos/test_FIC_calore1_mm_sptrsv.xml index 8ef0708c92dc..bbc01de17d4e 100644 --- a/packages/ifpack2/test/belos/test_FIC_calore1_mm_sptrsv.xml +++ b/packages/ifpack2/test/belos/test_FIC_calore1_mm_sptrsv.xml @@ -16,8 +16,7 @@ - - + diff --git a/packages/ifpack2/test/belos/test_FIC_small_sym_sing_sptrsv.xml b/packages/ifpack2/test/belos/test_FIC_small_sym_sing_sptrsv.xml index 8032e9116640..dae03f23b2be 100644 --- a/packages/ifpack2/test/belos/test_FIC_small_sym_sing_sptrsv.xml +++ b/packages/ifpack2/test/belos/test_FIC_small_sym_sing_sptrsv.xml @@ -18,7 +18,7 @@ - + diff --git a/packages/ifpack2/test/belos/test_FIC_tfqmr_small_sym_mm_schwarz.xml b/packages/ifpack2/test/belos/test_FIC_tfqmr_small_sym_mm_schwarz.xml index 163847c54acb..8cac989488ee 100644 --- a/packages/ifpack2/test/belos/test_FIC_tfqmr_small_sym_mm_schwarz.xml +++ b/packages/ifpack2/test/belos/test_FIC_tfqmr_small_sym_mm_schwarz.xml @@ -15,10 +15,10 @@ - - - - + + + + diff --git a/packages/ifpack2/test/belos/test_FIC_tfqmr_small_sym_mm_sptrsv.xml b/packages/ifpack2/test/belos/test_FIC_tfqmr_small_sym_mm_sptrsv.xml index bc8e4909314c..a390d664067a 100644 --- a/packages/ifpack2/test/belos/test_FIC_tfqmr_small_sym_mm_sptrsv.xml +++ b/packages/ifpack2/test/belos/test_FIC_tfqmr_small_sym_mm_sptrsv.xml @@ -13,7 +13,7 @@ - + diff --git a/packages/ifpack2/test/belos/test_FILDL_calore1_mm_sptrsv.xml b/packages/ifpack2/test/belos/test_FILDL_calore1_mm_sptrsv.xml index 98708c92ed6e..205d16e92fd7 100644 --- a/packages/ifpack2/test/belos/test_FILDL_calore1_mm_sptrsv.xml +++ b/packages/ifpack2/test/belos/test_FILDL_calore1_mm_sptrsv.xml @@ -16,7 +16,7 @@ - + diff --git a/packages/ifpack2/test/belos/test_FILDL_small_sym_sing_sptrsv.xml b/packages/ifpack2/test/belos/test_FILDL_small_sym_sing_sptrsv.xml index 0e46871f6c2d..ae937367c530 100644 --- a/packages/ifpack2/test/belos/test_FILDL_small_sym_sing_sptrsv.xml +++ b/packages/ifpack2/test/belos/test_FILDL_small_sym_sing_sptrsv.xml @@ -18,7 +18,7 @@ - + diff --git a/packages/ifpack2/test/belos/test_FILDL_tfqmr_small_sym_mm_schwarz.xml b/packages/ifpack2/test/belos/test_FILDL_tfqmr_small_sym_mm_schwarz.xml index ab50b83a8b74..345b11d7256e 100644 --- a/packages/ifpack2/test/belos/test_FILDL_tfqmr_small_sym_mm_schwarz.xml +++ b/packages/ifpack2/test/belos/test_FILDL_tfqmr_small_sym_mm_schwarz.xml @@ -15,10 +15,10 @@ - - - - + + + + diff --git a/packages/ifpack2/test/belos/test_FILDL_tfqmr_small_sym_mm_sptrsv.xml b/packages/ifpack2/test/belos/test_FILDL_tfqmr_small_sym_mm_sptrsv.xml index 205763a114fc..53c95d0db8d1 100644 --- a/packages/ifpack2/test/belos/test_FILDL_tfqmr_small_sym_mm_sptrsv.xml +++ b/packages/ifpack2/test/belos/test_FILDL_tfqmr_small_sym_mm_sptrsv.xml @@ -13,7 +13,7 @@ - + diff --git a/packages/ifpack2/test/belos/test_FILU_calore1_mm_sptrsv.xml b/packages/ifpack2/test/belos/test_FILU_calore1_mm_sptrsv.xml index 46638a6deddf..8bf0a85bf0b9 100644 --- a/packages/ifpack2/test/belos/test_FILU_calore1_mm_sptrsv.xml +++ b/packages/ifpack2/test/belos/test_FILU_calore1_mm_sptrsv.xml @@ -16,7 +16,7 @@ - + diff --git a/packages/ifpack2/test/belos/test_FILU_small_sym_sing_sptrsv.xml b/packages/ifpack2/test/belos/test_FILU_small_sym_sing_sptrsv.xml index 3a87761eafd2..4dfc4ef6dea3 100644 --- a/packages/ifpack2/test/belos/test_FILU_small_sym_sing_sptrsv.xml +++ b/packages/ifpack2/test/belos/test_FILU_small_sym_sing_sptrsv.xml @@ -18,7 +18,7 @@ - + diff --git a/packages/ifpack2/test/belos/test_FILU_tfqmr_small_sym_mm_schwarz.xml b/packages/ifpack2/test/belos/test_FILU_tfqmr_small_sym_mm_schwarz.xml index ac926d0ac2f3..9a4412d164f4 100644 --- a/packages/ifpack2/test/belos/test_FILU_tfqmr_small_sym_mm_schwarz.xml +++ b/packages/ifpack2/test/belos/test_FILU_tfqmr_small_sym_mm_schwarz.xml @@ -15,10 +15,10 @@ - - - - + + + + diff --git a/packages/ifpack2/test/belos/test_FILU_tfqmr_small_sym_mm_sptrsv.xml b/packages/ifpack2/test/belos/test_FILU_tfqmr_small_sym_mm_sptrsv.xml index 70161f9542a6..cd3efafab90c 100644 --- a/packages/ifpack2/test/belos/test_FILU_tfqmr_small_sym_mm_sptrsv.xml +++ b/packages/ifpack2/test/belos/test_FILU_tfqmr_small_sym_mm_sptrsv.xml @@ -13,7 +13,7 @@ - + diff --git a/packages/shylu/shylu_node/fastilu/src/shylu_fastic.hpp b/packages/shylu/shylu_node/fastilu/src/shylu_fastic.hpp index a5eb74096a66..c4dc2a94b181 100644 --- a/packages/shylu/shylu_node/fastilu/src/shylu_fastic.hpp +++ b/packages/shylu/shylu_node/fastilu/src/shylu_fastic.hpp @@ -53,6 +53,7 @@ #include #include #include +#include #include #include @@ -920,7 +921,12 @@ class FastICPrec { return nFact; } - + + std::string getSpTrsvType() const + { + return (standard_sptrsv ? "Standard" : "Fast"); + } + Ordinal getNTrisol() const { return nTrisol; diff --git a/packages/shylu/shylu_node/fastilu/src/shylu_fastildl.hpp b/packages/shylu/shylu_node/fastilu/src/shylu_fastildl.hpp index 2dfe3f90a05b..d766b4eec855 100644 --- a/packages/shylu/shylu_node/fastilu/src/shylu_fastildl.hpp +++ b/packages/shylu/shylu_node/fastilu/src/shylu_fastildl.hpp @@ -52,6 +52,7 @@ #include #include #include +#include #include #include @@ -903,7 +904,12 @@ class FastILDLPrec { return nFact; } - + + std::string getSpTrsvType() const + { + return (standard_sptrsv ? "Standard" : "Fast"); + } + Ordinal getNTrisol() const { return nTrisol; diff --git a/packages/shylu/shylu_node/fastilu/src/shylu_fastilu.hpp b/packages/shylu/shylu_node/fastilu/src/shylu_fastilu.hpp index 4d83557b6f75..f65600ae6217 100644 --- a/packages/shylu/shylu_node/fastilu/src/shylu_fastilu.hpp +++ b/packages/shylu/shylu_node/fastilu/src/shylu_fastilu.hpp @@ -53,6 +53,7 @@ #include #include #include +#include #include #include @@ -1267,7 +1268,19 @@ class FastILUPrec { return nFact; } - + + std::string getSpTrsvType() const + { + if (sptrsv_algo == FastILU::SpTRSV::StandardHost) { + return "Standard Host"; + } else if (sptrsv_algo == FastILU::SpTRSV::Standard) { + return "Standard"; + } else if (sptrsv_algo == FastILU::SpTRSV::Fast) { + return "Fast"; + } + return "Invalid"; + } + Ordinal getNTrisol() const { return nTrisol; From 571f40191393a2127157ca046739c6eb9cdd8c0d Mon Sep 17 00:00:00 2001 From: iyamazaki Date: Sat, 14 May 2022 23:53:46 -0600 Subject: [PATCH 09/21] ShyLU_node,FastILU : update Ifpack2 documentation with new options --- .../ifpack2/doc/UsersGuide/ifpack2guide.pdf | Bin 812061 -> 810463 bytes packages/ifpack2/doc/UsersGuide/options.tex | 10 +++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/ifpack2/doc/UsersGuide/ifpack2guide.pdf b/packages/ifpack2/doc/UsersGuide/ifpack2guide.pdf index 769ede592e8591ffe0a0f263e9a1fc510a3e53a7..d063b3fabc7648d0a6019b5d07243792708879ea 100644 GIT binary patch delta 73326 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�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 delta 72981 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

USx)U$(D&GkU2e36PThJ9sW{{sKlv}L*@0Z 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 GvHuJBWVieP diff --git a/packages/ifpack2/doc/UsersGuide/options.tex b/packages/ifpack2/doc/UsersGuide/options.tex index 4378f84b21ce..8edd449353d2 100644 --- a/packages/ifpack2/doc/UsersGuide/options.tex +++ b/packages/ifpack2/doc/UsersGuide/options.tex @@ -532,6 +532,10 @@ \subsection{ShyLU FastILU}\label{s:FastILU} {int} {5} {Number of iterations of ILU/IC/ILDL factorization algorithm.} +\ccc{triangular solve type} + {string} + {Fast} + {Type of triangular solve algorithm to use: ``Fast'' for the block Jacobi triangular solver, ``Standard'' for the standard (forward/backward) substitution based triangular solver (calls Kokkos-Kernels {\bf sptrsv}), or "Standard Host" for the standard triangular solver on host CPU (calls Kokkos-Kernels {\bf trsv} on the host).} \ccc{triangular solve iterations} {int} {1} @@ -552,7 +556,11 @@ \subsection{ShyLU FastILU}\label{s:FastILU} {bool} {true} {Whether to run another instance of FastILU/IC/ILDL (but with a lower level of fill) to compute the initial guess (only has an effect if level of fill $> 0$).} -\ccc{block size} +\ccc{block size for ILU} + {int} + {1} + {Block size for the iterative factorization algorithm.} +\ccc{block size for SpTRSV} {int} {1} {Block size for the block Jacobi solver.} From 9777618d42ee279974900fb311af75a0f77ea422 Mon Sep 17 00:00:00 2001 From: iyamazaki Date: Sun, 15 May 2022 02:41:11 -0400 Subject: [PATCH 10/21] ShyLU_node,FastILU : remove std::cout timer --- packages/ifpack2/src/Ifpack2_Details_Filu_def.hpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/ifpack2/src/Ifpack2_Details_Filu_def.hpp b/packages/ifpack2/src/Ifpack2_Details_Filu_def.hpp index 4854443e7591..b08a37e3ffd1 100644 --- a/packages/ifpack2/src/Ifpack2_Details_Filu_def.hpp +++ b/packages/ifpack2/src/Ifpack2_Details_Filu_def.hpp @@ -112,12 +112,8 @@ void Filu:: computeLocalPrec() { //update values in local prec (until compute(), values aren't needed) -Kokkos::Timer timer; localPrec_->setValues(this->localValues_); -std::cout << " * setValues = " << timer.seconds() << std::endl; -timer.reset(); localPrec_->compute(); -std::cout << " * compute = " << timer.seconds() << std::endl; this->computeTime_ = localPrec_->getComputeTime(); } From 30cb15045608caeb0a049aac33d62b5beb0c2195 Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Tue, 17 May 2022 09:39:53 -0600 Subject: [PATCH 11/21] Add -fPIC to CXXFLAGS and merge compile/link steps for MEX --- .../intrepid/matlab/intrelab/CMakeLists.txt | 90 +++++++++++++------ 1 file changed, 64 insertions(+), 26 deletions(-) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index c08d10461a2c..cda480dc8a05 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -12,17 +12,34 @@ PROJECT(Intrelab) CMAKE_MINIMUM_REQUIRED(VERSION 3.10) # --> ACTION: define Trilinos install directory -set(TRILINOS_INSTALL_DIR "/Users/pakuber/Compadre/Trilinos-new/pthread/install_release") -set(CMAKE_PREFIX_PATH ${TRILINOS_INSTALL_DIR} ${CMAKE_PREFIX_PATH}) +#set(TRILINOS_INSTALL_DIR "/Users/pakuber/Compadre/Trilinos-new/pthread/install_release") +set(TRILINOS_INSTALL_DIR "/ascldap/users/pakuber/Compadre/Trilinos-intrelab/build/install") +if(DEFINED ENV{TRILINOS_INSTALL_DIR}) + set(TRILINOS_INSTALL_DIR $ENV{TRILINOS_INSTALL_DIR}) +else() + set(TRILINOS_INSTALL_DIR "/ascldap/users/pakuber/Compadre/Trilinos-intrelab/build/install") +endif() + # --> ACTION: define Matlab binary directory -set(MATLAB_BIN_DIR "/Applications/MATLAB_R2020a.app/bin/") +#set(MATLAB_BIN_DIR "/Applications/MATLAB_R2020a.app/bin/") +if(DEFINED ENV{MATLAB_BIN_DIR}) + set(MATLAB_BIN_DIR $ENV{MATLAB_BIN_DIR}) +else() + set(MATLAB_BIN_DIR "/usr/local/matlab/R2021b/bin/") +endif() # --> ACTION: define install directory (full path or relative to the intrelab directory) set(INST_DIR "install") -set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/${INST_DIR}") +set(CMAKE_PREFIX_PATH ${TRILINOS_INSTALL_DIR} ${CMAKE_PREFIX_PATH}) +if(IS_ABSOLUTE ${INST_DIR}) + set(CMAKE_INSTALL_PREFIX ${INST_DIR}) +else() + set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/${INST_DIR}") +endif() + FIND_PACKAGE(Trilinos REQUIRED) # set Matlab mex path with -largeArrayDims option @@ -38,7 +55,7 @@ set(CMAKE_CXX_FLAGS ${Trilinos_CXX_COMPILER_FLAGS}) # Trilinos doesn't propagate its C++ standard set(CMAKE_CXX_STANDARD 17) -set(MEX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") +set(MEX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -fPIC") if (APPLE) # Trilinos doesn't propagate its sysroot message(STATUS "CMAKE_OSX_SYSROOT: ${CMAKE_OSX_SYSROOT}") @@ -66,18 +83,30 @@ endforeach() set(l_Trilinos_TPL "") foreach(alib ${Trilinos_TPL_LIBRARIES}) - if (APPLE) - string(FIND ${alib} ".tbd" alib_result) - # make sure .tbd not found in library name + # check if library has a "." in it + string(REGEX MATCH "\.*" lib_ext_result ${alib}) + if (lib_ext_result) + + if (APPLE) + string(FIND ${alib} ".tbd" alib_result) + # make sure .tbd not found in library name + else() + string(FIND ${alib} ".so" alib_result) + # make sure .so not found in library name + endif(APPLE) + + if (alib_result LESS 0) + # extension found but not .tbd or .so + message(FATAL_ERROR "${alib} encountered as TPL with unrecognized file extension.") + else() + # remove extension and get library name + get_filename_component(libname ${alib} NAME_WLE) + string(SUBSTRING ${libname} 3 -1 reduced_libname) + set(l_Trilinos_TPL "${l_Trilinos_TPL} -l${reduced_libname}") + endif() else() - set(alib_result -1) - endif(APPLE) - if (alib_result LESS 0) + # no extension on library name set(l_Trilinos_TPL "${l_Trilinos_TPL} -l${alib}") - else() - get_filename_component(libname ${alib} NAME_WLE) - string(SUBSTRING ${libname} 3 -1 reduced_libname) - set(l_Trilinos_TPL "${l_Trilinos_TPL} -l${reduced_libname}") endif() endforeach() @@ -99,20 +128,28 @@ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o COMMAND "${MEX}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" -c ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp" BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/objs) + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/objs + ) function(make_mex fname) add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o - COMMAND "${MEX}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" -c ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp" + COMMAND "${MEX}" "LDFLAGS=-shared" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" -c ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp" BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/objs ) + #add_custom_command(OUTPUT ${fname}.${MEX_EXTENSION} + # COMMAND "${MEX}" "LDFLAGS=-shared" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} ${Trilinos_LIBRARY_DIRS} ${Trilinos_TPL_LIBRARY_DIRS} ${l_Trilinos} ${l_Trilinos_TPL} "${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o" "${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o" + # DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o + # BYPRODUCTS ${fname}.${MEX_EXTENSION} + # WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + # ) + add_custom_command(OUTPUT ${fname}.${MEX_EXTENSION} - COMMAND "${MEX}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} ${Trilinos_LIBRARY_DIRS} ${Trilinos_TPL_LIBRARY_DIRS} ${l_Trilinos} ${l_Trilinos_TPL} "${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o" "${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o" - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o + COMMAND "${MEX}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} ${Trilinos_LIBRARY_DIRS} ${Trilinos_TPL_LIBRARY_DIRS} ${l_Trilinos} ${l_Trilinos_TPL} "${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp" + #DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o BYPRODUCTS ${fname}.${MEX_EXTENSION} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) @@ -124,22 +161,23 @@ endfunction(make_mex) set(MOBJS "intrepid_setJacobian;intrepid_setJacobianInv;intrepid_setJacobianDet;intrepid_getNumCubaturePoints;intrepid_getCubature;intrepid_getBasisValues;intrepid_computeCellMeasure;intrepid_HGRADtransformGRAD;intrepid_HGRADtransformVALUE;intrepid_multiplyMeasure;intrepid_integrate;intrepid_mapToPhysicalFrame;intrepid_mapToReferenceFrame;intrepid_scalarMultiplyDataField;intrepid_scalarMultiplyDataData;intrepid_dataIntegral;intrepid_evaluate;intrepid_multiplyVectorDataField;intrepid_dotMultiplyDataField;intrepid_vectorMultiplyDataField;intrepid_dotMultiplyDataData;intrepid_computeEdgeMeasure;intrepid_computeFaceMeasure;intrepid_getCellDeviatoricMat;intrepid_getCellVolumetricMat;intrepid_getPhysicalSideNormals;intrepid_mapToReferenceSubcell;intrepid_tensorMultiplyDataData;intrepid_tensorMultiplyDataField;defGrad;evaluateVectorField;evaluateVectorGradField;externalForceElastostaticsTL;geometricBmat;intrepid_det;intrepid_inverse;intrepid_transpose;materialBmat;strainEulerianLagrangian;stress;tangentStiffnessElastostaticsTL;tensorMultiplyDataField;myMatVecProductDataField;myMatVecProductDataData") # dummy targets to build up dependencies -add_custom_target(m2i_helpers - ALL - COMMAND # left intentionally blank - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o - ) +#add_custom_target(m2i_helpers +# ALL +# COMMAND # left intentionally blank +# DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o +# ) foreach(fname ${MOBJS}) make_mex(${fname}) # builds dependency chain add_custom_target(${fname} ALL COMMAND # left intentionally blank - #DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${fname}.${MEX_EXTENSION} - DEPENDS m2i_helpers ${fname}.${MEX_EXTENSION} + #DEPENDS m2i_helpers ${fname}.${MEX_EXTENSION} + DEPENDS ${fname}.${MEX_EXTENSION} ) endforeach() if(APPLE) message("\"*.dylib was built for newer macOS version (*.*) than being linked (10.9)\" type warnings can be safely ignored. MEX compiler specifies a -mmacosx-min-version=10.9, which can not be overridden.") endif(APPLE) + From 69df8028a06e4e477ea579382184ba42cac8f17f Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Tue, 17 May 2022 10:34:30 -0600 Subject: [PATCH 12/21] Updated RPATH flags for Linux compilation --- packages/intrepid/matlab/intrelab/CMakeLists.txt | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index cda480dc8a05..bd9d56d3c0f3 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -54,7 +54,6 @@ set(CMAKE_C_COMPILER ${Trilinos_C_COMPILER}) set(CMAKE_CXX_FLAGS ${Trilinos_CXX_COMPILER_FLAGS}) # Trilinos doesn't propagate its C++ standard -set(CMAKE_CXX_STANDARD 17) set(MEX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -fPIC") if (APPLE) # Trilinos doesn't propagate its sysroot @@ -62,6 +61,8 @@ if (APPLE) set(MEX_FLAGS "--sysroot=${CMAKE_OSX_SYSROOT} ${MEX_FLAGS}") endif(APPLE) +list (APPEND CMAKE_INSTALL_RPATH ${Trilinos_LIBRARY_DIRS}) +list (APPEND CMAKE_INSTALL_RPATH ${Trilinos_TPL_LIBRARY_DIRS}) if (Trilinos_INCLUDE_DIRS) set(Trilinos_INCLUDE_DIRS "-I${Trilinos_INCLUDE_DIRS}") @@ -110,6 +111,15 @@ foreach(alib ${Trilinos_TPL_LIBRARIES}) endif() endforeach() +set(MEX_LD_FLAGS "") +if(NOT APPLE) + foreach(rp ${CMAKE_INSTALL_RPATH}) + set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -Wl,-R,${rp}") + endforeach() + set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -Wl,-R,${MATLAB_BIN_DIR}/glnxa64") + set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -Wl,--enable-new-dtags") +endif() + separate_arguments(ll UNIX_COMMAND ${l_Trilinos}) set(l_Trilinos ${ll}) @@ -148,7 +158,7 @@ function(make_mex fname) # ) add_custom_command(OUTPUT ${fname}.${MEX_EXTENSION} - COMMAND "${MEX}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} ${Trilinos_LIBRARY_DIRS} ${Trilinos_TPL_LIBRARY_DIRS} ${l_Trilinos} ${l_Trilinos_TPL} "${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp" + COMMAND "${MEX}" "LDFLAGS=${MEX_LD_FLAGS}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} ${Trilinos_LIBRARY_DIRS} ${Trilinos_TPL_LIBRARY_DIRS} ${l_Trilinos} ${l_Trilinos_TPL} "${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp" #DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o BYPRODUCTS ${fname}.${MEX_EXTENSION} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} From e08c9c86d1c98ecf96a4459cfc053d585ae1d403 Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Tue, 17 May 2022 11:31:25 -0600 Subject: [PATCH 13/21] Fix LDFLAGS setting for MEX call --- packages/intrepid/matlab/intrelab/CMakeLists.txt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index bd9d56d3c0f3..3f2d5c0aaf78 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -16,17 +16,14 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.10) set(TRILINOS_INSTALL_DIR "/ascldap/users/pakuber/Compadre/Trilinos-intrelab/build/install") if(DEFINED ENV{TRILINOS_INSTALL_DIR}) set(TRILINOS_INSTALL_DIR $ENV{TRILINOS_INSTALL_DIR}) -else() - set(TRILINOS_INSTALL_DIR "/ascldap/users/pakuber/Compadre/Trilinos-intrelab/build/install") endif() # --> ACTION: define Matlab binary directory #set(MATLAB_BIN_DIR "/Applications/MATLAB_R2020a.app/bin/") +set(MATLAB_BIN_DIR "/usr/local/matlab/R2021b/bin/") if(DEFINED ENV{MATLAB_BIN_DIR}) set(MATLAB_BIN_DIR $ENV{MATLAB_BIN_DIR}) -else() - set(MATLAB_BIN_DIR "/usr/local/matlab/R2021b/bin/") endif() # --> ACTION: define install directory (full path or relative to the intrelab directory) @@ -111,8 +108,8 @@ foreach(alib ${Trilinos_TPL_LIBRARIES}) endif() endforeach() -set(MEX_LD_FLAGS "") if(NOT APPLE) + set(MEX_LD_FLAGS "LDFLAGS=") foreach(rp ${CMAKE_INSTALL_RPATH}) set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -Wl,-R,${rp}") endforeach() @@ -158,7 +155,7 @@ function(make_mex fname) # ) add_custom_command(OUTPUT ${fname}.${MEX_EXTENSION} - COMMAND "${MEX}" "LDFLAGS=${MEX_LD_FLAGS}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} ${Trilinos_LIBRARY_DIRS} ${Trilinos_TPL_LIBRARY_DIRS} ${l_Trilinos} ${l_Trilinos_TPL} "${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp" + COMMAND "${MEX}" "${MEX_LD_FLAGS}" "CXX=${CMAKE_CXX_COMPILER}" "CXXFLAGS=${MEX_FLAGS}" "-largeArrayDims" ${Trilinos_INCLUDE_DIRS} ${Trilinos_TPL_INCLUDE_DIRS} ${Trilinos_LIBRARY_DIRS} ${Trilinos_TPL_LIBRARY_DIRS} ${l_Trilinos} ${l_Trilinos_TPL} "${CMAKE_CURRENT_SOURCE_DIR}/src/${fname}.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/m2i_helpers.cpp" #DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/objs/${fname}.o ${CMAKE_CURRENT_BINARY_DIR}/objs/m2i_helpers.o BYPRODUCTS ${fname}.${MEX_EXTENSION} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} From 542b891124f12fe757a718ad554f8490d6d23216 Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Tue, 17 May 2022 15:27:12 -0600 Subject: [PATCH 14/21] Modify LDFLAGS for mac --- packages/intrepid/matlab/intrelab/CMakeLists.txt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/intrepid/matlab/intrelab/CMakeLists.txt b/packages/intrepid/matlab/intrelab/CMakeLists.txt index 3f2d5c0aaf78..e0d3be02c82c 100644 --- a/packages/intrepid/matlab/intrelab/CMakeLists.txt +++ b/packages/intrepid/matlab/intrelab/CMakeLists.txt @@ -108,10 +108,17 @@ foreach(alib ${Trilinos_TPL_LIBRARIES}) endif() endforeach() -if(NOT APPLE) +if(APPLE) + if(Trilinos_BUILD_SHARED_LIBS) + set(MEX_LD_FLAGS "LDFLAGS=") + set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -rpath ${Trilinos_INSTALL_DIR}/lib") + set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -rpath ${MATLAB_BIN_DIR}/maci64") + set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -shared") + endif() +else() set(MEX_LD_FLAGS "LDFLAGS=") foreach(rp ${CMAKE_INSTALL_RPATH}) - set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -Wl,-R,${rp}") + set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -Wl,-R,${rp}") endforeach() set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -Wl,-R,${MATLAB_BIN_DIR}/glnxa64") set(MEX_LD_FLAGS "${MEX_LD_FLAGS} -Wl,--enable-new-dtags") From cc76d50bb86f21ec81940223e00d677be2f37c00 Mon Sep 17 00:00:00 2001 From: Alan Williams Date: Wed, 18 May 2022 10:06:11 -0600 Subject: [PATCH 15/21] STK: Snapshot 05-18-22 10:06 --- .../unit_tests/UnitTestEvaluator.cpp | 36 +- .../stk_transfer/IntgTestCopyTransfer.cpp | 12 +- .../stk/stk_io/stk_io/StkMeshIoBroker.cpp | 14 +- .../stk/stk_mesh/stk_mesh/base/BulkData.cpp | 193 +------- .../stk/stk_mesh/stk_mesh/base/BulkData.hpp | 29 +- .../stk_mesh/stk_mesh/base/FieldParallel.cpp | 1 + .../stk_mesh/stk_mesh/base/MeshBuilder.cpp | 45 +- .../stk_mesh/stk_mesh/base/MeshBuilder.hpp | 6 + .../stk/stk_mesh/stk_mesh/base/Selector.hpp | 3 - .../stk_mesh/baseImpl/AuraGhosting.cpp | 233 ++++++++++ .../stk_mesh/baseImpl/AuraGhosting.hpp | 68 +++ .../AuraGhostingDownwardConnectivity.cpp | 91 ++++ .../AuraGhostingDownwardConnectivity.hpp | 58 +++ .../stk_mesh/CommunicateFieldData.cpp | 62 +-- .../stk/stk_simd/stk_simd_view/simd_view.hpp | 25 +- .../ReducedDependencyGeometricTransfer.hpp | 1 + .../stk_unit_test_utils/BulkDataTester.hpp | 12 +- .../stk_unit_test_utils/MeshFixture.hpp | 8 +- .../ReadWriteSidesetTester.hpp | 12 +- .../stk_unit_test_utils/TextMeshDataTypes.hpp | 2 +- .../stk_unit_tests/stk_mesh/UnitTestAura.cpp | 269 +++++------ .../stk_mesh/UnitTestNoUpwardConnectivity.cpp | 240 ++++++++++ .../UnitTestGeometricTransfer.cpp | 18 + .../stk_util/parallel/UnitTestMPICommKey.cpp | 406 ++++++++++++++++ .../parallel/UnitTestMPITagManager.cpp | 434 +++++++++++++++--- .../stk_util/parallel/CommReplacer.cpp | 79 ++++ .../stk_util/parallel/CommReplacer.hpp | 33 ++ .../stk_util/parallel/CommTagInUseList.cpp | 177 +++++++ .../stk_util/parallel/CommTagInUseList.hpp | 73 +++ .../stk_util/parallel/DeletionGroup.cpp | 90 ++++ .../stk_util/parallel/DeletionGroup.hpp | 59 +++ .../stk_util/stk_util/parallel/MPICommKey.cpp | 163 +++++-- .../stk_util/stk_util/parallel/MPICommKey.hpp | 96 +++- .../stk/stk_util/stk_util/parallel/MPITag.cpp | 23 + .../stk/stk_util/stk_util/parallel/MPITag.hpp | 123 +++++ .../stk_util/parallel/MPITagManager.cpp | 184 ++++---- .../stk_util/parallel/MPITagManager.hpp | 166 ++----- .../stk_util/registry/ProductRegistry.cpp | 2 +- 38 files changed, 2773 insertions(+), 773 deletions(-) create mode 100644 packages/stk/stk_mesh/stk_mesh/baseImpl/AuraGhosting.cpp create mode 100644 packages/stk/stk_mesh/stk_mesh/baseImpl/AuraGhosting.hpp create mode 100644 packages/stk/stk_mesh/stk_mesh/baseImpl/AuraGhostingDownwardConnectivity.cpp create mode 100644 packages/stk/stk_mesh/stk_mesh/baseImpl/AuraGhostingDownwardConnectivity.hpp create mode 100644 packages/stk/stk_unit_tests/stk_mesh/UnitTestNoUpwardConnectivity.cpp create mode 100644 packages/stk/stk_unit_tests/stk_util/parallel/UnitTestMPICommKey.cpp create mode 100644 packages/stk/stk_util/stk_util/parallel/CommReplacer.cpp create mode 100644 packages/stk/stk_util/stk_util/parallel/CommReplacer.hpp create mode 100644 packages/stk/stk_util/stk_util/parallel/CommTagInUseList.cpp create mode 100644 packages/stk/stk_util/stk_util/parallel/CommTagInUseList.hpp create mode 100644 packages/stk/stk_util/stk_util/parallel/DeletionGroup.cpp create mode 100644 packages/stk/stk_util/stk_util/parallel/DeletionGroup.hpp create mode 100644 packages/stk/stk_util/stk_util/parallel/MPITag.cpp create mode 100644 packages/stk/stk_util/stk_util/parallel/MPITag.hpp diff --git a/packages/stk/stk_expreval/unit_tests/UnitTestEvaluator.cpp b/packages/stk/stk_expreval/unit_tests/UnitTestEvaluator.cpp index 962829e227a8..c7b275ebd6b5 100644 --- a/packages/stk/stk_expreval/unit_tests/UnitTestEvaluator.cpp +++ b/packages/stk/stk_expreval/unit_tests/UnitTestEvaluator.cpp @@ -45,6 +45,8 @@ namespace { +using ViewInt1DHostType = Kokkos::View; + bool has_variable(const std::vector& variableNames, const std::string& variableName) { @@ -104,26 +106,29 @@ double device_evaluate(const std::string & expression, stk::expreval::Eval eval(expression, arrayOffsetType); eval.parse(); - int variableIndices[10]; - int variableSizes[10]; + auto variableIndicesHost = ViewInt1DHostType("variableIndices", 10); + auto variableSizesHost = ViewInt1DHostType("variableSizes", 10); Kokkos::View variableDeviceValues("device values"); Kokkos::View::HostMirror variableHostValues("input variables"); for (unsigned varIndex = 0; varIndex < boundScalars.size(); ++varIndex) { - variableIndices[varIndex] = eval.get_variable_index(boundScalars[varIndex].varName); - variableSizes[varIndex] = 1; + variableIndicesHost(varIndex) = eval.get_variable_index(boundScalars[varIndex].varName); + variableSizesHost(varIndex) = 1; variableHostValues(varIndex, 0) = boundScalars[varIndex].varValue; } for (unsigned varIndex = 0; varIndex < boundVectors.size(); ++varIndex) { - variableIndices[varIndex + boundScalars.size()] = eval.get_variable_index(boundVectors[varIndex].varName); - variableSizes[varIndex + boundScalars.size()] = boundVectors[varIndex].varValues.size(); + variableIndicesHost(varIndex + boundScalars.size()) = eval.get_variable_index(boundVectors[varIndex].varName); + variableSizesHost(varIndex + boundScalars.size()) = boundVectors[varIndex].varValues.size(); for (unsigned varComponent = 0; varComponent < boundVectors[varIndex].varValues.size(); ++varComponent) { variableHostValues(varIndex + boundScalars.size(), varComponent) = boundVectors[varIndex].varValues[varComponent]; } } + auto variableIndicesDevice = Kokkos::create_mirror_view_and_copy(stk::ngp::MemSpace(), variableIndicesHost); + auto variableSizesDevice = Kokkos::create_mirror_view_and_copy(stk::ngp::MemSpace(), variableSizesHost); Kokkos::deep_copy(variableDeviceValues, variableHostValues); + const unsigned numBoundVariables = boundScalars.size() + boundVectors.size(); auto & parsedEval = eval.get_parsed_eval(); @@ -131,7 +136,7 @@ double device_evaluate(const std::string & expression, Kokkos::parallel_reduce(Kokkos::RangePolicy(0,1), KOKKOS_LAMBDA (const int& i, double& localResult) { stk::expreval::DeviceVariableMap<> deviceVariableMap(parsedEval); for (unsigned varIndex = 0; varIndex < numBoundVariables; ++varIndex) { - deviceVariableMap.bind(variableIndices[varIndex], variableDeviceValues(varIndex, 0), variableSizes[varIndex], 1); + deviceVariableMap.bind(variableIndicesDevice(varIndex), variableDeviceValues(varIndex, 0), variableSizesDevice(varIndex), 1); } localResult = parsedEval.evaluate(deviceVariableMap); }, result); @@ -148,8 +153,8 @@ std::vector threaded_device_evaluate(const std::string & expression, stk::expreval::Eval eval(expression, arrayOffsetType); eval.parse(); - int variableIndices[10]; - int variableSizes[10]; + auto variableIndicesHost = ViewInt1DHostType("variableIndices", 10); + auto variableSizesHost = ViewInt1DHostType("variableSizes", 10); Kokkos::View variableDeviceValues("device values"); Kokkos::View::HostMirror variableHostValues("input variables"); @@ -157,8 +162,8 @@ std::vector threaded_device_evaluate(const std::string & expression, typename Kokkos::View::HostMirror hostResults = Kokkos::create_mirror_view(deviceResults); for (unsigned varIndex = 0; varIndex < boundScalars.size(); ++varIndex) { - variableIndices[varIndex] = eval.get_variable_index(boundScalars[varIndex].varName); - variableSizes[varIndex] = 1; + variableIndicesHost(varIndex) = eval.get_variable_index(boundScalars[varIndex].varName); + variableSizesHost(varIndex) = 1; ThrowRequireMsg(numThreads == boundScalars[varIndex].varValue.size(), "Number of threads doesn't match declared number of threads in scalar bound data"); for (unsigned threadIndex = 0; threadIndex < numThreads; ++threadIndex) { variableHostValues(threadIndex, varIndex, 0) = boundScalars[varIndex].varValue[threadIndex]; @@ -166,8 +171,8 @@ std::vector threaded_device_evaluate(const std::string & expression, } for (unsigned varIndex = 0; varIndex < boundVectors.size(); ++varIndex) { - variableIndices[varIndex + boundScalars.size()] = eval.get_variable_index(boundVectors[varIndex].varName); - variableSizes[varIndex + boundScalars.size()] = boundVectors[varIndex].varValues.size(); + variableIndicesHost(varIndex + boundScalars.size()) = eval.get_variable_index(boundVectors[varIndex].varName); + variableSizesHost(varIndex + boundScalars.size()) = boundVectors[varIndex].varValues.size(); ThrowRequireMsg(numThreads == boundVectors[varIndex].varValues.size(), "Number of threads doesn't match declared number of threads in vector bound data"); for (unsigned threadIndex = 0; threadIndex < numThreads; ++threadIndex) { for (unsigned varComponent = 0; varComponent < boundVectors[varIndex].varValues[threadIndex].size(); ++varComponent) { @@ -176,14 +181,17 @@ std::vector threaded_device_evaluate(const std::string & expression, } } + auto variableIndicesDevice = Kokkos::create_mirror_view_and_copy(stk::ngp::MemSpace(), variableIndicesHost); + auto variableSizesDevice = Kokkos::create_mirror_view_and_copy(stk::ngp::MemSpace(), variableSizesHost); Kokkos::deep_copy(variableDeviceValues, variableHostValues); + const unsigned numBoundVariables = boundScalars.size() + boundVectors.size(); auto & parsedEval = eval.get_parsed_eval(); Kokkos::parallel_for(numThreads, KOKKOS_LAMBDA (const int& i) { stk::expreval::DeviceVariableMap<> deviceVariableMap(parsedEval); for (unsigned varIndex = 0; varIndex < numBoundVariables; ++varIndex) { - deviceVariableMap.bind(variableIndices[varIndex], variableDeviceValues(i, varIndex, 0), variableSizes[varIndex], 1); + deviceVariableMap.bind(variableIndicesDevice(varIndex), variableDeviceValues(i, varIndex, 0), variableSizesDevice(varIndex), 1); } deviceResults(i) = parsedEval.evaluate(deviceVariableMap); }); diff --git a/packages/stk/stk_integration_tests/stk_transfer/IntgTestCopyTransfer.cpp b/packages/stk/stk_integration_tests/stk_transfer/IntgTestCopyTransfer.cpp index 33328a27d9c0..9c6aca8174a0 100644 --- a/packages/stk/stk_integration_tests/stk_transfer/IntgTestCopyTransfer.cpp +++ b/packages/stk/stk_integration_tests/stk_transfer/IntgTestCopyTransfer.cpp @@ -371,9 +371,9 @@ class CopyTransferFixture : public ::testing::Test // if (commOwnsMesh[0]) { - metaA = std::unique_ptr(new stk::mesh::MetaData(spatial_dimension)); + metaA = stk::mesh::MeshBuilder().set_spatial_dimension(spatial_dimension).create_meta_data(); metaA->use_simple_fields(); - meshA = std::unique_ptr(new stk::mesh::BulkData(*metaA, pmSub)); + meshA = stk::mesh::MeshBuilder(pmSub).create(metaA); build_mesh(*metaA, *meshA, info.num_elements, info.num_nodes, info.element_ids, element_ownerA, &info.elem_node_ids[0], info.node_sharingA, info.coordinates, create_faces); } @@ -381,9 +381,9 @@ class CopyTransferFixture : public ::testing::Test // if (commOwnsMesh[1]) { - metaB = std::unique_ptr(new stk::mesh::MetaData(spatial_dimension)); + metaB = stk::mesh::MeshBuilder().set_spatial_dimension(spatial_dimension).create_meta_data(); metaB->use_simple_fields(); - meshB = std::unique_ptr(new stk::mesh::BulkData(*metaB, pmSub)); + meshB = stk::mesh::MeshBuilder(pmSub).create(metaB); build_mesh(*metaB, *meshB, info.num_elements, info.num_nodes, info.element_ids, element_ownerB, &info.elem_node_ids[0], info.node_sharingB, info.coordinates, create_faces); } } @@ -503,9 +503,9 @@ class CopyTransferFixture : public ::testing::Test SearchById copySearch; bool receiverIncludesSharedNodes = false; const size_t spatial_dimension = 3; - std::unique_ptr metaA; + std::shared_ptr metaA; std::unique_ptr meshA; - std::unique_ptr metaB; + std::shared_ptr metaB; std::unique_ptr meshB; ScalarIntField * scalarIntTargetField = nullptr; ScalarDoubleField * scalarDoubleTargetField = nullptr; diff --git a/packages/stk/stk_io/stk_io/StkMeshIoBroker.cpp b/packages/stk/stk_io/stk_io/StkMeshIoBroker.cpp index 6b80182f72e5..029ccd5c94a4 100644 --- a/packages/stk/stk_io/stk_io/StkMeshIoBroker.cpp +++ b/packages/stk/stk_io/stk_io/StkMeshIoBroker.cpp @@ -83,6 +83,7 @@ #include "stk_mesh/base/SideSetEntry.hpp" // for SideSet #include "stk_mesh/base/SidesetUpdater.hpp" // for SidesetUpdater #include "stk_mesh/base/Types.hpp" // for FieldVector, Ent... +#include "stk_mesh/base/MeshBuilder.hpp" #include "stk_topology/topology.hpp" // for operator++, topo... #include "stk_util/parallel/Parallel.hpp" // for parallel_machine... #include "stk_util/parallel/ParallelReduce.hpp" // for all_reduce_max @@ -805,17 +806,10 @@ void StkMeshIoBroker::create_bulk_data() ThrowErrorMsgIf (region==nullptr, "INTERNAL ERROR: Mesh Input Region pointer is NULL in populate_mesh."); - // Check if bulk_data is null; if so, create a new one... if (is_bulk_data_null()) { - stk::mesh::FieldDataManager* fieldDataManager = nullptr; - set_bulk_data(std::shared_ptr( - new stk::mesh::BulkData(meta_data(), - region->get_database()->util().communicator(), - stk::mesh::BulkData::AUTO_AURA, -#ifdef SIERRA_MIGRATION - false, -#endif - fieldDataManager))); + set_bulk_data(stk::mesh::MeshBuilder(region->get_database()->util().communicator()) + .set_aura_option(stk::mesh::BulkData::AUTO_AURA) + .create(meta_data_ptr())); } } diff --git a/packages/stk/stk_mesh/stk_mesh/base/BulkData.cpp b/packages/stk/stk_mesh/stk_mesh/base/BulkData.cpp index 2214c236fed3..d0f8c1964389 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/BulkData.cpp +++ b/packages/stk/stk_mesh/stk_mesh/base/BulkData.cpp @@ -43,6 +43,7 @@ #include "stk_mesh/base/Selector.hpp" // for Selector #include "stk_mesh/base/Types.hpp" // for EntityProc, EntityRank, etc #include "stk_mesh/base/ForEachEntity.hpp" +#include "stk_mesh/baseImpl/AuraGhosting.hpp" #include "stk_mesh/baseImpl/BucketRepository.hpp" // for BucketRepository #include "stk_mesh/baseImpl/Visitors.hpp" #include "stk_mesh/baseImpl/MeshImplUtils.hpp" @@ -337,6 +338,8 @@ BulkData::BulkData(MetaData & mesh_meta_data, #ifdef SIERRA_MIGRATION m_check_invalid_rels(true), #endif + m_createUpwardConnectivity(true), + m_auraGhosting(std::make_shared()), m_entity_comm_map(), m_ghosting(), m_meta_raw_ptr_to_be_deprecated( &mesh_meta_data ), @@ -428,11 +431,15 @@ BulkData::BulkData(std::shared_ptr mesh_meta_data, bool add_fmwk_data, #endif FieldDataManager *field_data_manager, - unsigned bucket_capacity) + unsigned bucket_capacity, + std::shared_ptr auraGhosting, + bool createUpwardConnectivity) : #ifdef SIERRA_MIGRATION m_check_invalid_rels(true), #endif + m_createUpwardConnectivity(createUpwardConnectivity), + m_auraGhosting((auraGhosting!=nullptr ? auraGhosting : std::make_shared())), m_entity_comm_map(), m_ghosting(), m_meta_raw_ptr_to_be_deprecated( mesh_meta_data.get() ), @@ -575,9 +582,7 @@ void BulkData::set_automatic_aura_option(AutomaticAuraOption auraOption, bool ap if (applyImmediately) { modification_begin(); if (m_autoAuraOption == BulkData::NO_AUTO_AURA) { - EntityVector recvAuraEntitiesToRemove; - aura_ghosting().receive_list(recvAuraEntitiesToRemove); - internal_change_ghosting(aura_ghosting(), {}, recvAuraEntitiesToRemove); + m_auraGhosting->remove_aura(*this); } modification_end(); } @@ -2351,7 +2356,7 @@ void BulkData::internal_declare_relation( Entity e_from , // Should be an exact match if relation of local_id already exists (e_to should be the same). bool is_new_relation = internal_declare_relation(e_from, e_to, local_id, permut); - if(is_new_relation) + if(is_new_relation && m_createUpwardConnectivity) { internal_declare_relation(e_to, e_from, local_id, permut); } @@ -3525,118 +3530,6 @@ void BulkData::delete_unneeded_entries_from_the_comm_list() m_entity_comm_list.erase( i , m_entity_comm_list.end() ); } -void BulkData::internal_change_ghosting( Ghosting & ghosting, - EntityProcMapping& entityProcMapping, - const EntityProcMapping& entitySharing) -{ - //------------------------------------ - // Copy ghosting lists into more efficiently edited container. - // The send and receive lists must be in entity rank-order. - - std::vector add_send; - entityProcMapping.fill_vec(add_send); - - //------------------------------------ - // Add the specified entities and their closure to entityProcMapping - - impl::StoreInEntityProcMapping siepm(*this, entityProcMapping); - EntityProcMapping epm(this->get_size_of_entity_index_space()); - impl::OnlyGhostsEPM og(*this, epm, entitySharing); - for ( const EntityProc& entityProc : add_send ) { - og.proc = entityProc.second; - siepm.proc = entityProc.second; - impl::VisitClosureGeneral(*this,entityProc.first,siepm,og); - } - - entityProcMapping.fill_vec(add_send); - - // Synchronize the send and receive list. - // If the send list contains a not-owned entity - // inform the owner and receiver to add that entity - // to their ghost send and receive lists. - - std::vector ghostStatus(get_size_of_entity_index_space(), false); - - stk::mesh::impl::comm_sync_aura_send_recv(*this, add_send, - entityProcMapping, ghostStatus ); - - //------------------------------------ - // Remove the ghost entities that will not remain. - // If the last reference to the receive ghost entity then delete it. - - OrdinalVector addParts; - OrdinalVector removeParts(1, m_ghost_parts[ghosting.ordinal()]->mesh_meta_data_ordinal()); - OrdinalVector scratchOrdinalVec, scratchSpace; - bool removed = false ; - - std::vector comm_ghost ; - for ( EntityCommListInfoVector::reverse_iterator - i = m_entity_comm_list.rbegin() ; i != m_entity_comm_list.rend() ; ++i) { - - if (!i->entity_comm) { - continue; - } - - EntityCommListInfo& entityComm = *i; - if (!entityComm.entity_comm->isGhost) { - continue; - } - - const bool is_owner = parallel_owner_rank(entityComm.entity) == parallel_rank() ; - const bool remove_recv = ( ! is_owner ) && - !ghostStatus[entityComm.entity.local_offset()] && in_receive_ghost(ghosting, entityComm.entity); - - if(is_valid(entityComm.entity)) - { - if ( is_owner ) { - // Is owner, potentially removing ghost-sends - // Have to make a copy - - const PairIterEntityComm ec = ghost_info_range(entityComm.entity_comm->comm_map, ghosting); - comm_ghost.assign( ec.first , ec.second ); - - for ( ; ! comm_ghost.empty() ; comm_ghost.pop_back() ) { - const EntityCommInfo tmp = comm_ghost.back(); - - if (!entityProcMapping.find(entityComm.entity, tmp.proc) ) { - entity_comm_map_erase(entityComm.key, tmp); - } - else { - entityProcMapping.eraseEntityProc(entityComm.entity, tmp.proc); - } - } - } - else if ( remove_recv ) { - entity_comm_map_erase(entityComm.key, ghosting); - internal_change_entity_parts(entityComm.entity, addParts, removeParts, scratchOrdinalVec, scratchSpace); - } - - if ( internal_entity_comm_map(entityComm.entity).empty() ) { - removed = true ; - entityComm.key = EntityKey(); // No longer communicated - if ( remove_recv ) { - ThrowRequireMsg( internal_destroy_entity_with_notification( entityComm.entity, remove_recv ), - "P[" << this->parallel_rank() << "]: FAILED attempt to destroy entity: " - << entity_key(entityComm.entity) ); - } - } - } - } - - // if an entry in the comm_list has the EntityKey() value, it is invalid, - // and removed from the comm_list - - if ( removed ) { - delete_unneeded_entries_from_the_comm_list(); - } - - std::set sendGhosts(EntityLess(*this)); - entityProcMapping.fill_set(sendGhosts); - - const bool isFullRegen = true; - ghost_entities_and_fields(ghosting, sendGhosts, isFullRegen); -} - void BulkData::internal_change_ghosting( Ghosting & ghosting , const std::vector & add_send , @@ -3737,65 +3630,11 @@ void BulkData::internal_change_ghosting( //---------------------------------------------------------------------- //---------------------------------------------------------------------- -void BulkData::fill_list_of_entities_to_send_for_aura_ghosting(EntityProcMapping& sendAuraEntityProcs, - const EntityProcMapping& entitySharing) -{ - const EntityRank end_rank = static_cast(mesh_meta_data().entity_rank_count()); - - // Iterate over all shared entities, ensure that upwardly related - // entities to each shared entity will be ghosted to the sharing proc. - Selector shared = mesh_meta_data().globally_shared_part(); - - std::vector sharingProcs; - impl::for_each_selected_entity_run_no_threads(*this, stk::topology::NODE_RANK, shared, - [&sendAuraEntityProcs, &entitySharing, &sharingProcs, &end_rank] - (const BulkData& bulk, const MeshIndex& meshIndex) { - const Bucket& bucket = *meshIndex.bucket; - const unsigned bucketOrd = meshIndex.bucket_ordinal; - const EntityRank nextHigherRank = stk::topology::EDGE_RANK; - - bulk.comm_shared_procs(bucket[bucketOrd], sharingProcs); - for (const int sharingProc : sharingProcs) { - - for (EntityRank higherRank = nextHigherRank; higherRank < end_rank; ++higherRank) { - const unsigned num_rels = bucket.num_connectivity(bucketOrd, higherRank); - const Entity* rels = bucket.begin(bucketOrd, higherRank); - - for (unsigned r = 0; r < num_rels; ++r) { - stk::mesh::impl::insert_upward_relations(bulk, entitySharing, rels[r], stk::topology::NODE_RANK, sharingProc, sendAuraEntityProcs); - } - } - } - } - ); // for_each_entity_run -} - void BulkData::internal_regenerate_aura() { require_ok_to_modify(); - EntityProcMapping entitySharing(get_size_of_entity_index_space()); - std::vector ranks = {stk::topology::NODE_RANK, stk::topology::EDGE_RANK}; - const MetaData& meta = mesh_meta_data(); - if (meta.side_rank() > stk::topology::EDGE_RANK) { - ranks.push_back(meta.side_rank()); - } - std::vector sharingProcs; - for(EntityRank rank : ranks) { - impl::for_each_selected_entity_run_no_threads(*this, rank, meta.globally_shared_part(), - [&entitySharing, &sharingProcs](const BulkData& bulk, const MeshIndex& meshIndex) { - Entity entity = (*meshIndex.bucket)[meshIndex.bucket_ordinal]; - bulk.comm_shared_procs(entity, sharingProcs); - for(int p : sharingProcs) { - entitySharing.addEntityProc(entity, p); - } - }); - } - - EntityProcMapping entityProcMapping(get_size_of_entity_index_space()); - fill_list_of_entities_to_send_for_aura_ghosting(entityProcMapping, entitySharing); - - internal_change_ghosting(aura_ghosting() , entityProcMapping, entitySharing); + m_auraGhosting->generate_aura(*this); } void BulkData::internal_remove_aura() @@ -3803,9 +3642,7 @@ void BulkData::internal_remove_aura() require_ok_to_modify(); if (m_autoAuraOption == BulkData::NO_AUTO_AURA) { - EntityVector recvAuraEntitiesToRemove; - aura_ghosting().receive_list(recvAuraEntitiesToRemove); - internal_change_ghosting(aura_ghosting(), {}, recvAuraEntitiesToRemove); + m_auraGhosting->remove_aura(*this); m_turningOffAutoAura = false; } } @@ -6505,14 +6342,16 @@ void BulkData::throw_on_mesh_diagnostic_error() m_meshDiagnosticObserver->throw_if_errors_exist(); } -void BulkData::initialize_face_adjacent_element_graph() +bool BulkData::initialize_face_adjacent_element_graph() { - if (m_elemElemGraph == nullptr) + if (m_elemElemGraph == nullptr && m_createUpwardConnectivity) { m_elemElemGraph = new ElemElemGraph(*this); m_elemElemGraphUpdater = std::make_shared(*this,*m_elemElemGraph); register_observer(m_elemElemGraphUpdater, ModificationObserverPriority::STK_INTERNAL); + return true; } + return false; } void BulkData::delete_face_adjacent_element_graph() diff --git a/packages/stk/stk_mesh/stk_mesh/base/BulkData.hpp b/packages/stk/stk_mesh/stk_mesh/base/BulkData.hpp index 4d780c13e254..0d4186dfc415 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/BulkData.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/BulkData.hpp @@ -67,7 +67,6 @@ #include "stk_util/util/ReportHandler.hpp" // for ThrowAssert, etc #include "stk_mesh/base/ModificationSummary.hpp" #include -#include #include "stk_mesh/baseImpl/MeshModification.hpp" #include "stk_mesh/baseImpl/elementGraph/GraphTypes.hpp" #include @@ -79,7 +78,7 @@ namespace stk { namespace mesh { class FieldBase; } } namespace stk { namespace mesh { class MetaData; } } namespace stk { namespace mesh { class Part; } } namespace stk { namespace mesh { class BulkData; } } -namespace stk { namespace mesh { class EntityProcMapping; } } +namespace stk { namespace mesh { namespace impl { class AuraGhosting; } } } namespace stk { namespace mesh { namespace impl { class EntityRepository; } } } namespace stk { namespace mesh { class FaceCreator; } } namespace stk { namespace mesh { class ElemElemGraph; } } @@ -847,7 +846,7 @@ void get_entities(EntityRank rank, Selector const& selector, EntityVector& outpu template std::vector> get_observer_type() const { return notifier.get_observer_type(); } - void initialize_face_adjacent_element_graph(); + bool initialize_face_adjacent_element_graph(); void delete_face_adjacent_element_graph(); stk::mesh::ElemElemGraph& get_face_adjacent_element_graph(); const stk::mesh::ElemElemGraph& get_face_adjacent_element_graph() const; @@ -878,15 +877,16 @@ void get_entities(EntityRank rank, Selector const& selector, EntityVector& outpu void set_large_ids_flag(bool largeIds) { m_supportsLargeIds = largeIds; } protected: //functions - BulkData( std::shared_ptr mesh_meta_data - , ParallelMachine parallel - , enum AutomaticAuraOption auto_aura_option = AUTO_AURA + BulkData(std::shared_ptr mesh_meta_data, + ParallelMachine parallel, + enum AutomaticAuraOption auto_aura_option = AUTO_AURA, #ifdef SIERRA_MIGRATION - , bool add_fmwk_data = false + bool add_fmwk_data = false, #endif - , FieldDataManager *field_dataManager = nullptr - , unsigned bucket_capacity = impl::BucketRepository::default_bucket_capacity - ); + FieldDataManager *field_dataManager = nullptr, + unsigned bucket_capacity = impl::BucketRepository::default_bucket_capacity, + std::shared_ptr auraGhosting = std::shared_ptr(), + bool createUpwardConnectivity = true); Entity declare_entity( EntityRank ent_rank , EntityId ent_id);// Mod Mark @@ -1055,10 +1055,6 @@ void get_entities(EntityRank rank, Selector const& selector, EntityVector& outpu const std::vector & remove_receive, bool add_send_is_globally_empty = false); - void internal_change_ghosting( Ghosting & ghosts, - EntityProcMapping& entityProcMapping, - const EntityProcMapping& entitySharing); - void internal_add_to_ghosting( Ghosting &ghosting, const std::vector &add_send); // Mod Mark template @@ -1190,8 +1186,6 @@ void get_entities(EntityRank rank, Selector const& selector, EntityVector& outpu */ void internal_regenerate_aura(); void internal_remove_aura(); - void fill_list_of_entities_to_send_for_aura_ghosting(EntityProcMapping& send, - const EntityProcMapping& entitySharing); void require_ok_to_modify() const ; void internal_update_fast_comm_maps() const; @@ -1479,6 +1473,7 @@ void get_entities(EntityRank rank, Selector const& selector, EntityVector& outpu friend class stk::mesh::Bucket; // for field callback friend class Ghosting; // friend until Ghosting is refactored to be like Entity friend class ::stk::mesh::impl::MeshModification; + friend class ::stk::mesh::impl::AuraGhosting; friend class ::stk::mesh::FaceCreator; friend class ::stk::mesh::EntityLess; friend class ::stk::io::StkMeshIoBroker; @@ -1544,6 +1539,8 @@ void get_entities(EntityRank rank, Selector const& selector, EntityVector& outpu mutable bool m_check_invalid_rels; // TODO REMOVE protected: //data + bool m_createUpwardConnectivity = true; + std::shared_ptr m_auraGhosting; mutable ModificationNotifier notifier; static const uint16_t orphaned_node_marking; EntityCommDatabase m_entity_comm_map; diff --git a/packages/stk/stk_mesh/stk_mesh/base/FieldParallel.cpp b/packages/stk/stk_mesh/stk_mesh/base/FieldParallel.cpp index d67af7495295..15b17990ebbf 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/FieldParallel.cpp +++ b/packages/stk/stk_mesh/stk_mesh/base/FieldParallel.cpp @@ -528,6 +528,7 @@ void parallel_op_impl(const BulkData& mesh, std::vector fields }; MPI_Comm comm = mesh.parallel(); + std::cout << "mesh comm = " << comm << ", rank " << stk::parallel_machine_rank(comm) << " of " << stk::parallel_machine_size(comm) << std::endl; stk::parallel_data_exchange_sym_pack_unpack(comm, comm_procs, msgPacker, msgUnpacker, deterministic); } diff --git a/packages/stk/stk_mesh/stk_mesh/base/MeshBuilder.cpp b/packages/stk/stk_mesh/stk_mesh/base/MeshBuilder.cpp index 60911023b137..c89e6489af1c 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/MeshBuilder.cpp +++ b/packages/stk/stk_mesh/stk_mesh/base/MeshBuilder.cpp @@ -34,12 +34,14 @@ #include #include +#include namespace stk { namespace mesh { MeshBuilder::MeshBuilder() : m_comm(MPI_COMM_NULL), + m_haveComm(false), m_auraOption(BulkData::AUTO_AURA), m_addFmwkData(false), m_fieldDataManager(nullptr), @@ -51,12 +53,14 @@ MeshBuilder::MeshBuilder() MeshBuilder::MeshBuilder(ParallelMachine comm) : m_comm(comm), + m_haveComm(true), m_auraOption(BulkData::AUTO_AURA), m_addFmwkData(false), m_fieldDataManager(nullptr), m_bucketCapacity(impl::BucketRepository::default_bucket_capacity), m_spatialDimension(0), - m_entityRankNames() + m_entityRankNames(), + m_upwardConnectivity(true) { } @@ -75,6 +79,7 @@ MeshBuilder& MeshBuilder::set_entity_rank_names(const std::vector& MeshBuilder& MeshBuilder::set_communicator(ParallelMachine comm) { m_comm = comm; + m_haveComm = true; return *this; } @@ -102,6 +107,12 @@ MeshBuilder& MeshBuilder::set_bucket_capacity(unsigned bucketCapacity) return *this; } +MeshBuilder& MeshBuilder::set_upward_connectivity(bool onOrOff) +{ + m_upwardConnectivity = onOrOff; + return *this; +} + std::shared_ptr MeshBuilder::create_meta_data() { if (m_spatialDimension > 0 || !m_entityRankNames.empty()) { @@ -111,27 +122,33 @@ std::shared_ptr MeshBuilder::create_meta_data() return std::make_shared(); } -std::unique_ptr MeshBuilder::create() -{ - return create(create_meta_data()); -} - -void verify_valid_communicator(MPI_Comm comm) +std::shared_ptr MeshBuilder::create_aura_ghosting() { - ThrowRequireMsg(MPI_COMM_NULL != comm, "MeshBuilder must have a valid communicator before creating BulkData."); + if (m_upwardConnectivity) { + return std::make_shared(); + } + return std::make_shared(); } std::unique_ptr MeshBuilder::create(std::shared_ptr metaData) { - verify_valid_communicator(m_comm); + ThrowRequireMsg(m_haveComm, "MeshBuilder must be given an MPI communicator before creating BulkData"); - return std::unique_ptr(new BulkData(metaData, m_comm, m_auraOption, + return std::unique_ptr(new BulkData(metaData, + m_comm, + m_auraOption, #ifdef SIERRA_MIGRATION - m_addFmwkData, + m_addFmwkData, #endif - m_fieldDataManager, - m_bucketCapacity - )); + m_fieldDataManager, + m_bucketCapacity, + create_aura_ghosting(), + m_upwardConnectivity)); +} + +std::unique_ptr MeshBuilder::create() +{ + return create(create_meta_data()); } } diff --git a/packages/stk/stk_mesh/stk_mesh/base/MeshBuilder.hpp b/packages/stk/stk_mesh/stk_mesh/base/MeshBuilder.hpp index 70a1a5de245a..edbfbb59b03a 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/MeshBuilder.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/MeshBuilder.hpp @@ -58,19 +58,25 @@ class MeshBuilder MeshBuilder& set_field_data_manager(FieldDataManager* fieldDataManager); MeshBuilder& set_bucket_capacity(unsigned bucketCapacity); + MeshBuilder& set_upward_connectivity(bool onOrOff); + std::unique_ptr create(); std::unique_ptr create(std::shared_ptr metaData); std::shared_ptr create_meta_data(); private: + std::shared_ptr create_aura_ghosting(); + ParallelMachine m_comm; + bool m_haveComm; BulkData::AutomaticAuraOption m_auraOption; bool m_addFmwkData; FieldDataManager* m_fieldDataManager; unsigned m_bucketCapacity; unsigned m_spatialDimension; std::vector m_entityRankNames; + bool m_upwardConnectivity; }; } diff --git a/packages/stk/stk_mesh/stk_mesh/base/Selector.hpp b/packages/stk/stk_mesh/stk_mesh/base/Selector.hpp index 760ba1f625c7..5fc1d29ee4b7 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/Selector.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/Selector.hpp @@ -211,14 +211,11 @@ class Selector { Selector & operator &= ( const Selector & selector) { return add_binary_op(SelectorNodeType::INTERSECTION, selector); } -// Remove once Fmwk::MeshPart no longer exists -#ifdef SIERRA_MIGRATION Selector & operator &= ( const Part& part) { return add_binary_op(SelectorNodeType::INTERSECTION, Selector(part)); } Selector & operator |= ( const Part& part ) { return operator|=(Selector(part)); } -#endif /** \brief Union: this = this UNION ( expression ) */ Selector & operator |= ( const Selector & selector) diff --git a/packages/stk/stk_mesh/stk_mesh/baseImpl/AuraGhosting.cpp b/packages/stk/stk_mesh/stk_mesh/baseImpl/AuraGhosting.cpp new file mode 100644 index 000000000000..bb5018e7cb90 --- /dev/null +++ b/packages/stk/stk_mesh/stk_mesh/baseImpl/AuraGhosting.cpp @@ -0,0 +1,233 @@ +// 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 +#include + +namespace stk { +namespace mesh { +namespace impl { + +AuraGhosting::AuraGhosting() +{ +} + +AuraGhosting::~AuraGhosting() +{ +} + +void AuraGhosting::generate_aura(BulkData& bulkData) +{ + EntityProcMapping entitySharing(bulkData.get_size_of_entity_index_space()); + std::vector ranks = {stk::topology::NODE_RANK, stk::topology::EDGE_RANK}; + const MetaData& meta = bulkData.mesh_meta_data(); + if (meta.side_rank() > stk::topology::EDGE_RANK) { + ranks.push_back(meta.side_rank()); + } + std::vector sharingProcs; + for(EntityRank rank : ranks) { + impl::for_each_selected_entity_run_no_threads(bulkData, rank, meta.globally_shared_part(), + [&entitySharing, &sharingProcs](const BulkData& bulk, const MeshIndex& meshIndex) { + Entity entity = (*meshIndex.bucket)[meshIndex.bucket_ordinal]; + bulk.comm_shared_procs(entity, sharingProcs); + for(int p : sharingProcs) { + entitySharing.addEntityProc(entity, p); + } + }); + } + + EntityProcMapping sendAuraEntityProcs(bulkData.get_size_of_entity_index_space()); + fill_send_aura_entities(bulkData, sendAuraEntityProcs, entitySharing); + + change_ghosting(bulkData, sendAuraEntityProcs, entitySharing); +} + +void AuraGhosting::remove_aura(BulkData& bulkData) +{ + EntityVector recvAuraEntitiesToRemove; + bulkData.aura_ghosting().receive_list(recvAuraEntitiesToRemove); + bulkData.internal_change_ghosting(bulkData.aura_ghosting(), {}, recvAuraEntitiesToRemove); +} + +void AuraGhosting::fill_send_aura_entities(BulkData& bulkData, + EntityProcMapping& sendAuraEntityProcs, + const EntityProcMapping& entitySharing) +{ + const EntityRank end_rank = static_cast(bulkData.mesh_meta_data().entity_rank_count()); + + // Iterate over all shared entities, ensure that upwardly related + // entities to each shared entity will be ghosted to the sharing proc. + Selector shared = bulkData.mesh_meta_data().globally_shared_part(); + + std::vector sharingProcs; + impl::for_each_selected_entity_run_no_threads(bulkData, stk::topology::NODE_RANK, shared, + [&sendAuraEntityProcs, &entitySharing, &sharingProcs, &end_rank] + (const BulkData& bulk, const MeshIndex& meshIndex) { + const Bucket& bucket = *meshIndex.bucket; + const unsigned bucketOrd = meshIndex.bucket_ordinal; + const EntityRank nextHigherRank = stk::topology::EDGE_RANK; + + bulk.comm_shared_procs(bucket[bucketOrd], sharingProcs); + for (const int sharingProc : sharingProcs) { + + for (EntityRank higherRank = nextHigherRank; higherRank < end_rank; ++higherRank) { + const unsigned num_rels = bucket.num_connectivity(bucketOrd, higherRank); + const Entity* rels = bucket.begin(bucketOrd, higherRank); + + for (unsigned r = 0; r < num_rels; ++r) { + stk::mesh::impl::insert_upward_relations(bulk, entitySharing, rels[r], stk::topology::NODE_RANK, sharingProc, sendAuraEntityProcs); + } + } + } + } + ); // for_each_entity_run +} + +void AuraGhosting::change_ghosting(BulkData& bulkData, + EntityProcMapping& sendAuraEntityProcs, + const EntityProcMapping& entitySharing) +{ + std::vector add_send; + sendAuraEntityProcs.fill_vec(add_send); + + //------------------------------------ + // Add the specified entities and their closure to sendAuraEntityProcs + + impl::StoreInEntityProcMapping siepm(bulkData, sendAuraEntityProcs); + EntityProcMapping epm(bulkData.get_size_of_entity_index_space()); + impl::OnlyGhostsEPM og(bulkData, epm, entitySharing); + for ( const EntityProc& entityProc : add_send ) { + og.proc = entityProc.second; + siepm.proc = entityProc.second; + impl::VisitClosureGeneral(bulkData,entityProc.first,siepm,og); + } + + sendAuraEntityProcs.fill_vec(add_send); + + // Synchronize the send and receive list. + // If the send list contains a not-owned entity + // inform the owner and receiver to add that entity + // to their ghost send and receive lists. + + std::vector ghostStatus(bulkData.get_size_of_entity_index_space(), false); + + stk::mesh::impl::comm_sync_aura_send_recv(bulkData, add_send, + sendAuraEntityProcs, ghostStatus ); + + //------------------------------------ + // Remove the ghost entities that will not remain. + // If the last reference to the receive ghost entity then delete it. + + OrdinalVector addParts; + OrdinalVector removeParts(1, bulkData.m_ghost_parts[BulkData::AURA]->mesh_meta_data_ordinal()); + OrdinalVector scratchOrdinalVec, scratchSpace; + bool removed = false ; + + std::vector comm_ghost ; + for ( EntityCommListInfoVector::reverse_iterator + i = bulkData.m_entity_comm_list.rbegin() ; i != bulkData.m_entity_comm_list.rend() ; ++i) { + + if (!i->entity_comm) { + continue; + } + + EntityCommListInfo& entityComm = *i; + if (!entityComm.entity_comm->isGhost) { + continue; + } + + const bool is_owner = bulkData.parallel_owner_rank(entityComm.entity) == bulkData.parallel_rank() ; + const bool remove_recv = ( ! is_owner ) && + !ghostStatus[entityComm.entity.local_offset()] && bulkData.in_receive_ghost(bulkData.aura_ghosting(), entityComm.entity); + + if(bulkData.is_valid(entityComm.entity)) + { + if ( is_owner ) { + // Is owner, potentially removing ghost-sends + // Have to make a copy + + const PairIterEntityComm ec = ghost_info_range(entityComm.entity_comm->comm_map, bulkData.aura_ghosting()); + comm_ghost.assign( ec.first , ec.second ); + + for ( ; ! comm_ghost.empty() ; comm_ghost.pop_back() ) { + const EntityCommInfo tmp = comm_ghost.back(); + + if (!sendAuraEntityProcs.find(entityComm.entity, tmp.proc) ) { + bulkData.entity_comm_map_erase(entityComm.key, tmp); + } + else { + sendAuraEntityProcs.eraseEntityProc(entityComm.entity, tmp.proc); + } + } + } + else if ( remove_recv ) { + bulkData.entity_comm_map_erase(entityComm.key, bulkData.aura_ghosting()); + bulkData.internal_change_entity_parts(entityComm.entity, addParts, removeParts, scratchOrdinalVec, scratchSpace); + } + + if ( bulkData.internal_entity_comm_map(entityComm.entity).empty() ) { + removed = true ; + entityComm.key = EntityKey(); // No longer communicated + if ( remove_recv ) { + ThrowRequireMsg( bulkData.internal_destroy_entity_with_notification( entityComm.entity, remove_recv ), + "P[" << bulkData.parallel_rank() << "]: FAILED attempt to destroy entity: " + << bulkData.entity_key(entityComm.entity) ); + } + } + } + } + + // if an entry in the comm_list has the EntityKey() value, it is invalid, + // and removed from the comm_list + + if ( removed ) { + bulkData.delete_unneeded_entries_from_the_comm_list(); + } + + EntityLess entityLess(bulkData); + std::set finalSendGhosts(entityLess); + sendAuraEntityProcs.fill_set(finalSendGhosts); + + const bool isFullRegen = true; + bulkData.ghost_entities_and_fields(bulkData.aura_ghosting(), finalSendGhosts, isFullRegen); +} + +}}} // end namepsace stk mesh impl + diff --git a/packages/stk/stk_mesh/stk_mesh/baseImpl/AuraGhosting.hpp b/packages/stk/stk_mesh/stk_mesh/baseImpl/AuraGhosting.hpp new file mode 100644 index 000000000000..fe0a80368dce --- /dev/null +++ b/packages/stk/stk_mesh/stk_mesh/baseImpl/AuraGhosting.hpp @@ -0,0 +1,68 @@ +// 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_mesh_impl_AuraGhosting_hpp +#define stk_mesh_impl_AuraGhosting_hpp + +namespace stk { +namespace mesh { + +class BulkData; +class EntityProcMapping; + +namespace impl { + +class AuraGhosting +{ +public: + AuraGhosting(); + virtual ~AuraGhosting(); + + virtual void generate_aura(BulkData& bulkData); + virtual void remove_aura(BulkData& bulkData); + +protected: + virtual void fill_send_aura_entities(BulkData& bulkData, + EntityProcMapping& sendAuraEntityProcs, + const EntityProcMapping& entitySharing); + + virtual void change_ghosting(BulkData& bulkData, + EntityProcMapping& entityProcMapping, + const EntityProcMapping& entitySharing); +}; + +}}} // end namepsace stk mesh impl + + +#endif diff --git a/packages/stk/stk_mesh/stk_mesh/baseImpl/AuraGhostingDownwardConnectivity.cpp b/packages/stk/stk_mesh/stk_mesh/baseImpl/AuraGhostingDownwardConnectivity.cpp new file mode 100644 index 000000000000..c626aa0a71c0 --- /dev/null +++ b/packages/stk/stk_mesh/stk_mesh/baseImpl/AuraGhostingDownwardConnectivity.cpp @@ -0,0 +1,91 @@ +// 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 +#include + +namespace stk { +namespace mesh { +namespace impl { + +AuraGhostingDownwardConnectivity::AuraGhostingDownwardConnectivity() + : AuraGhosting() +{ +} + +AuraGhostingDownwardConnectivity::~AuraGhostingDownwardConnectivity() +{ +} + +void AuraGhostingDownwardConnectivity::generate_aura(BulkData& bulkData) +{ + EntityProcMapping entitySharing(bulkData.get_size_of_entity_index_space()); + EntityProcMapping sendAuraEntityProcs(bulkData.get_size_of_entity_index_space()); + const MetaData& meta = bulkData.mesh_meta_data(); + + std::vector sharingProcs; + for(EntityRank rank : {stk::topology::ELEM_RANK, stk::topology::CONSTRAINT_RANK}) { + impl::for_each_selected_entity_run_no_threads(bulkData, rank, meta.locally_owned_part(), + [&entitySharing, &sendAuraEntityProcs, &sharingProcs](const BulkData& bulk, const MeshIndex& meshIndex) { + Entity entity = (*meshIndex.bucket)[meshIndex.bucket_ordinal]; + for(EntityRank lowerRank : {stk::topology::NODE_RANK, stk::topology::EDGE_RANK, stk::topology::FACE_RANK}) { + const unsigned numConn = bulk.num_connectivity(entity, lowerRank); + const Entity* conn = bulk.begin(entity, lowerRank); + + for(unsigned i=0; i + +namespace stk { +namespace mesh { + +namespace impl { + +class AuraGhostingDownwardConnectivity : public AuraGhosting +{ +public: + AuraGhostingDownwardConnectivity(); + + virtual void generate_aura(BulkData& bulkData); + + virtual ~AuraGhostingDownwardConnectivity(); +}; + +}}} // end namepsace stk mesh impl + + +#endif diff --git a/packages/stk/stk_performance_tests/stk_mesh/CommunicateFieldData.cpp b/packages/stk/stk_performance_tests/stk_mesh/CommunicateFieldData.cpp index 346441165527..539bb9a98e68 100644 --- a/packages/stk/stk_performance_tests/stk_mesh/CommunicateFieldData.cpp +++ b/packages/stk/stk_performance_tests/stk_mesh/CommunicateFieldData.cpp @@ -38,12 +38,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include // for StkMeshIoBroker #include // for count_entities @@ -112,11 +114,11 @@ void createMetaAndBulkData(stk::io::StkMeshIoBroker &exodusFileReader, std::stri } exodusFileReader.create_input_mesh(); - stk::mesh::MetaData &stkMeshMetaData = exodusFileReader.meta_data(); - createNodalVectorFields(stkMeshMetaData); + std::shared_ptr stkMeshMetaData = exodusFileReader.meta_data_ptr(); + createNodalVectorFields(*stkMeshMetaData); - auto arg_bulk_data(new stk::mesh::BulkData(stkMeshMetaData, MPI_COMM_WORLD, stk::mesh::BulkData::AUTO_AURA, false, NULL)); - exodusFileReader.set_bulk_data(*arg_bulk_data); + std::shared_ptr arg_bulk_data = stk::mesh::MeshBuilder(MPI_COMM_WORLD).set_aura_option(stk::mesh::BulkData::AUTO_AURA).create(stkMeshMetaData); + exodusFileReader.set_bulk_data(arg_bulk_data); stk::mesh::BulkData& stkMeshBulkData = *arg_bulk_data; bool delay_field_data_allocation = true; @@ -145,7 +147,7 @@ void createMetaAndBulkData(stk::io::StkMeshIoBroker &exodusFileReader, std::stri std::cerr << "Finished Reading Mesh" << std::endl; } - stk::mesh::Selector allEntities = stkMeshMetaData.universal_part(); + stk::mesh::Selector allEntities = stkMeshMetaData->universal_part(); std::vector entityCounts; stk::mesh::count_entities(allEntities, stkMeshBulkData, entityCounts); size_t numElements = entityCounts[stk::topology::ELEMENT_RANK]; @@ -187,7 +189,8 @@ void test_communicate_field_data_all_ghosting(stk::mesh::BulkData& mesh, int num const_fields[i] = fields[i]; } - double start_time = stk::cpu_time(); + stk::performance_tests::Timer timer(mesh.parallel()); + timer.start_timing(); for(int iter=0; iter(&stk_comm_time_with_loop), static_cast(&max_time_with_loop), 1, MPI_DOUBLE, MPI_MAX, 0 /*root*/, mesh.parallel()); - MPI_Reduce(static_cast(&stk_comm_time_bulk), static_cast(&max_time_bulk), 1, MPI_DOUBLE, MPI_MAX, 0 /*root*/, mesh.parallel()); + timer.update_timing(); - if ( my_proc == 0 ) { - std::cerr << "Time to do communicate_field_data with loop: " << max_time_with_loop << std::endl; - std::cerr << "Time to do communicate_field_data with bulk: " << max_time_bulk << std::endl; - } - - stk::parallel_print_time_for_performance_compare(mesh.parallel(), stk_comm_time_bulk); + timer.print_timing(num_iters); } void test_communicate_field_data_ghosting(stk::mesh::BulkData& mesh, const stk::mesh::Ghosting& ghosting, int num_iters) @@ -231,21 +221,15 @@ void test_communicate_field_data_ghosting(stk::mesh::BulkData& mesh, const stk:: const_fields[i] = fields[i]; } - double start_time = stk::cpu_time(); + stk::performance_tests::Timer timer(mesh.parallel()); + timer.start_timing(); for(int iter=0; iter(&stk_comm_time), static_cast(&max_time), 1, MPI_DOUBLE, MPI_MAX, 0 /*root*/, MPI_COMM_WORLD); - - if ( my_proc == 0 ) { - std::cerr << "Time to do communicate_field_data ("<(*field)); } - double startTime = 0.0; - double cumulativeTime = 0.0; + stk::performance_tests::Timer timer(mesh.parallel()); + timer.start_timing(); for(int iter=0; iter(ngpFields); } - startTime = stk::wall_time(); stk::mesh::communicate_field_data(mesh, ngpFields, true, true); - cumulativeTime += stk::wall_time() - startTime; } - double max_time=0; - MPI_Reduce(static_cast(&cumulativeTime), static_cast(&max_time), 1, MPI_DOUBLE, MPI_MAX, 0 /*root*/, MPI_COMM_WORLD); - - if ( my_proc == 0 ) { - std::cerr << "Time to do communicate_field_data ("< -#ifndef KOKKOS_INVALID_INDEX -#define KOKKOS_INVALID_INDEX 0 -#endif #include #include #include @@ -49,6 +46,12 @@ #define STK_LAMBDA KOKKOS_LAMBDA #define STK_INLINE KOKKOS_INLINE_FUNCTION #define STK_FORCE_INLINE KOKKOS_FORCEINLINE_FUNCTION +#define STK_INVALID_INDEX KOKKOS_INVALID_INDEX + +#ifndef KOKKOS_INVALID_INDEX +#undef STK_INVALID_INDEX +#define STK_INVALID_INDEX 0 +#endif namespace stk { namespace simd { @@ -286,14 +289,14 @@ class View template< typename Label > explicit KOKKOS_INLINE_FUNCTION View( const Label & arg_label - , const size_t arg_N0 = KOKKOS_INVALID_INDEX - , const size_t arg_N1 = KOKKOS_INVALID_INDEX - , const size_t arg_N2 = KOKKOS_INVALID_INDEX - , const size_t arg_N3 = KOKKOS_INVALID_INDEX - , const size_t arg_N4 = KOKKOS_INVALID_INDEX - , const size_t arg_N5 = KOKKOS_INVALID_INDEX - , const size_t arg_N6 = KOKKOS_INVALID_INDEX - , const size_t arg_N7 = KOKKOS_INVALID_INDEX + , const size_t arg_N0 = STK_INVALID_INDEX + , const size_t arg_N1 = STK_INVALID_INDEX + , const size_t arg_N2 = STK_INVALID_INDEX + , const size_t arg_N3 = STK_INVALID_INDEX + , const size_t arg_N4 = STK_INVALID_INDEX + , const size_t arg_N5 = STK_INVALID_INDEX + , const size_t arg_N6 = STK_INVALID_INDEX + , const size_t arg_N7 = STK_INVALID_INDEX ) : Kokkos::View< DataType, array_layout, execution_space, memory_traits >( arg_label, arg_N0 , arg_N1 , arg_N2 , arg_N3, diff --git a/packages/stk/stk_transfer/stk_transfer/ReducedDependencyGeometricTransfer.hpp b/packages/stk/stk_transfer/stk_transfer/ReducedDependencyGeometricTransfer.hpp index 3bbd00fde8df..be6345e70c88 100644 --- a/packages/stk/stk_transfer/stk_transfer/ReducedDependencyGeometricTransfer.hpp +++ b/packages/stk/stk_transfer/stk_transfer/ReducedDependencyGeometricTransfer.hpp @@ -144,6 +144,7 @@ template void get_unique_procs_from_entity_keys(const typename Mesh::EntityProcVec & vec, std::vector & uniqueProcVec) { //recalculate uniqueProcs using masked values + uniqueProcVec.clear(); uniqueProcVec.reserve(vec.size()); std::transform(vec.begin(), vec.end(), std::back_inserter(uniqueProcVec), [](typename Mesh::EntityProc a) {return a.proc();}); diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/BulkDataTester.hpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/BulkDataTester.hpp index 2a98b233f889..c80e6133906a 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/BulkDataTester.hpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/BulkDataTester.hpp @@ -74,21 +74,13 @@ class BulkDataTester : public stk::mesh::BulkData public: BulkDataTester(stk::mesh::MetaData &mesh_meta_data, MPI_Comm comm) : - stk::mesh::BulkData(std::shared_ptr(&mesh_meta_data, [](auto pointerWeWontDelete){}), comm, stk::mesh::BulkData::AUTO_AURA -#ifdef SIERRA_MIGRATION -, false -#endif -, (stk::mesh::FieldDataManager*)nullptr) + stk::mesh::BulkData(std::shared_ptr(&mesh_meta_data, [](auto pointerWeWontDelete){}), comm, stk::mesh::BulkData::AUTO_AURA) { } BulkDataTester(stk::mesh::MetaData &mesh_meta_data, MPI_Comm comm, enum stk::mesh::BulkData::AutomaticAuraOption auto_aura_option) - : stk::mesh::BulkData(std::shared_ptr(&mesh_meta_data, [](auto pointerWeWontDelete){}), comm, auto_aura_option -#ifdef SIERRA_MIGRATION -, false -#endif -, (stk::mesh::FieldDataManager*)nullptr) + : stk::mesh::BulkData(std::shared_ptr(&mesh_meta_data, [](auto pointerWeWontDelete){}), comm, auto_aura_option) { } diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/MeshFixture.hpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/MeshFixture.hpp index 797742ad1e20..3eedcb24111d 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/MeshFixture.hpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/MeshFixture.hpp @@ -76,11 +76,9 @@ class MeshFixtureNoTest { } - MeshFixtureNoTest(unsigned spatial_dim, stk::mesh::BulkData::AutomaticAuraOption auraOption) - : communicator(MPI_COMM_WORLD), - m_spatialDim(spatial_dim), - m_entityRankNames(), - metaData(nullptr), bulkData() + MeshFixtureNoTest( + unsigned spatial_dim, stk::mesh::BulkData::AutomaticAuraOption auraOption, MPI_Comm comm = MPI_COMM_WORLD) + : communicator(comm), m_spatialDim(spatial_dim), m_entityRankNames(), metaData(nullptr), bulkData() { setup_empty_mesh(auraOption); } diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/ReadWriteSidesetTester.hpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/ReadWriteSidesetTester.hpp index 94a59cdfd75e..8510fee09a64 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/ReadWriteSidesetTester.hpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/ReadWriteSidesetTester.hpp @@ -117,11 +117,7 @@ class BulkDataTester : public stk::mesh::BulkData { public: BulkDataTester(std::shared_ptr mesh_meta_data, stk::ParallelMachine parallel) - : stk::mesh::BulkData(mesh_meta_data, parallel, stk::mesh::BulkData::AUTO_AURA -#ifdef SIERRA_MIGRATION - , false -#endif - ) + : stk::mesh::BulkData(mesh_meta_data, parallel, stk::mesh::BulkData::AUTO_AURA) { } }; @@ -173,11 +169,7 @@ class BulkDataTester : public stk::mesh::BulkData { public: BulkDataTester(stk::mesh::MetaData & mesh_meta_data, stk::ParallelMachine parallel) - : stk::mesh::BulkData(std::shared_ptr(&mesh_meta_data, [](auto pointerWeWontDelete){}), parallel, stk::mesh::BulkData::AUTO_AURA, -#ifdef SIERRA_MIGRATION - false, -#endif - (stk::mesh::FieldDataManager*)nullptr) + : stk::mesh::BulkData(std::shared_ptr(&mesh_meta_data, [](auto pointerWeWontDelete){}), parallel, stk::mesh::BulkData::AUTO_AURA) { } }; diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/TextMeshDataTypes.hpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/TextMeshDataTypes.hpp index 2bed9fe20550..7e7be7f1ad65 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/TextMeshDataTypes.hpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/TextMeshDataTypes.hpp @@ -210,7 +210,7 @@ class Coordinates const std::vector &operator[](const EntityId nodeId) const { - auto it(m_nodalCoords.find(nodeId)); + auto it = m_nodalCoords.find(nodeId); if (it == m_nodalCoords.end()) { std::ostringstream errmsg; diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestAura.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestAura.cpp index 407691603911..6da37976d0f0 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestAura.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestAura.cpp @@ -46,6 +46,7 @@ #include "stk_mesh/base/Comm.hpp" #include "stk_topology/topology.hpp" // for topology, etc #include "stk_io/FillMesh.hpp" +#include "stk_mesh/base/MeshBuilder.hpp" #include "stk_unit_test_utils/BuildMesh.hpp" #include "UnitTestTextMeshFixture.hpp" @@ -140,17 +141,7 @@ stk::mesh::Part& setupDavidNobleTestCase(stk::mesh::BulkData& bulk) bool isEntityInPart(stk::mesh::BulkData &bulk, stk::mesh::EntityRank rank, stk::mesh::EntityId id, const stk::mesh::Part &part) { stk::mesh::Entity entity = bulk.get_entity(rank, id); - const stk::mesh::PartVector &partsNodes6 = bulk.bucket(entity).supersets(); - bool isInPart = false; - for(size_t i = 0; i < partsNodes6.size(); ++i) - { - if(partsNodes6[i] == &part) - { - isInPart = true; - break; - } - } - return isInPart; + return bulk.bucket(entity).member(part); } TEST(BulkDataTest, testRemovingPartsOnNodeSharedWithOneProcAndAuraToAnotherProc) @@ -284,68 +275,74 @@ void confirm_entities_not_valid(const stk::mesh::BulkData& mesh, } } +void test_aura_disconnect_elem_on_proc_boundary(stk::mesh::BulkData& mesh) +{ + // 3----------7----------11 + // /| /| /| + // / | / | / | + // / | / | / | + // 2----------6----------10 | + // | 4------|---8------|---12 + // | / | / | / + // | / E1 | / E2 | / + // |/ |/ |/ + // 1----------5----------9 + // P0 P1 + // Nodes 5,6,7,8 are shared + // + const std::string generatedMeshSpec = "generated:1x1x2"; + stk::io::fill_mesh(generatedMeshSpec, mesh); + + disconnect_elem1_on_proc0(mesh); + + int thisProc = stk::parallel_machine_rank(mesh.parallel()); + stk::mesh::EntityId auraElemId = 2; + if (thisProc == 1) { + auraElemId = 1; + } + if (thisProc == 0) { + check_elem_state(mesh, auraElemId, Modified); + + stk::mesh::EntityState expectedAuraElemNodeStates[] = { + Modified, Modified, Modified, Modified, + Modified, Modified, Modified, Modified + }; + check_node_states_for_elem(mesh, auraElemId, expectedAuraElemNodeStates); + + stk::mesh::EntityId ownedElemId = 1; + stk::mesh::Entity ownedElem = mesh.get_entity(stk::topology::ELEM_RANK, ownedElemId); + EXPECT_EQ(Modified, mesh.state(ownedElem)); + stk::mesh::EntityState expectedNodeStates[] = { + Unchanged, Unchanged, Unchanged, Unchanged, + Created, Created, Created, Created + }; + check_node_states_for_elem(mesh, ownedElemId, expectedNodeStates); + } + else { + confirm_entities_not_valid(mesh, stk::topology::ELEM_RANK, + stk::mesh::EntityIdVector{auraElemId}); + confirm_entities_not_valid(mesh, stk::topology::NODE_RANK, + stk::mesh::EntityIdVector{1, 2, 3, 4}); + + stk::mesh::EntityId ownedElemId = 2; + stk::mesh::EntityState expectedNodeStates[] = { + Modified, Modified, Modified, Modified, + Unchanged, Unchanged, Unchanged, Unchanged + }; + check_node_states_for_elem(mesh, ownedElemId, expectedNodeStates); + } +} + TEST(BulkData, aura_disconnectElemOnProcBoundary) { int numProcs = stk::parallel_machine_size(MPI_COMM_WORLD); - int thisProc = stk::parallel_machine_rank(MPI_COMM_WORLD); if (numProcs==2) { - std::shared_ptr bulkPtr = build_mesh(3, MPI_COMM_WORLD, stk::mesh::BulkData::AUTO_AURA); - stk::mesh::BulkData& mesh = *bulkPtr; - - // 3----------7----------11 - // /| /| /| - // / | / | / | - // / | / | / | - // 2----------6----------10 | - // | 4------|---8------|---12 - // | / | / | / - // | / E1 | / E2 | / - // |/ |/ |/ - // 1----------5----------9 - // P0 P1 - // Nodes 5,6,7,8 are shared - // - const std::string generatedMeshSpec = "generated:1x1x2"; - stk::io::fill_mesh(generatedMeshSpec, mesh); - - disconnect_elem1_on_proc0(mesh); - - stk::mesh::EntityId auraElemId = 2; - if (thisProc == 1) { - auraElemId = 1; - } - if (thisProc == 0) { - check_elem_state(mesh, auraElemId, Modified); - - stk::mesh::EntityState expectedAuraElemNodeStates[] = { - Modified, Modified, Modified, Modified, - Modified, Modified, Modified, Modified - }; - check_node_states_for_elem(mesh, auraElemId, expectedAuraElemNodeStates); - - stk::mesh::EntityId ownedElemId = 1; - stk::mesh::Entity ownedElem = mesh.get_entity(stk::topology::ELEM_RANK, ownedElemId); - EXPECT_EQ(Modified, mesh.state(ownedElem)); - stk::mesh::EntityState expectedNodeStates[] = { - Unchanged, Unchanged, Unchanged, Unchanged, - Created, Created, Created, Created - }; - check_node_states_for_elem(mesh, ownedElemId, expectedNodeStates); - } - else { - confirm_entities_not_valid(mesh, stk::topology::ELEM_RANK, - stk::mesh::EntityIdVector{auraElemId}); - confirm_entities_not_valid(mesh, stk::topology::NODE_RANK, - stk::mesh::EntityIdVector{1, 2, 3, 4}); - - stk::mesh::EntityId ownedElemId = 2; - stk::mesh::EntityState expectedNodeStates[] = { - Modified, Modified, Modified, Modified, - Unchanged, Unchanged, Unchanged, Unchanged - }; - check_node_states_for_elem(mesh, ownedElemId, expectedNodeStates); - } + std::shared_ptr bulkPtr = stk::mesh::MeshBuilder(MPI_COMM_WORLD) + .set_spatial_dimension(3) + .set_aura_option(stk::mesh::BulkData::AUTO_AURA) + .create(); + test_aura_disconnect_elem_on_proc_boundary(*bulkPtr); } } @@ -372,72 +369,86 @@ void expect_recv_aura(const stk::mesh::BulkData& bulk, } } -TEST(BulkData, aura_moveElem1FromProc0ToProc1) +void test_aura_move_elem1_from_proc0_to_proc1(stk::mesh::BulkData& mesh) { - int numProcs = stk::parallel_machine_size(MPI_COMM_WORLD); + const std::string generatedMeshSpec = "generated:1x1x4"; + stk::io::fill_mesh(generatedMeshSpec, mesh); + + //Initial mesh: + // 3----------7----------11----------15-----------19 + // /| /| /| /| /| + // / | / | / | / | / | + // / | / | / | / | / | + // 2----------6----------10-----------14----------18 | + // | 4------|---8------|---12-------|--16-------|---20 + // | / | / | / | / | / + // | / E1 | / E2 | / E3 | / E4 | / + // |/ |/ |/ |/ |/ + // 1----------5----------9------------13----------17 + // P0 P0 P1 P1 + // Nodes 9,10,11,12 are shared + // Elem 3 is aura-ghost on P0 and elem 2 is aura-ghost on P1 + // Nodes 13-16 are aura-ghosts on P0, nodes 5-8 are aura-ghosts on P1 + // int thisProc = stk::parallel_machine_rank(MPI_COMM_WORLD); - if (numProcs==2) { - const unsigned spatialDim = 3; - std::shared_ptr bulkPtr = build_mesh(spatialDim, MPI_COMM_WORLD, stk::mesh::BulkData::AUTO_AURA); - stk::mesh::BulkData& mesh = *bulkPtr; - const std::string generatedMeshSpec = "generated:1x1x4"; - stk::io::fill_mesh(generatedMeshSpec, mesh); - - //Initial mesh: - // 3----------7----------11----------15-----------19 - // /| /| /| /| /| - // / | / | / | / | / | - // / | / | / | / | / | - // 2----------6----------10-----------14----------18 | - // | 4------|---8------|---12-------|--16-------|---20 - // | / | / | / | / | / - // | / E1 | / E2 | / E3 | / E4 | / - // |/ |/ |/ |/ |/ - // 1----------5----------9------------13----------17 - // P0 P0 P1 P1 - // Nodes 9,10,11,12 are shared - // Elem 3 is aura-ghost on P0 and elem 2 is aura-ghost on P1 - // Nodes 13-16 are aura-ghosts on P0, nodes 5-8 are aura-ghosts on P1 - // - { - stk::mesh::EntityIdVector elemIds[] = {{3}, {2}}; - stk::mesh::EntityIdVector nodeIds[] = {{13,14,15,16}, {5,6,7,8}}; - expect_recv_aura(mesh, stk::topology::ELEM_RANK, elemIds[thisProc]); - expect_recv_aura(mesh, stk::topology::NODE_RANK, nodeIds[thisProc]); - } + stk::mesh::EntityIdVector elemIds[] = {{3}, {2}}; + stk::mesh::EntityIdVector nodeIds[] = {{13,14,15,16}, {5,6,7,8}}; + expect_recv_aura(mesh, stk::topology::ELEM_RANK, elemIds[thisProc]); + expect_recv_aura(mesh, stk::topology::NODE_RANK, nodeIds[thisProc]); + } - //--------------------------------------- - stk::mesh::EntityProcVec elemToMove; - if (thisProc == 0) { - stk::mesh::Entity elem1 = mesh.get_entity(stk::topology::ELEM_RANK, 1); - elemToMove.push_back(stk::mesh::EntityProc(elem1, 1)); - } + //--------------------------------------- + stk::mesh::EntityProcVec elemToMove; + if (thisProc == 0) { + stk::mesh::Entity elem1 = mesh.get_entity(stk::topology::ELEM_RANK, 1); + elemToMove.push_back(stk::mesh::EntityProc(elem1, 1)); + } - mesh.change_entity_owner(elemToMove); - - //After change-entity-owner moves elem 1 to P1: - // 3----------7----------11----------15-----------19 - // /| /| /| /| /| - // / | / | / | / | / | - // / | / | / | / | / | - // 2----------6----------10-----------14----------18 | - // | 4------|---8------|---12-------|--16-------|---20 - // | / | / | / | / | / - // | / E1 | / E2 | / E3 | / E4 | / - // |/ |/ |/ |/ |/ - // 1----------5----------9------------13----------17 - // P1 P0 P1 P1 - // Nodes 1-12 are shared - // Elem 2 is aura-ghost on P1 and elems 1 and 3 are aura-ghosts on P0 - // Nodes 13-16 are aura-ghosts on P0. No nodes are aura-ghosts on P1. - // - { - stk::mesh::EntityIdVector elemIds[] = {{1, 3}, {2}}; - stk::mesh::EntityIdVector nodeIds[] = {{13,14,15,16}, {}}; - expect_recv_aura(mesh, stk::topology::ELEM_RANK, elemIds[thisProc]); - expect_recv_aura(mesh, stk::topology::NODE_RANK, nodeIds[thisProc]); - } + mesh.change_entity_owner(elemToMove); + + //After change-entity-owner moves elem 1 to P1: + // 3----------7----------11----------15-----------19 + // /| /| /| /| /| + // / | / | / | / | / | + // / | / | / | / | / | + // 2----------6----------10-----------14----------18 | + // | 4------|---8------|---12-------|--16-------|---20 + // | / | / | / | / | / + // | / E1 | / E2 | / E3 | / E4 | / + // |/ |/ |/ |/ |/ + // 1----------5----------9------------13----------17 + // P1 P0 P1 P1 + // Nodes 1-12 are shared + // Elem 2 is aura-ghost on P1 and elems 1 and 3 are aura-ghosts on P0 + // Nodes 13-16 are aura-ghosts on P0. No nodes are aura-ghosts on P1. + // + { + stk::mesh::EntityIdVector elemIds[] = {{1, 3}, {2}}; + stk::mesh::EntityIdVector nodeIds[] = {{13,14,15,16}, {}}; + expect_recv_aura(mesh, stk::topology::ELEM_RANK, elemIds[thisProc]); + expect_recv_aura(mesh, stk::topology::NODE_RANK, nodeIds[thisProc]); + } +} + +TEST(BulkData, aura_moveElem1FromProc0ToProc1) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD)==2) { + std::shared_ptr bulkPtr = stk::mesh::MeshBuilder(MPI_COMM_WORLD) + .set_aura_option(stk::mesh::BulkData::AUTO_AURA) + .create(); + test_aura_move_elem1_from_proc0_to_proc1(*bulkPtr); + } +} + +TEST(BulkData, aura_moveElem1FromProc0ToProc1_NoUpwardConnectivity) +{ + if (stk::parallel_machine_size(MPI_COMM_WORLD)==2) { + std::shared_ptr bulkPtr = stk::mesh::MeshBuilder(MPI_COMM_WORLD) + .set_aura_option(stk::mesh::BulkData::AUTO_AURA) + .set_upward_connectivity(false) + .create(); + test_aura_move_elem1_from_proc0_to_proc1(*bulkPtr); } } diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestNoUpwardConnectivity.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestNoUpwardConnectivity.cpp new file mode 100644 index 000000000000..d40a298fe6c8 --- /dev/null +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestNoUpwardConnectivity.cpp @@ -0,0 +1,240 @@ +#include "gtest/gtest.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + +TEST(NoUpwardConnectivity, basic_mesh_read_no_aura) +{ + MPI_Comm comm = MPI_COMM_WORLD; + const int numProcs = stk::parallel_machine_size(comm); + if(numProcs > 2) { GTEST_SKIP(); } + + stk::mesh::MeshBuilder builder(comm); + builder.set_aura_option(stk::mesh::BulkData::NO_AUTO_AURA); + builder.set_upward_connectivity(false); + std::shared_ptr bulkPtr = builder.create(); + stk::mesh::BulkData& bulk = *bulkPtr; + stk::mesh::MetaData& meta = bulk.mesh_meta_data(); + + stk::io::fill_mesh("generated:1x1x2", bulk); + + const unsigned numNodesLocalWithoutAura = numProcs==1 ? 12 : 8; + const unsigned numElemsLocalWithoutAura = numProcs==1 ? 2 : 1; + EXPECT_EQ(numNodesLocalWithoutAura, stk::mesh::count_entities(bulk, stk::topology::NODE_RANK, meta.universal_part())); + EXPECT_EQ(numElemsLocalWithoutAura, stk::mesh::count_entities(bulk, stk::topology::ELEM_RANK, meta.universal_part())); + + stk::mesh::for_each_entity_run(bulk, stk::topology::NODE_RANK, meta.universal_part(), + [](const stk::mesh::BulkData& bulkData, stk::mesh::Entity node) { + EXPECT_EQ(0u, bulkData.num_elements(node)); + }); + + stk::mesh::for_each_entity_run(bulk, stk::topology::ELEM_RANK, meta.universal_part(), + [](const stk::mesh::BulkData& bulkData, stk::mesh::Entity elem) { + EXPECT_EQ(8u, bulkData.num_nodes(elem)); + }); +} + +TEST(NoUpwardConnectivity, basic_mesh_read_no_aura_create_edges) +{ + MPI_Comm comm = MPI_COMM_WORLD; + const int numProcs = stk::parallel_machine_size(comm); + if(numProcs > 2) { GTEST_SKIP(); } + + stk::mesh::MeshBuilder builder(comm); + builder.set_aura_option(stk::mesh::BulkData::NO_AUTO_AURA); + builder.set_upward_connectivity(false); + std::shared_ptr bulkPtr = builder.create(); + stk::mesh::BulkData& bulk = *bulkPtr; + stk::mesh::MetaData& meta = bulk.mesh_meta_data(); + + stk::io::fill_mesh("generated:1x1x2", bulk); + + stk::mesh::create_edges(bulk); + + const unsigned numNodesLocalWithoutAura = numProcs==1 ? 12 : 8; + const unsigned numEdgesLocalWithoutAura = numProcs==1 ? 20 : 12; + const unsigned numElemsLocalWithoutAura = numProcs==1 ? 2 : 1; + EXPECT_EQ(numNodesLocalWithoutAura, stk::mesh::count_entities(bulk, stk::topology::NODE_RANK, meta.universal_part())); + EXPECT_EQ(numEdgesLocalWithoutAura, stk::mesh::count_entities(bulk, stk::topology::EDGE_RANK, meta.universal_part())); + EXPECT_EQ(numElemsLocalWithoutAura, stk::mesh::count_entities(bulk, stk::topology::ELEM_RANK, meta.universal_part())); + + stk::mesh::for_each_entity_run(bulk, stk::topology::NODE_RANK, meta.universal_part(), + [](const stk::mesh::BulkData& bulkData, stk::mesh::Entity node) { + EXPECT_EQ(0u, bulkData.num_elements(node)); + }); + + stk::mesh::for_each_entity_run(bulk, stk::topology::EDGE_RANK, meta.universal_part(), + [](const stk::mesh::BulkData& bulkData, stk::mesh::Entity edge) { + EXPECT_EQ(0u, bulkData.num_elements(edge)); + EXPECT_EQ(2u, bulkData.num_nodes(edge)); + }); + + stk::mesh::for_each_entity_run(bulk, stk::topology::ELEM_RANK, meta.universal_part(), + [](const stk::mesh::BulkData& bulkData, stk::mesh::Entity elem) { + EXPECT_EQ(12u, bulkData.num_edges(elem)); + EXPECT_EQ(8u, bulkData.num_nodes(elem)); + }); +} + +TEST(NoUpwardConnectivity, basic_mesh_read_no_aura_create_faces) +{ + MPI_Comm comm = MPI_COMM_WORLD; + const int numProcs = stk::parallel_machine_size(comm); + if(numProcs > 2) { GTEST_SKIP(); } + + stk::mesh::MeshBuilder builder(comm); + builder.set_aura_option(stk::mesh::BulkData::NO_AUTO_AURA); + builder.set_upward_connectivity(false); + std::shared_ptr bulkPtr = builder.create(); + stk::mesh::BulkData& bulk = *bulkPtr; + stk::mesh::MetaData& meta = bulk.mesh_meta_data(); + + stk::io::fill_mesh("generated:1x1x2", bulk); + + stk::mesh::create_faces(bulk); + + const unsigned numNodesLocalWithoutAura = numProcs==1 ? 12 : 8; + const unsigned numFacesLocalWithoutAura = numProcs==1 ? 11 : 6; + const unsigned numElemsLocalWithoutAura = numProcs==1 ? 2 : 1; + EXPECT_EQ(numNodesLocalWithoutAura, stk::mesh::count_entities(bulk, stk::topology::NODE_RANK, meta.universal_part())); + EXPECT_EQ(numFacesLocalWithoutAura, stk::mesh::count_entities(bulk, stk::topology::FACE_RANK, meta.universal_part())); + EXPECT_EQ(numElemsLocalWithoutAura, stk::mesh::count_entities(bulk, stk::topology::ELEM_RANK, meta.universal_part())); + + stk::mesh::for_each_entity_run(bulk, stk::topology::NODE_RANK, meta.universal_part(), + [](const stk::mesh::BulkData& bulkData, stk::mesh::Entity node) { + EXPECT_EQ(0u, bulkData.num_elements(node)); + }); + + stk::mesh::for_each_entity_run(bulk, stk::topology::FACE_RANK, meta.universal_part(), + [](const stk::mesh::BulkData& bulkData, stk::mesh::Entity face) { + EXPECT_EQ(0u, bulkData.num_elements(face)); + EXPECT_EQ(4u, bulkData.num_nodes(face)); + }); + + stk::mesh::for_each_entity_run(bulk, stk::topology::ELEM_RANK, meta.universal_part(), + [](const stk::mesh::BulkData& bulkData, stk::mesh::Entity elem) { + EXPECT_EQ(6u, bulkData.num_faces(elem)); + EXPECT_EQ(8u, bulkData.num_nodes(elem)); + }); +} + +TEST(NoUpwardConnectivity, basic_mesh_read_no_aura_create_edges_and_faces) +{ + MPI_Comm comm = MPI_COMM_WORLD; + const int numProcs = stk::parallel_machine_size(comm); + if(numProcs > 2) { GTEST_SKIP(); } + + stk::mesh::MeshBuilder builder(comm); + builder.set_aura_option(stk::mesh::BulkData::NO_AUTO_AURA); + builder.set_upward_connectivity(false); + std::shared_ptr bulkPtr = builder.create(); + stk::mesh::BulkData& bulk = *bulkPtr; + stk::mesh::MetaData& meta = bulk.mesh_meta_data(); + + stk::io::fill_mesh("generated:1x1x2", bulk); + + stk::mesh::create_edges(bulk); + stk::mesh::create_faces(bulk); + + const unsigned numNodesLocalWithoutAura = numProcs==1 ? 12 : 8; + const unsigned numEdgesLocalWithoutAura = numProcs==1 ? 20 : 12; + const unsigned numFacesLocalWithoutAura = numProcs==1 ? 11 : 6; + const unsigned numElemsLocalWithoutAura = numProcs==1 ? 2 : 1; + EXPECT_EQ(numNodesLocalWithoutAura, stk::mesh::count_entities(bulk, stk::topology::NODE_RANK, meta.universal_part())); + EXPECT_EQ(numEdgesLocalWithoutAura, stk::mesh::count_entities(bulk, stk::topology::EDGE_RANK, meta.universal_part())); + EXPECT_EQ(numFacesLocalWithoutAura, stk::mesh::count_entities(bulk, stk::topology::FACE_RANK, meta.universal_part())); + EXPECT_EQ(numElemsLocalWithoutAura, stk::mesh::count_entities(bulk, stk::topology::ELEM_RANK, meta.universal_part())); + + stk::mesh::for_each_entity_run(bulk, stk::topology::NODE_RANK, meta.universal_part(), + [](const stk::mesh::BulkData& bulkData, stk::mesh::Entity node) { + EXPECT_EQ(0u, bulkData.num_elements(node)); + }); + + stk::mesh::for_each_entity_run(bulk, stk::topology::EDGE_RANK, meta.universal_part(), + [](const stk::mesh::BulkData& bulkData, stk::mesh::Entity edge) { + EXPECT_EQ(0u, bulkData.num_elements(edge)); + EXPECT_EQ(2u, bulkData.num_nodes(edge)); + }); + + stk::mesh::for_each_entity_run(bulk, stk::topology::FACE_RANK, meta.universal_part(), + [](const stk::mesh::BulkData& bulkData, stk::mesh::Entity face) { + EXPECT_EQ(0u, bulkData.num_elements(face)); + EXPECT_EQ(4u, bulkData.num_nodes(face)); + }); + + stk::mesh::for_each_entity_run(bulk, stk::topology::ELEM_RANK, meta.universal_part(), + [](const stk::mesh::BulkData& bulkData, stk::mesh::Entity elem) { + EXPECT_EQ(6u, bulkData.num_faces(elem)); + EXPECT_EQ(12u, bulkData.num_edges(elem)); + EXPECT_EQ(8u, bulkData.num_nodes(elem)); + }); +} + +TEST(NoUpwardConnectivity, elem_graph_not_available) +{ + MPI_Comm comm = MPI_COMM_WORLD; + const int numProcs = stk::parallel_machine_size(comm); + if(numProcs > 2) { GTEST_SKIP(); } + + stk::mesh::MeshBuilder builder(comm); + builder.set_aura_option(stk::mesh::BulkData::NO_AUTO_AURA); + builder.set_upward_connectivity(false); + std::shared_ptr bulkPtr = builder.create(); + + EXPECT_FALSE(bulkPtr->has_face_adjacent_element_graph()); + EXPECT_FALSE(bulkPtr->initialize_face_adjacent_element_graph()); + EXPECT_ANY_THROW(bulkPtr->get_face_adjacent_element_graph()); +} + +TEST(NoUpwardConnectivity, basic_mesh_read_create_all_sides_throws) +{ + MPI_Comm comm = MPI_COMM_WORLD; + const int numProcs = stk::parallel_machine_size(comm); + if(numProcs > 2) { GTEST_SKIP(); } + + stk::mesh::MeshBuilder builder(comm); + builder.set_aura_option(stk::mesh::BulkData::NO_AUTO_AURA); + builder.set_upward_connectivity(false); + std::shared_ptr bulkPtr = builder.create(); + stk::mesh::BulkData& bulk = *bulkPtr; + stk::mesh::MetaData& meta = bulk.mesh_meta_data(); + + stk::io::fill_mesh("generated:1x1x2", bulk); + + EXPECT_ANY_THROW(stk::mesh::create_all_sides(bulk, meta.universal_part())); +} + +TEST(NoUpwardConnectivity, basic_mesh_read_with_aura) +{ + MPI_Comm comm = MPI_COMM_WORLD; + if(stk::parallel_machine_size(comm) > 2) { GTEST_SKIP(); } + + stk::mesh::MeshBuilder builder(comm); + builder.set_aura_option(stk::mesh::BulkData::AUTO_AURA); + builder.set_upward_connectivity(false); + std::shared_ptr bulkPtr = builder.create(); + stk::mesh::BulkData& bulk = *bulkPtr; + stk::mesh::MetaData& meta = bulk.mesh_meta_data(); + + stk::io::fill_mesh("generated:1x1x2", bulk); + + const unsigned numNodesLocalWithAura = 12; + const unsigned numElemsLocalWithAura = 2; + EXPECT_EQ(numNodesLocalWithAura, stk::mesh::count_entities(bulk, stk::topology::NODE_RANK, meta.universal_part())); + EXPECT_EQ(numElemsLocalWithAura, stk::mesh::count_entities(bulk, stk::topology::ELEM_RANK, meta.universal_part())); + + stk::mesh::for_each_entity_run(bulk, stk::topology::NODE_RANK, meta.universal_part(), + [](const stk::mesh::BulkData& bulkData, stk::mesh::Entity node) { + EXPECT_EQ(0u, bulkData.num_elements(node)); + }); +} + +} diff --git a/packages/stk/stk_unit_tests/stk_transfer/UnitTestGeometricTransfer.cpp b/packages/stk/stk_unit_tests/stk_transfer/UnitTestGeometricTransfer.cpp index ac87c098cd87..f230b159288b 100644 --- a/packages/stk/stk_unit_tests/stk_transfer/UnitTestGeometricTransfer.cpp +++ b/packages/stk/stk_unit_tests/stk_transfer/UnitTestGeometricTransfer.cpp @@ -99,6 +99,24 @@ class MockMeshA_Common }; +TEST(GeomXferImpl, clear_unique_procs_for_each_call) +{ + using Mesh = MockMeshA_Common; + Mesh::EntityProcVec entityProcs = {{1,0}, {1,1}, {1,1}, {1,2}}; + std::vector uniqueProcs; + + size_t expectedSize = 3; + + stk::transfer::impl::get_unique_procs_from_entity_keys(entityProcs, uniqueProcs); + EXPECT_EQ(expectedSize, uniqueProcs.size()); + + entityProcs = {{1,3}}; + expectedSize = 1; + + stk::transfer::impl::get_unique_procs_from_entity_keys(entityProcs, uniqueProcs); + EXPECT_EQ(expectedSize, uniqueProcs.size()); +} + class MockMeshB_Common { public: diff --git a/packages/stk/stk_unit_tests/stk_util/parallel/UnitTestMPICommKey.cpp b/packages/stk/stk_unit_tests/stk_util/parallel/UnitTestMPICommKey.cpp new file mode 100644 index 000000000000..bdd1269b4710 --- /dev/null +++ b/packages/stk/stk_unit_tests/stk_util/parallel/UnitTestMPICommKey.cpp @@ -0,0 +1,406 @@ +// 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_util/stk_config.h" // for STK_HAS_MPI +#ifdef STK_HAS_MPI + +#include "gtest/gtest.h" +#include "stk_util/parallel/MPICommKey.hpp" + + +namespace { + +class KeyManagerTester : public ::testing::Test +{ + protected: + KeyManagerTester() + { + comm1 = MPI_COMM_WORLD; + MPI_Comm_dup(comm1, &comm2); + } + + ~KeyManagerTester() + { + MPI_Comm_free(&comm2); + } + + MPI_Comm comm1; + MPI_Comm comm2; + stk::impl::MPIKeyManager keyManager; +}; + +class CallbackChecker +{ + public: + int callcount = 0; + + void set_called(MPI_Comm) { callcount++; } +}; + +} // namespace + + +namespace { + MPI_Request req; + bool is_complete = false; + int comm_destructor_callback(MPI_Comm, int keyval, void* attribute_val, void* extra_state) + { + MPI_Wait(&req, MPI_STATUS_IGNORE); + is_complete = true; + + return MPI_SUCCESS; + } +} + +#ifndef MPI_KEY_MANAGER_COMM_DESTRUCTOR_CALLBACK_BROKEN +TEST(KeyManager, IntelMPIBug) +{ + MPI_Comm comm2; + MPI_Comm_dup(MPI_COMM_WORLD, &comm2); + int keyval; + MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, &comm_destructor_callback, &keyval, nullptr); + MPI_Comm_set_attr(comm2, keyval, nullptr); + + is_complete = false; + MPI_Ibarrier(comm2, &req); + MPI_Comm_free(&comm2); + EXPECT_TRUE(is_complete); +} +#endif + + +TEST_F(KeyManagerTester, KeyValuesUniqueness) +{ + MPI_Comm comm3, comm4; + MPI_Comm_dup(comm1, &comm3); + MPI_Comm_dup(comm1, &comm4); + + + std::vector keyVals; + keyVals.push_back(keyManager.get_key(comm1)); + keyVals.push_back(keyManager.get_key(comm2)); + keyVals.push_back(keyManager.get_key(comm3)); + keyVals.push_back(keyManager.get_key(comm4)); + + for (unsigned int i=0; i < keyVals.size(); ++i) + for (unsigned int j=0; j < keyVals.size(); ++j) + if (i == j) + EXPECT_EQ(keyVals[i], keyVals[j]); + else + EXPECT_NE(keyVals[i], keyVals[j]); + + MPI_Comm_free(&comm3); + MPI_Comm_free(&comm4); +} + + +TEST_F(KeyManagerTester, getTagConst) +{ + auto key1 = keyManager.get_key(comm1); + auto key2 = keyManager.get_key(comm2); + + const stk::impl::MPIKeyManager& keyManagerConst = keyManager; + + EXPECT_EQ(key1, keyManagerConst.get_key(comm1)); + EXPECT_EQ(key2, keyManagerConst.get_key(comm2)); + + MPI_Comm comm3; + MPI_Comm_dup(comm1, &comm3); + EXPECT_ANY_THROW(keyManagerConst.get_key(comm3)); + MPI_Comm_free(&comm3); +} + + +TEST_F(KeyManagerTester, KeyReuse) +{ + MPI_Comm comm3; + MPI_Comm_dup(comm1, &comm3); + + auto key1 = keyManager.get_key(comm1); + auto key2 = keyManager.get_key(comm2); + keyManager.get_key(comm3); + + MPI_Comm_free(&comm3); + MPI_Comm_dup(comm1, &comm3); + + auto key4 = keyManager.get_key(comm3); + + EXPECT_NE(key1, key4); + EXPECT_NE(key2, key4); + + MPI_Comm_free(&comm3); +} + + +TEST_F(KeyManagerTester, SplitCommSubsetOfProcs) +{ + MPI_Comm comm3; + int myrank; + MPI_Comm_rank(comm1, &myrank); + int color = myrank == 0 ? MPI_UNDEFINED : 1; + MPI_Comm_split(comm1, color, 0, &comm3); + + auto key1 = keyManager.get_key(comm1); + stk::impl::MPIKeyManager::CommKey key3; + if (color != MPI_UNDEFINED) + key3 = keyManager.get_key(comm3); + auto key2 = keyManager.get_key(comm2); + + EXPECT_NE(key1, key2); + if (color != MPI_UNDEFINED) + { + EXPECT_NE(key1, key3); + EXPECT_NE(key2, key3); + + MPI_Comm_free(&comm3); + } +} + + +TEST_F(KeyManagerTester, Callback) +{ + MPI_Comm comm3; + MPI_Comm_dup(comm1, &comm3); + + CallbackChecker checker3; + keyManager.get_key(comm3); + + EXPECT_EQ(checker3.callcount, 0); + auto callerUID = keyManager.get_UID(); + keyManager.register_callback(comm3, callerUID, + std::bind(&CallbackChecker::set_called, &checker3, std::placeholders::_1)); + MPI_Comm_free(&comm3); + EXPECT_EQ(checker3.callcount, 1); + +} + + +TEST(KeyManager, CommNeverFreed) +{ + MPI_Comm comm = MPI_COMM_WORLD; + CallbackChecker checker; + + { + stk::impl::MPIKeyManager keyManager; + keyManager.get_key(comm); + auto callerUID = keyManager.get_UID(); + keyManager.register_callback(comm, callerUID, + std::bind(&CallbackChecker::set_called, &checker, std::placeholders::_1)); + + EXPECT_EQ(checker.callcount, 0); + } + + EXPECT_EQ(checker.callcount, 1); +} // comm is never freed, but MPIKeyManager shouldn't segfault + + +TEST(KeyManager, CommFreedAfterManager) +{ + MPI_Comm comm3; + MPI_Comm_dup(MPI_COMM_WORLD, &comm3); + + { + stk::impl::MPIKeyManager keyManager; + keyManager.get_key(comm3); + } // keyManager destructor runs here, shouldn't segfault + + MPI_Comm_free(&comm3); +} + + +TEST(KeyManager, CommFreedAfterManagerWithCallback) +{ + MPI_Comm comm3; + MPI_Comm_dup(MPI_COMM_WORLD, &comm3); + CallbackChecker checker3; + + { + stk::impl::MPIKeyManager keyManager; + keyManager.get_key(comm3); + auto callerUID = keyManager.get_UID(); + keyManager.register_callback(comm3, callerUID, + std::bind(&CallbackChecker::set_called, &checker3, std::placeholders::_1)); + } + + EXPECT_EQ(checker3.callcount, 1); + MPI_Comm_free(&comm3); + EXPECT_EQ(checker3.callcount, 1); +} + + +TEST(KeyManager, CommFreedCallback) +{ + MPI_Comm comm3; + MPI_Comm_dup(MPI_COMM_WORLD, &comm3); + CallbackChecker checker3; + + { + stk::impl::MPIKeyManager keyManager; + keyManager.get_key(comm3); + auto callerUID = keyManager.get_UID(); + keyManager.register_callback(comm3, callerUID, + std::bind(&CallbackChecker::set_called, &checker3, std::placeholders::_1)); + + EXPECT_EQ(checker3.callcount, 0); + MPI_Comm_free(&comm3); + EXPECT_EQ(checker3.callcount, 1); + } + + + EXPECT_EQ(checker3.callcount, 1); +} + + +TEST(KeyManager, CallbackImmediately) +{ + MPI_Comm comm3; + MPI_Comm_dup(MPI_COMM_WORLD, &comm3); + CallbackChecker checker3; + + { + stk::impl::MPIKeyManager keyManager; + keyManager.get_key(comm3); + auto callerUID = keyManager.get_UID(); + keyManager.register_callback(comm3, + callerUID, std::bind(&CallbackChecker::set_called, &checker3, std::placeholders::_1)); + keyManager.execute_callbacks_immediately(callerUID); + + EXPECT_EQ(checker3.callcount, 1); + } + + EXPECT_EQ(checker3.callcount, 1); + MPI_Comm_free(&comm3); + EXPECT_EQ(checker3.callcount, 1); +} + + +TEST(KeyManager, UnregisterCallbacks) +{ + MPI_Comm comm3; + MPI_Comm_dup(MPI_COMM_WORLD, &comm3); + CallbackChecker checker3; + + { + stk::impl::MPIKeyManager keyManager; + keyManager.get_key(comm3); + auto callerUID = keyManager.get_UID(); + keyManager.register_callback(comm3, + callerUID, std::bind(&CallbackChecker::set_called, &checker3, std::placeholders::_1)); + keyManager.unregister_callbacks(callerUID); + + EXPECT_EQ(checker3.callcount, 0); + } + + EXPECT_EQ(checker3.callcount, 0); + MPI_Comm_free(&comm3); + EXPECT_EQ(checker3.callcount, 0); +} + + +TEST(KeyManager, MultipleCallbacks) +{ + MPI_Comm comm3; + MPI_Comm_dup(MPI_COMM_WORLD, &comm3); + CallbackChecker checker1, checker2, checker3; + + auto callback1 = std::bind(&CallbackChecker::set_called, &checker1, std::placeholders::_1); + auto callback2 = std::bind(&CallbackChecker::set_called, &checker2, std::placeholders::_1); + auto callback3 = std::bind(&CallbackChecker::set_called, &checker3, std::placeholders::_1); + { + stk::impl::MPIKeyManager keyManager; + keyManager.get_key(comm3); + auto callerUID1 = keyManager.get_UID(); + auto callerUID2 = keyManager.get_UID(); + auto callerUID3 = keyManager.get_UID(); + keyManager.register_callback(comm3, callerUID1, callback1); + keyManager.register_callback(comm3, callerUID2, callback2); + keyManager.register_callback(comm3, callerUID3, callback3); + + keyManager.execute_callbacks_immediately(callerUID1); + EXPECT_EQ(checker1.callcount, 1); + EXPECT_EQ(checker2.callcount, 0); + EXPECT_EQ(checker3.callcount, 0); + + keyManager.unregister_callbacks(callerUID2); + EXPECT_EQ(checker1.callcount, 1); + EXPECT_EQ(checker2.callcount, 0); + EXPECT_EQ(checker3.callcount, 0); + } + + EXPECT_EQ(checker1.callcount, 1); + EXPECT_EQ(checker2.callcount, 0); + EXPECT_EQ(checker3.callcount, 1); + + MPI_Comm_free(&comm3); + EXPECT_EQ(checker1.callcount, 1); + EXPECT_EQ(checker2.callcount, 0); + EXPECT_EQ(checker3.callcount, 1); +} + + +TEST(KeyManager, OrderedKeys) +{ + MPI_Comm comm1=MPI_COMM_WORLD, comm2, comm3, comm4; + int myRank, commSize; + MPI_Comm_rank(comm1, &myRank); + MPI_Comm_size(comm1, &commSize); + + int color = myRank == commSize-1 ? MPI_UNDEFINED : 1; + MPI_Comm_split(comm1, color, 0, &comm2); + MPI_Comm_dup(comm1, &comm3); + MPI_Comm_dup(comm1, &comm4); + + auto keyManager = std::make_shared(); + keyManager->get_key(comm1); + if (color != MPI_UNDEFINED) + keyManager->get_key(comm2); + + keyManager->get_key(comm3); + if (color != MPI_UNDEFINED) + MPI_Comm_free(&comm2); + + keyManager->get_key(comm4); + + std::vector comms{comm1, comm3, comm4}; + std::sort(comms.begin(), comms.end(), stk::impl::CommCompare(keyManager)); + + // if this doesn't hang, the comms are in the same order on all procs + for (auto& comm : comms) + MPI_Barrier(comm); + + MPI_Comm_free(&comm3); + MPI_Comm_free(&comm4); +} + +#endif \ No newline at end of file diff --git a/packages/stk/stk_unit_tests/stk_util/parallel/UnitTestMPITagManager.cpp b/packages/stk/stk_unit_tests/stk_util/parallel/UnitTestMPITagManager.cpp index 9c61b2d56963..f5cfc2063d21 100644 --- a/packages/stk/stk_unit_tests/stk_util/parallel/UnitTestMPITagManager.cpp +++ b/packages/stk/stk_unit_tests/stk_util/parallel/UnitTestMPITagManager.cpp @@ -31,64 +31,107 @@ // (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_util/stk_config.h" // for STK_HAS_MPI +#ifdef STK_HAS_MPI + #include "gtest/gtest.h" #include "stk_util/parallel/MPITagManager.hpp" +#include namespace { +MPI_Comm copy_comm(MPI_Comm comm) +{ + MPI_Comm newcomm; + MPI_Comm_dup(comm, &newcomm); + return newcomm; +} + + +class MPITagManagerForTesting : public stk::MPITagManager +{ + public: + MPITagManagerForTesting(int deletionGroupSize, int delayCount) : + MPITagManager(deletionGroupSize, delayCount) + {} +}; + + +std::shared_ptr make_tag_manager_for_testing(int deletionGroupSize, int delayCount) +{ + return std::make_shared(deletionGroupSize, delayCount); +} + + class TagManagerTester : public ::testing::Test { protected: TagManagerTester() : - tag_manager(stk::get_mpi_tag_manager()) + tag_manager_ptr(make_tag_manager_for_testing(1, 0)), + tag_manager(*tag_manager_ptr) + + { + comm1 = copy_comm(MPI_COMM_WORLD); + comm2 = copy_comm(MPI_COMM_WORLD); + } + + ~TagManagerTester() { - comm1 = MPI_COMM_WORLD; - MPI_Comm_dup(comm1, &comm2); + MPI_Comm_free(&comm1); + MPI_Comm_free(&comm2); } MPI_Comm comm1; MPI_Comm comm2; + std::shared_ptr tag_manager_ptr; stk::MPITagManager& tag_manager; }; +void sleep(int milliseconds) +{ + std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); +} + } // namespace -TEST_F(TagManagerTester, TagUniqueness) +TEST_F(TagManagerTester, TagComm) { - auto tag1 = tag_manager.get_tag(comm1, 1); - auto tag2 = tag_manager.get_tag(comm1, 1); - auto tag3 = tag_manager.get_tag(comm1, 1); - auto tag4 = tag_manager.get_tag(comm1, 1); - - EXPECT_NE(tag1, tag2); - EXPECT_NE(tag1, tag3); - EXPECT_NE(tag1, tag4); + stk::MPITag tag1 = tag_manager.get_tag(comm1); + stk::MPITag tag2 = tag_manager.get_tag(comm2); + stk::MPITag tag3 = tag_manager.get_tag(comm1); + stk::MPITag tag4 = tag_manager.get_tag(comm2); + + EXPECT_EQ(tag1.get_comm(), comm1); + EXPECT_EQ(tag2.get_comm(), comm2); + EXPECT_EQ(tag3.get_comm(), comm1); + EXPECT_EQ(tag4.get_comm(), comm2); +} - EXPECT_NE(tag2, tag1); - EXPECT_NE(tag2, tag3); - EXPECT_NE(tag2, tag4); - EXPECT_NE(tag3, tag1); - EXPECT_NE(tag3, tag2); - EXPECT_NE(tag3, tag4); +TEST_F(TagManagerTester, TagUniqueness) +{ + std::set unique_tags; + stk::MPITag tag1 = tag_manager.get_tag(comm1, 1); unique_tags.insert(tag1); + stk::MPITag tag2 = tag_manager.get_tag(comm1, 1); unique_tags.insert(tag2); + stk::MPITag tag3 = tag_manager.get_tag(comm1, 1); unique_tags.insert(tag3); + stk::MPITag tag4 = tag_manager.get_tag(comm1, 1); unique_tags.insert(tag4); - EXPECT_NE(tag3, tag1); - EXPECT_NE(tag3, tag2); - EXPECT_NE(tag3, tag4); + EXPECT_EQ(unique_tags.size(), 4u); } TEST_F(TagManagerTester, TagUniquenessWithHoles) { - auto tag1 = tag_manager.get_tag(comm1, 1); - auto tag2 = tag_manager.get_tag(comm1, 4); - auto tag3 = tag_manager.get_tag(comm1, 1); - auto tag4 = tag_manager.get_tag(comm1, 1); - auto tag5 = tag_manager.get_tag(comm1, 5); + stk::MPITag tag1 = tag_manager.get_tag(comm1, 1); + stk::MPITag tag2 = tag_manager.get_tag(comm1, 4); + stk::MPITag tag3 = tag_manager.get_tag(comm1, 1); + stk::MPITag tag4 = tag_manager.get_tag(comm1, 1); + stk::MPITag tag5 = tag_manager.get_tag(comm1, 5); std::vector tags{tag1, tag2, tag3, tag4, tag5}; - for (unsigned int i=0; i < tags.size(); ++i) + for (unsigned int i=0; i < tags.size(); ++i) { for (unsigned int j=0; j < tags.size(); ++j) { if (i == j) { EXPECT_EQ(tags[i], tags[j]); @@ -96,81 +139,130 @@ TEST_F(TagManagerTester, TagUniquenessWithHoles) EXPECT_NE(tags[i], tags[j]); } } + } } TEST_F(TagManagerTester, TagReuse) { { - auto tag1 = tag_manager.get_tag(comm1, 1); - auto tag2 = tag_manager.get_tag(comm1, 2); + stk::MPITag tag1 = tag_manager.get_tag(comm1, 1); + stk::MPITag tag2 = tag_manager.get_tag(comm1, 2); + EXPECT_EQ(static_cast(tag1), 1); EXPECT_EQ(static_cast(tag2), 2); - } + } // tags get freed - // the tags should have be freed at the end of the block { - auto tag1 = tag_manager.get_tag(comm1, 1); - auto tag2 = tag_manager.get_tag(comm1, 2); + stk::MPITag tag1 = tag_manager.get_tag(comm1, 1); + stk::MPITag tag2 = tag_manager.get_tag(comm1, 2); + EXPECT_EQ(static_cast(tag1), 1); EXPECT_EQ(static_cast(tag2), 2); } } +TEST_F(TagManagerTester, TagReuseMultipleComms) +{ + { + stk::MPITag tag11 = tag_manager.get_tag(comm1, 1); + stk::MPITag tag12 = tag_manager.get_tag(comm1, 2); + + stk::MPITag tag21 = tag_manager.get_tag(comm2, 1); + stk::MPITag tag22 = tag_manager.get_tag(comm2, 2); + + EXPECT_EQ(static_cast(tag11), 1); + EXPECT_EQ(static_cast(tag12), 2); + EXPECT_EQ(static_cast(tag21), 1); + EXPECT_EQ(static_cast(tag22), 2); + } // tags get freed + + { + stk::MPITag tag11 = tag_manager.get_tag(comm1, 1); + stk::MPITag tag12 = tag_manager.get_tag(comm1, 2); + + stk::MPITag tag21 = tag_manager.get_tag(comm2, 1); + stk::MPITag tag22 = tag_manager.get_tag(comm2, 2); + + EXPECT_EQ(static_cast(tag11), 1); + EXPECT_EQ(static_cast(tag12), 2); + EXPECT_EQ(static_cast(tag21), 1); + EXPECT_EQ(static_cast(tag22), 2); + } + +} + TEST_F(TagManagerTester, TagCopying) { { - auto tag1 = tag_manager.get_tag(comm1, 1); - auto tag2 = tag1; - auto tag3 = tag2; + stk::MPITag tag1 = tag_manager.get_tag(comm1, 1); + stk::MPITag tag2 = tag1; + stk::MPITag tag3 = tag2; EXPECT_EQ(static_cast(tag1), 1); EXPECT_EQ(static_cast(tag2), 1); - EXPECT_EQ(static_cast(tag2), 1); - } // if a tag was double freed, an error will be thrown here + EXPECT_EQ(static_cast(tag3), 1); + } } TEST_F(TagManagerTester, CommFree) { { - auto tag1 = tag_manager.get_tag(comm2, 1); - auto tag2 = tag_manager.get_tag(comm2, 2); - auto tag3 = tag_manager.get_tag(comm2, 3); + MPI_Comm comm3 = copy_comm(comm1); + stk::MPITag tag1 = tag_manager.get_tag(comm3, 1); + stk::MPITag tag2 = tag_manager.get_tag(comm3, 2); + stk::MPITag tag3 = tag_manager.get_tag(comm3, 3); - MPI_Comm_free(&comm2); - } // if a tag was double freed, an error will be thrown here + MPI_Comm_free(&comm3); + } } -TEST_F(TagManagerTester, CommFree2) +TEST_F(TagManagerTester, CommFree_ResetTagRange) { { - auto tag1 = tag_manager.get_tag(comm2, 1); - auto tag2 = tag_manager.get_tag(comm2, 2); - auto tag3 = tag_manager.get_tag(comm2, 3); + MPI_Comm comm3 = copy_comm(comm1); + stk::MPITag tag1 = tag_manager.get_tag(comm3, 1); + stk::MPITag tag2 = tag_manager.get_tag(comm3, 2); + stk::MPITag tag3 = tag_manager.get_tag(comm3, 3); - MPI_Comm_free(&comm2); - MPI_Comm_dup(comm1, &comm2); + MPI_Comm_free(&comm3); + MPI_Comm_dup(comm1, &comm3); - auto tag4 = tag_manager.get_tag(comm2, 1); + stk::MPITag tag4 = tag_manager.get_tag(comm3, 1); EXPECT_EQ(static_cast(tag4), 1); - } // if a tag was double freed, an error will be thrown here + } } -TEST_F(TagManagerTester, CommFreeMultiple) +TEST_F(TagManagerTester, CommFree_ResetTagRangeNewScope) { - MPI_Comm comm3, comm4, comm5; + { + MPI_Comm comm3 = copy_comm(comm1); + stk::MPITag tag1 = tag_manager.get_tag(comm3, 1); + stk::MPITag tag2 = tag_manager.get_tag(comm3, 2); + stk::MPITag tag3 = tag_manager.get_tag(comm3, 3); - MPI_Comm_dup(comm1, &comm3); - MPI_Comm_dup(comm1, &comm4); - MPI_Comm_dup(comm1, &comm5); + MPI_Comm_free(&comm3); + } + + { + MPI_Comm comm3 = copy_comm(comm1); + stk::MPITag tag4 = tag_manager.get_tag(comm3, 1); + EXPECT_EQ(static_cast(tag4), 1); + } +} - auto tag11 = tag_manager.get_tag(comm1); - auto tag21 = tag_manager.get_tag(comm2); - auto tag31 = tag_manager.get_tag(comm3); - auto tag41 = tag_manager.get_tag(comm4); - auto tag51 = tag_manager.get_tag(comm5); +TEST_F(TagManagerTester, CommFreeMultiple) +{ + MPI_Comm comm3 = copy_comm(comm1); + MPI_Comm comm4 = copy_comm(comm1); + MPI_Comm comm5 = copy_comm(comm1); + stk::MPITag tag11 = tag_manager.get_tag(comm1); + stk::MPITag tag21 = tag_manager.get_tag(comm2); + stk::MPITag tag31 = tag_manager.get_tag(comm3); + stk::MPITag tag41 = tag_manager.get_tag(comm4); + stk::MPITag tag51 = tag_manager.get_tag(comm5); MPI_Comm_free(&comm3); MPI_Comm_free(&comm4); @@ -178,12 +270,12 @@ TEST_F(TagManagerTester, CommFreeMultiple) MPI_Comm_dup(comm1, &comm3); MPI_Comm_dup(comm1, &comm4); - auto tag32 = tag_manager.get_tag(comm3); - auto tag42 = tag_manager.get_tag(comm4); + stk::MPITag tag32 = tag_manager.get_tag(comm3); + stk::MPITag tag42 = tag_manager.get_tag(comm4); std::vector tags{tag11, tag21, tag32, tag42, tag51}; - for (unsigned int i=0; i < tags.size(); ++i) + for (unsigned int i=0; i < tags.size(); ++i) { for (unsigned int j=0; j < tags.size(); ++j) { if (i == j) { EXPECT_EQ(tags[i], tags[j]); @@ -191,11 +283,221 @@ TEST_F(TagManagerTester, CommFreeMultiple) EXPECT_NE(tags[i], tags[j]); } } - + } EXPECT_NE(tag31, tag31); EXPECT_NE(tag41, tag41); + for (unsigned int i=0; i < tags.size(); ++i) { EXPECT_NE(tag31, tags[i]); EXPECT_NE(tag41, tags[i]); } -} \ No newline at end of file +} + + +TEST(TagManager, NonSortedCommOrder_DoesntHang) +{ + MPI_Comm comm1=MPI_COMM_WORLD, comm2, comm3, comm4; + int myRank; + MPI_Comm_rank(comm1, &myRank); + + int color = myRank == 0 ? MPI_UNDEFINED : 1; + MPI_Comm_split(comm1, color, 0, &comm2); + MPI_Comm_dup(comm1, &comm3); + MPI_Comm_dup(comm1, &comm4); + + { + int deletionGroupSize = 1, delayCount = 100; + auto tagManager = make_tag_manager_for_testing(deletionGroupSize, delayCount); + tagManager->get_tag(comm1); + if (color != MPI_UNDEFINED) { + tagManager->get_tag(comm2); + } + + tagManager->get_tag(comm3); + if (color != MPI_UNDEFINED) { + MPI_Comm_free(&comm2); + } + + tagManager->get_tag(comm4); + } +} + + +void perf_test(int deletionGroupSize, int delayCount, int ntags, int freeEvery) +{ + auto tagManager = make_tag_manager_for_testing(deletionGroupSize, delayCount); + + std::vector tags; + tags.reserve(ntags); + + MPI_Barrier(MPI_COMM_WORLD); + auto t_start = MPI_Wtime(); + for (int i=0; i < ntags; ++i) { + tags.push_back(tagManager->get_tag(MPI_COMM_WORLD, 1)); + if (i % freeEvery == 0) { + tags.clear(); + } + } + + auto elapsed_time = MPI_Wtime() - t_start; + + int myRank; + MPI_Comm_rank(MPI_COMM_WORLD, &myRank); + if (myRank == 0) { + std::cout << "elapsed time for " << ntags << ", freed every " << freeEvery << " = " << elapsed_time + << ", time per tag = " << elapsed_time/ntags << std::endl; + } + + MPI_Barrier(MPI_COMM_WORLD); + +} + +TEST(TagManager, MeasureKeyPerformance) +{ + + perf_test(32, 16, 1024, 1024); + perf_test(32, 16, 1024, 96); + perf_test(32, 16, 2048, 2048); + perf_test(32, 16, 2048, 96); + perf_test(32, 16, 4096, 4096); + perf_test(32, 16, 4096, 96); + perf_test(32, 16, 8192, 8192); + perf_test(32, 16, 8192, 96); + perf_test(32, 16, 16384, 16384); + perf_test(32, 16, 16384, 96); + + + int myRank; + MPI_Comm_rank(MPI_COMM_WORLD, &myRank); + + if (myRank == 0) { + std::cout << "\nSecond round" << std::endl; + } + perf_test(32, 16, 1024, 1024); + perf_test(32, 16, 1024, 96); + perf_test(32, 16, 2048, 2048); + perf_test(32, 16, 2048, 96); + perf_test(32, 16, 4096, 4096); + perf_test(32, 16, 4096, 96); + perf_test(32, 16, 8192, 8192); + perf_test(32, 16, 8192, 96); + perf_test(32, 16, 16384, 16384); + perf_test(32, 16, 16384, 96); +} + + + +namespace { +void check_tags_same_on_all_procs(MPI_Comm comm, const std::vector& vals) +{ + int myRank, commSize; + MPI_Comm_rank(comm, &myRank); + MPI_Comm_size(comm, &commSize); + + int root = 0; + int niters = vals.size(); + std::vector vals_all(niters * commSize); + MPI_Gather(vals.data(), niters, MPI_INT, vals_all.data(), niters, MPI_INT, root, comm); + if (myRank == root) { + for (int i=0; i < niters; ++i) { + for (int rank=0; rank < commSize; ++rank) { + EXPECT_EQ(vals[i], vals_all[rank * niters + i]); + } + } + } +} +} + +TEST(TagManager, MisalignedProcs) +{ + MPI_Comm comm1 = MPI_COMM_WORLD; + int myRank, commSize; + MPI_Comm_rank(comm1, &myRank); + MPI_Comm_size(comm1, &commSize); + + int deletionGroupSize=16, delayCount=8; + auto tagManager = make_tag_manager_for_testing(deletionGroupSize, delayCount); + std::vector tag_vals; + + int niters = 50; + for (int i=0; i < niters; ++i) { + tag_vals.push_back(tagManager->get_tag(comm1)); + sleep(10*myRank); + } + + check_tags_same_on_all_procs(comm1, tag_vals); +} + +TEST(TagManager, MisalignedProcsMultipleComms) +{ + MPI_Comm comm1 = copy_comm(MPI_COMM_WORLD); + int myRank1, commSize1; + MPI_Comm_rank(comm1, &myRank1); + MPI_Comm_size(comm1, &commSize1); + + MPI_Comm comm2; + int color = 0; + if (commSize1 >= 2) { + color = myRank1 / (commSize1 / 2); + } + MPI_Comm_split(comm1, color, 0, &comm2); + + int deletionGroupSize=16, delayCount=8; + auto tagManager = make_tag_manager_for_testing(deletionGroupSize, delayCount); + std::vector tag_vals1, tag_vals2; + + int niters = 50; + for (int i=0; i < niters; ++i) { + tag_vals1.push_back(tagManager->get_tag(comm1)); + tag_vals2.push_back(tagManager->get_tag(comm2)); + sleep(10*myRank1); + } + + check_tags_same_on_all_procs(comm1, tag_vals1); + check_tags_same_on_all_procs(comm2, tag_vals2); + + MPI_Comm_free(&comm1); + MPI_Comm_free(&comm2); +} + + +TEST(TagManager, MisalignedProcsFreePeriodically) +{ + MPI_Comm comm1 = copy_comm(MPI_COMM_WORLD); + int myRank, commSize; + MPI_Comm_rank(comm1, &myRank); + MPI_Comm_size(comm1, &commSize); + + int deletionGroupSize=16, delayCount=8; + auto tagManager = make_tag_manager_for_testing(deletionGroupSize, delayCount); + std::vector tags; + std::vector> tag_vals; + + int niters = 50, free_every = 22; + for (int i=0; i < niters; ++i) { + tags.push_back(tagManager->get_tag(comm1)); + sleep(10*myRank); + + if (i % free_every == 0) { + tag_vals.emplace_back(tags.begin(), tags.end()); + tags.clear(); + } + } + + for (auto& tag_vals_group : tag_vals) { + check_tags_same_on_all_procs(comm1, tag_vals_group); + } + + MPI_Comm_free(&comm1); +} + + + +TEST(TagManager, StaticInstance) +{ + stk::get_mpi_tag_manager().get_tag(MPI_COMM_WORLD); + + // if this doesn't segfault when MPI_Finalize is called, then the test passes +} + +#endif \ No newline at end of file diff --git a/packages/stk/stk_util/stk_util/parallel/CommReplacer.cpp b/packages/stk/stk_util/stk_util/parallel/CommReplacer.cpp new file mode 100644 index 000000000000..f6f3cb70a487 --- /dev/null +++ b/packages/stk/stk_util/stk_util/parallel/CommReplacer.cpp @@ -0,0 +1,79 @@ +#include "stk_util/parallel/CommReplacer.hpp" +#include "stk_util/util/ReportHandler.hpp" // for ThrowAssertMsg, ThrowRequire + +namespace stk { +namespace impl { + +#ifdef MPI_KEY_MANAGER_COMM_DESTRUCTOR_CALLBACK_BROKEN + +CommReplacer::CommReplacer() +{ + MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &m_mpiAttrKey, nullptr); +} + + +MPI_Comm CommReplacer::get_copied_comm(MPI_Comm origComm) +{ + int* unused = nullptr; + int foundFlag; + MPI_Comm_get_attr(origComm, m_mpiAttrKey, &unused, &foundFlag); + + if (!foundFlag) { + delete_comm_pair(origComm); + MPI_Comm_set_attr(origComm, m_mpiAttrKey, nullptr); + + + MPI_Comm copyComm; + MPI_Comm_dup(origComm, ©Comm); + m_origComms.push_back(origComm); + m_copyComms.push_back(copyComm); + + return copyComm; + } else { + for (unsigned int i=0; i < m_origComms.size(); ++i) { + if (m_origComms[i] == origComm) { + return m_copyComms[i]; + } + } + + ThrowRequireMsg(false, "Unable to find origComm"); + } + + return MPI_COMM_NULL; +} + + +MPI_Comm CommReplacer::get_orig_comm(MPI_Comm copyComm) +{ + for (unsigned int i=0; i < m_copyComms.size(); ++i) { + if (m_copyComms[i] == copyComm) { + return m_origComms[i]; + } + } + + ThrowRequireMsg(false, "Unable to find copyComm"); + return MPI_COMM_NULL; +} + + +void CommReplacer::delete_comm_pair(MPI_Comm origComm) +{ + for (unsigned int i=0; i < m_origComms.size(); ++i) { + if (origComm == m_origComms[i]) + { + MPI_Comm_free(&(m_copyComms[i])); + auto itOrig = m_origComms.begin(); + auto itCopy = m_copyComms.begin(); + std::advance(itOrig, i); + std::advance(itCopy, i); + + m_origComms.erase(itOrig); + m_copyComms.erase(itCopy); + } + } +} + +#endif + +} // namespace +} // namespace \ No newline at end of file diff --git a/packages/stk/stk_util/stk_util/parallel/CommReplacer.hpp b/packages/stk/stk_util/stk_util/parallel/CommReplacer.hpp new file mode 100644 index 000000000000..12753de52ef3 --- /dev/null +++ b/packages/stk/stk_util/stk_util/parallel/CommReplacer.hpp @@ -0,0 +1,33 @@ +#ifndef stk_util_parallel_CommReplacer +#define stk_util_parallel_CommReplacer + +#include +#include "stk_util/parallel/Parallel.hpp" // for MPI +#include "stk_util/parallel/MPICommKey.hpp" // for MPIKeyManager + +namespace stk { +namespace impl { + +#ifdef MPI_KEY_MANAGER_COMM_DESTRUCTOR_CALLBACK_BROKEN + class CommReplacer + { + public: + CommReplacer(); + + MPI_Comm get_copied_comm(MPI_Comm origComm); + + MPI_Comm get_orig_comm(MPI_Comm copyComm); + + void delete_comm_pair(MPI_Comm origComm); + + private: + std::vector m_origComms; + std::vector m_copyComms; + int m_mpiAttrKey; + }; +#endif + +} // namespace +} // namespace + +#endif \ No newline at end of file diff --git a/packages/stk/stk_util/stk_util/parallel/CommTagInUseList.cpp b/packages/stk/stk_util/stk_util/parallel/CommTagInUseList.cpp new file mode 100644 index 000000000000..febd512fcc5b --- /dev/null +++ b/packages/stk/stk_util/stk_util/parallel/CommTagInUseList.cpp @@ -0,0 +1,177 @@ +#include "stk_util/parallel/CommTagInUseList.hpp" +#include +#include +#include + +namespace stk { +namespace impl { + +CommTagInUseList::~CommTagInUseList() +{ + for (auto& deletionGroup : m_deletionGroups) { + if (deletionGroup.is_barrier_in_progress()) { + deletionGroup.finish_barrier(); + erase_internal(deletionGroup.get_tags()); + } + } + + for (auto& weak_tag_ptr : m_tags) { + if (auto tag_shared_ptr = weak_tag_ptr.second.lock()) { + tag_shared_ptr->set_free(); + } + } +} + + +void CommTagInUseList::insert(std::shared_ptr newTag) +{ + #ifdef MPI_KEY_MANAGER_COMM_DESTRUCTOR_CALLBACK_BROKEN + assert(are_comms_identical(m_comm, newTag->get_comm_internal())); + #else + assert(are_comms_identical(m_comm, newTag->get_comm())); + #endif + + int tagVal = newTag->get_tag(); + ThrowRequireMsg(m_tags.count(tagVal) == 0, "Cannot create new tag with same value as existing tag"); + + auto iteratorBoolPair = m_tags.insert(std::make_pair(tagVal, newTag)); + assert(iteratorBoolPair.second); + + if (newTag->get_tag() == m_minFreeTag) + { + auto it = iteratorBoolPair.first; + int prevVal = it->first; + bool found = false; + while (it != m_tags.end()) + { + int currentVal = it->first; + if (currentVal - prevVal > 1) + { + m_minFreeTag = prevVal + 1; + found = true; + break; + } + prevVal = it->first; + it++; + } + + if (!found) + m_minFreeTag = (std::prev(m_tags.end()))->first + 1; + } + + increment_entry_count(); +} + + +void CommTagInUseList::erase(MPITagData& tag) +{ + #ifdef MPI_KEY_MANAGER_COMM_DESTRUCTOR_CALLBACK_BROKEN + assert(are_comms_identical(m_comm, tag.get_comm_internal())); + #else + assert(are_comms_identical(m_comm, tag.get_comm())); + #endif + + auto& deletionGroup = m_deletionGroups.back(); + deletionGroup.insert_tag(tag.get_tag()); + + if (deletionGroup.get_tags().size() == m_deletionGroupSize) { + deletionGroup.start_barrier(m_entryCount); + + MPI_Comm comm; +#ifdef MPI_KEY_MANAGER_COMM_DESTRUCTOR_CALLBACK_BROKEN + comm = tag.get_comm_internal(); +#else + comm = tag.get_comm(); +#endif + m_deletionGroups.emplace_back(comm); + } + + tag.set_free(); +} + + +int CommTagInUseList::get_min_free_tag() +{ + check_tag_deletion_completion(); + return m_minFreeTag; +} + + +const std::map>& CommTagInUseList::get_tags() +{ + check_tag_deletion_completion(); + return m_tags; +} + + +void CommTagInUseList::check_tag_deletion_completion() +{ + int groupsFreed = 0; + for ( auto& deletionGroup : m_deletionGroups) + { + bool barrierInProgress = deletionGroup.is_barrier_in_progress(); + if (barrierInProgress) { + bool isDelaySatisfied = is_delay_satisfied(deletionGroup.get_entry_count_barrier_start()); + + if (isDelaySatisfied) { + deletionGroup.finish_barrier(); + erase_internal(deletionGroup.get_tags()); + groupsFreed++; + } else { + deletionGroup.test_barrier(); + } + } + + if (!barrierInProgress){ + break; + } + } + + if (groupsFreed > 0) + { + auto begin = m_deletionGroups.begin(); + auto end = m_deletionGroups.begin(); + std::advance(end, groupsFreed); + m_deletionGroups.erase(begin, end); + } +} + + +CommTagInUseList::EntryCountInt CommTagInUseList::increment_entry_count() +{ + if (std::numeric_limits::max() == m_entryCount) + throw std::runtime_error("Cannot call get_tag() more than " + + std::to_string(std::numeric_limits::max()) + " times"); + + return ++m_entryCount; +} + + +bool CommTagInUseList::is_delay_satisfied(EntryCountInt startCount) +{ + auto currentCount = m_entryCount; + assert(currentCount >= startCount); + return currentCount - startCount >= m_delayCount; +} + + +void CommTagInUseList::erase_internal(const std::vector& tagVals) +{ + for (auto& tag_val : tagVals) { + ThrowRequireMsg(m_tags.count(tag_val) == 1, "Cannot free tag this has not been assigned (possible double free)"); + m_tags.erase(tag_val); + m_minFreeTag = std::min(m_minFreeTag, tag_val); + } +} + + +bool CommTagInUseList::are_comms_identical(MPI_Comm comm1, MPI_Comm comm2) +{ + int result; + MPI_Comm_compare(comm1, comm2, &result); + return result == MPI_IDENT; +} + + +} +} \ No newline at end of file diff --git a/packages/stk/stk_util/stk_util/parallel/CommTagInUseList.hpp b/packages/stk/stk_util/stk_util/parallel/CommTagInUseList.hpp new file mode 100644 index 000000000000..e6c72d56300b --- /dev/null +++ b/packages/stk/stk_util/stk_util/parallel/CommTagInUseList.hpp @@ -0,0 +1,73 @@ +#ifndef stk_util_parallel_CommManagerData +#define stk_util_parallel_CommManagerData + +#include +#include +#include +#include +#include "stk_util/parallel/MPITag.hpp" +#include "stk_util/util/ReportHandler.hpp" // for ThrowAssertMsg, ThrowRequire +#include "stk_util/parallel/DeletionGroup.hpp" + +namespace stk { +namespace impl { + + +class CommTagInUseList +{ + public: + CommTagInUseList(MPI_Comm comm, int minTag, int deletionGroupSize, int delayCount) : + m_comm(comm), + m_entryCount(0), + m_minFreeTag(minTag), + m_deletionGroupSize(deletionGroupSize), + m_delayCount(delayCount) + { + m_deletionGroups.emplace_back(comm); + } + + ~CommTagInUseList(); + + CommTagInUseList(const CommTagInUseList&) = delete; + + CommTagInUseList& operator=(const CommTagInUseList&) = delete; + + MPI_Comm get_comm() const { return m_comm; } + + void insert(std::shared_ptr new_tag); + + void erase(MPITagData& tag); + + int get_min_free_tag(); + + const std::map>& get_tags(); + + private: + using EntryCountInt = DeletionGroup::EntryCountInt; + + using MPITagInt = int; + + void check_tag_deletion_completion(); + + EntryCountInt increment_entry_count(); + + bool is_delay_satisfied(EntryCountInt startCount); + + void erase_internal(const std::vector& tags); + + bool are_comms_identical(MPI_Comm comm1, MPI_Comm comm2); + + MPI_Comm m_comm; + EntryCountInt m_entryCount; + std::map> m_tags; + std::deque m_deletionGroups; + int m_minFreeTag; + const size_t m_deletionGroupSize; + const EntryCountInt m_delayCount; +}; + + +} +} + +#endif \ No newline at end of file diff --git a/packages/stk/stk_util/stk_util/parallel/DeletionGroup.cpp b/packages/stk/stk_util/stk_util/parallel/DeletionGroup.cpp new file mode 100644 index 000000000000..81a615bb6291 --- /dev/null +++ b/packages/stk/stk_util/stk_util/parallel/DeletionGroup.cpp @@ -0,0 +1,90 @@ +#include "stk_util/parallel/DeletionGroup.hpp" + +namespace stk { +namespace impl { + +DeletionGroup::DeletionGroup(MPI_Comm comm) : + m_comm(comm), + m_req(MPI_REQUEST_NULL), + m_barrierSemanticallyInProgress(false), + m_barrierActuallyInProgress(false), + m_entryCount(0) +#ifndef NDEBUG + , m_req_debug(MPI_REQUEST_NULL) +#endif +{ +#ifndef NDEBUG + int commSize, myRank; + MPI_Comm_rank(comm, &myRank); + MPI_Comm_size(comm, &commSize); + if (myRank == 0) + m_entryCounts.resize(commSize); +#endif +} + +DeletionGroup::~DeletionGroup() +{ + if (m_barrierActuallyInProgress) + std::cerr << "Error: DeletionGroup destructed without calling finish_barrier() first. " + << "MPI may terminate abnormally or produce undefined behavior" << std::endl; +} + + +void DeletionGroup::start_barrier(int entryCount) +{ + assert(!m_barrierSemanticallyInProgress); + + MPI_Ibarrier(m_comm, &m_req); + m_barrierActuallyInProgress = true; + m_barrierSemanticallyInProgress = true; + m_entryCount = entryCount; + +#ifndef NDEBUG + MPI_Igather(&m_entryCount, 1, EntryCountIntDatatype, m_entryCounts.data(), 1, + EntryCountIntDatatype, 0, m_comm, &m_req_debug); +#endif +} + +void DeletionGroup::finish_barrier() +{ + assert(m_barrierSemanticallyInProgress); + if (m_barrierActuallyInProgress) { + MPI_Wait(&m_req, MPI_STATUS_IGNORE); + m_barrierActuallyInProgress = false; + m_barrierSemanticallyInProgress = false; + } + +#ifndef NDEBUG + int myRank; + MPI_Comm_rank(m_comm, &myRank); + MPI_Wait(&m_req_debug, MPI_STATUS_IGNORE); + + if (myRank == 0) { + for (unsigned int i=1; i < m_entryCounts.size(); ++i) { + assert(m_entryCounts[i] == m_entryCounts[0]); + } + } +#endif +} + +DeletionGroup::EntryCountInt DeletionGroup::get_entry_count_barrier_start() const +{ + assert(m_barrierSemanticallyInProgress); + return m_entryCount; +} + + +void DeletionGroup::test_barrier() +{ + assert(m_barrierSemanticallyInProgress); + if (!m_barrierActuallyInProgress) + return; + + int flag; + MPI_Test(&m_req, &flag, MPI_STATUS_IGNORE); + if (flag) + m_barrierActuallyInProgress = false; +} + +} +} \ No newline at end of file diff --git a/packages/stk/stk_util/stk_util/parallel/DeletionGroup.hpp b/packages/stk/stk_util/stk_util/parallel/DeletionGroup.hpp new file mode 100644 index 000000000000..737e7ea7c4b9 --- /dev/null +++ b/packages/stk/stk_util/stk_util/parallel/DeletionGroup.hpp @@ -0,0 +1,59 @@ +#ifndef stk_util_parallel_DeletionGroup +#define stk_util_parallel_DeletionGroup + +#include +#include "stk_util/parallel/MPITag.hpp" + +namespace stk { +namespace impl { + +class DeletionGroup +{ + public: + using EntryCountInt = unsigned long long int; + MPI_Datatype EntryCountIntDatatype = MPI_UNSIGNED_LONG_LONG; + + DeletionGroup(MPI_Comm comm); + + ~DeletionGroup(); + + MPI_Comm get_comm() const { return m_comm; } + + void insert_tag(int tag) { m_tags.push_back(tag); } + + const std::vector& get_tags() const { return m_tags; } + + // returns true if the MPI_Ibarrier is *semantically* in progress (ie. if start_barrier() has + // been called but finish_barrier() has not) + bool is_barrier_in_progress() const { return m_barrierSemanticallyInProgress; } + + void start_barrier(int entryCount); + + void finish_barrier(); + + EntryCountInt get_entry_count_barrier_start() const; + + // use this function to trip the MPI progress engine. + // You still must call finish_barrier() to complete + // the operation + void test_barrier(); + + + private: + MPI_Comm m_comm; + MPI_Request m_req; + bool m_barrierSemanticallyInProgress; + bool m_barrierActuallyInProgress; + EntryCountInt m_entryCount; + std::vector m_tags; + +#ifndef NDEBUG + MPI_Request m_req_debug; + std::vector m_entryCounts; +#endif +}; + +} +} + +#endif \ No newline at end of file diff --git a/packages/stk/stk_util/stk_util/parallel/MPICommKey.cpp b/packages/stk/stk_util/stk_util/parallel/MPICommKey.cpp index 32e170065758..6543d5ea426a 100644 --- a/packages/stk/stk_util/stk_util/parallel/MPICommKey.cpp +++ b/packages/stk/stk_util/stk_util/parallel/MPICommKey.cpp @@ -1,9 +1,13 @@ - +#include +#include +#include #include "stk_util/parallel/MPICommKey.hpp" #include "ParallelComm.hpp" namespace stk { +namespace impl { + bool CommCompare::operator()(MPI_Comm comm1, MPI_Comm comm2) { auto key1 = m_manager->get_key(comm1); @@ -18,21 +22,21 @@ bool CommCompare::operator()(MPI_Comm comm1, MPI_Comm comm2) const return std::less{}(key1, key2); } -namespace Impl { +namespace impl { -int delete_mpi_comm_key(MPI_Comm comm,int comm_keyval, void* attribute_val, void* extra_state) +int delete_mpi_comm_key(MPI_Comm comm, int comm_keyval, void* attribute_val, void* extra_state) { - //auto comm_key_ptr = reinterpret_cast(attribute_val); MPIKeyManager* key_manager = reinterpret_cast(extra_state); - // the predefined comms sometimes (but not allways) get freed after the - // MPICommManager static variable, so we don't need to (and can't) - // unregister them - bool isSpecial = comm == MPI_COMM_WORLD || - comm == MPI_COMM_SELF || - comm == MPI_COMM_NULL; - if (!isSpecial) { - key_manager->free_comm(comm); - } + key_manager->free_comm(comm); + + return MPI_SUCCESS; +} + + +int destruct_mpi_key_manager(MPI_Comm comm,int comm_keyval, void* attribute_val, void* extra_state) +{ + MPIKeyManager* key_manager = reinterpret_cast(extra_state); + key_manager->destructor(); return MPI_SUCCESS; } @@ -46,7 +50,33 @@ MPIKeyManager::MPIKeyManager() MPI_Initialized(&isInitialized); ThrowRequireMsg(isInitialized, "MPI must be initialized prior to constructing MPIKeyManager"); - MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, &Impl::delete_mpi_comm_key, &m_mpiAttrKey, this); + MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, &impl::delete_mpi_comm_key, &m_mpiAttrKey, this); + + // The deleter function will be called when MPI_Finalize is invoked. This + // is the recommended way to execute callbacks, see Section 8.7.1 of the + // MPI 3.1 Standard. + MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, &impl::destruct_mpi_key_manager, &m_destructorAttrKey, this); + MPI_Comm_set_attr(MPI_COMM_SELF, m_destructorAttrKey, nullptr); + + int myRank; + MPI_Comm_rank(MPI_COMM_WORLD, &myRank); + m_currentCommKey = myRank; +} + +MPIKeyManager::~MPIKeyManager() +{ + int isMpiFinalized = false; + MPI_Finalized(&isMpiFinalized); + if (isMpiFinalized) { + assert(m_isFinalized); + } + + if (!isMpiFinalized) + { + // call destructor() via the MPI callback, and also ensure destructor() + // doesn't get called again when MPI_Finalize is called + MPI_Comm_delete_attr(MPI_COMM_SELF, m_destructorAttrKey); + } } @@ -59,8 +89,10 @@ MPIKeyManager::CommKey MPIKeyManager::get_key(MPI_Comm comm) if (!foundFlag) { commKey = generate_comm_key(); MPI_Comm_set_attr(comm, m_mpiAttrKey, const_cast(commKey)); + m_comms[*commKey] = comm; } + return *commKey; } @@ -85,36 +117,62 @@ bool MPIKeyManager::has_key(MPI_Comm comm) } -void MPIKeyManager::register_callback(MPI_Comm comm, Callback func) +MPIKeyManager::CallerUID MPIKeyManager::get_UID() { - get_key(comm); - m_callbacks[comm].push_back(func); + return m_currUID++; } +void MPIKeyManager::register_callback(MPI_Comm comm, CallerUID uid, Callback func) +{ + assert(uid < m_currUID); + auto key = get_key(comm); + m_callbacks[key][uid].push_back(func); +} -const MPIKeyManager::CommKey* MPIKeyManager::generate_comm_key() + +void MPIKeyManager::execute_callbacks_immediately(CallerUID uid) { - // find first unused key in range [0, int_max] - CommKey valPrev = -1, valFound = -1; - if (m_usedCommKeys.size() == 0) { - valFound = 0; - } else { - for (auto v : m_usedCommKeys) - { - if (v - valPrev > 1) { - valFound = valPrev + 1; - break; - } - - valPrev = v; - } + for (auto& commKeyMapPair : m_callbacks) + { + MPI_Comm comm = m_comms[commKeyMapPair.first]; + auto& uidCallbackVecMap = commKeyMapPair.second; + if (uidCallbackVecMap.count(uid) == 0) + continue; + + for (auto& callback : uidCallbackVecMap[uid]) + callback(comm); + + uidCallbackVecMap.erase(uid); } +} - if (valFound == -1) { - valFound = *(std::prev(m_usedCommKeys.end())) + 1; + +void MPIKeyManager::unregister_callbacks(CallerUID uid) +{ + for (auto& comm_map_pair : m_callbacks) + { + auto& uidCallbackVecMap = comm_map_pair.second; + if (uidCallbackVecMap.count(uid) > 0) { + uidCallbackVecMap.erase(uid); + } } +} - ThrowRequireMsg(valFound >= 0, "generate_comm_key() failed or overflowed"); + +MPIKeyManager::CommKey MPIKeyManager::get_next_comm_key() +{ + auto max_val = std::numeric_limits::max(); + if (m_currentCommKey == max_val) + throw std::runtime_error(std::string("cannot have more than ") + + std::to_string(max_val) + " communicators in a program"); + + return m_currentCommKey++; +} + + +const MPIKeyManager::CommKey* MPIKeyManager::generate_comm_key() +{ + auto valFound = get_next_comm_key(); auto p = m_usedCommKeys.insert(valFound); ThrowRequireMsg(p.second, "Error in generateCommKey()"); @@ -125,13 +183,34 @@ const MPIKeyManager::CommKey* MPIKeyManager::generate_comm_key() void MPIKeyManager::free_comm(MPI_Comm comm) { - ThrowRequireMsg(m_usedCommKeys.count(get_key(comm)) == 1, "Cannot free MPI Comm that is not assigned (possible double free)"); - for ( auto& callback : m_callbacks[comm]) - callback(comm); + const auto& this_ref = *this; + auto key = this_ref.get_key(comm); + ThrowRequireMsg(m_usedCommKeys.count(key) == 1, "Cannot free MPI Comm that is not assigned (possible double free)"); + for (auto& uidCallbackVecPair : m_callbacks[key]) { + for (auto& callback : uidCallbackVecPair.second) { + callback(comm); + } + } + + m_callbacks.erase(key); + m_usedCommKeys.erase(key); + m_comms.erase(key); +} + + +void MPIKeyManager::destructor() +{ + while (!m_comms.empty()) { + auto& p = *(m_comms.begin()); + // delete the attribute to trigger callback to free_comm(), and + // also ensure the callback does *not* get called again when + // the comm is freed + MPI_Comm_delete_attr(p.second, m_mpiAttrKey); + } - m_callbacks.erase(comm); - m_usedCommKeys.erase(get_key(comm)); - + m_isFinalized = true; } -} \ No newline at end of file +} + +} diff --git a/packages/stk/stk_util/stk_util/parallel/MPICommKey.hpp b/packages/stk/stk_util/stk_util/parallel/MPICommKey.hpp index 579f56aac674..020a6872100e 100644 --- a/packages/stk/stk_util/stk_util/parallel/MPICommKey.hpp +++ b/packages/stk/stk_util/stk_util/parallel/MPICommKey.hpp @@ -5,11 +5,20 @@ #include #include #include +#include #include #include "Parallel.hpp" // for MPI +// Detect if MPI has bug +#ifdef MPICH + #define MPI_KEY_MANAGER_COMM_DESTRUCTOR_CALLBACK_BROKEN +#endif + namespace stk { +//TODO: get rid of this once MPICH/IntelMPI is fixed +namespace impl { + class MPIKeyManager; class CommCompare @@ -28,54 +37,121 @@ class CommCompare }; -namespace Impl { +namespace impl { int delete_mpi_comm_key(MPI_Comm comm,int comm_keyval, void* attribute_val, void* extra_state); + + int destruct_mpi_key_manager(MPI_Comm comm,int comm_keyval, void* attribute_val, void* extra_state); } // Assigns keys to MPI_Comm objects. In conjunction with CommCompare, allows // storing MPI_Comms in stl containers that require a comparison function. +// MPI_Comms sort in the same order on all processes. +// The key value is *not* guaranteed to be the same on all processes. // Note: once the communicator is destroyed (ex. by MPI_Comm_free), it is no longer // possible to use a container that contains the destroyed MPI_Comm. Use // the register_callback() function to get notified just before the MPI_Comm // gets destroyed so you can remove it from your data structures. +// Callbacks will also be called when MPI_Finalize is called or when +// the MPIKeyManager destructor runs. The latter case can be a +// problem if the the callback requires another object to still +// be alive. Use execute_callbacks_immediately() or +// unregister_callbacks() to handle this. One particular case +// of this problem is: +// +// class Foo +// { +// public: +// Foo() : +// m_keyManager(std::make_shared()), +// m_map(CommCompare(m_keyManager)) +// { +// m_callerUID = m_keyManager.get_UID(); +// m_keyManager.register_callback(..., m_callerUID, ...); +// } +// +// ~Foo() +// { +// m_keyManager.execute_callbacks_immediately(m_callerUID); +// } +// +// +// +// private: +// std::shared_ptr m_keyManager; +// std::map m_map; +// MPIKeyManager::CallerUID m_callerUID; +// }; +// +// Notice the call to execute_callbacks_immediately() in the destructor. +// Without this, the callbacks would execute when the m_keyManager +// member is destructed, which happens *after* m_map is destructed. +// So if the callback uses m_map, the program will have undefined +// behavior. For this reason, it is recommended to put a call +// to either execute_callbacks_immediately() or unregister_callbacks() +// in the destructor body. class MPIKeyManager { public: - using CommKey = int; + using CommKey = unsigned long long; + + using CallerUID = unsigned long long; using Callback = std::function; MPIKeyManager(); - ~MPIKeyManager() = default; + ~MPIKeyManager(); + + MPIKeyManager(const MPIKeyManager&) = delete; + + MPIKeyManager& operator=(const MPIKeyManager&) = delete; + + MPIKeyManager(MPIKeyManager&& ) = delete; + + MPIKeyManager& operator=(MPIKeyManager&&) = delete; CommKey get_key(MPI_Comm comm); CommKey get_key(MPI_Comm comm) const; - bool has_key(MPI_Comm comm); - // registers a callback that will be called just before the MPI_Comm is destroyed. + CallerUID get_UID(); + + // registers a callback that will be called just before the MPI_Comm is destroyed, or + // MPI_Finalize is called, or this class gets destructed. // Function must be callable as func(MPI_Comm) - void register_callback(MPI_Comm comm, Callback func); + void register_callback(MPI_Comm comm, CallerUID uid, Callback func); + + void execute_callbacks_immediately(CallerUID uid); + + void unregister_callbacks(CallerUID uid); private: + CommKey get_next_comm_key(); const CommKey* generate_comm_key(); void free_comm(MPI_Comm comm); + void destructor(); int m_mpiAttrKey; + int m_destructorAttrKey; + CommKey m_currentCommKey = 0; + CallerUID m_currUID = 0; std::set m_usedCommKeys; - std::map> m_callbacks; - - friend int Impl::delete_mpi_comm_key(MPI_Comm comm,int comm_keyval, void* attribute_val, void* extra_state); + std::map>> m_callbacks; + std::map m_comms; + bool m_isFinalized = false; + friend int impl::delete_mpi_comm_key(MPI_Comm comm,int comm_keyval, void* attribute_val, void* extra_state); + friend int impl::destruct_mpi_key_manager(MPI_Comm comm,int comm_keyval, void* attribute_val, void* extra_state); }; -} +} // namespace + +} // namespace #endif diff --git a/packages/stk/stk_util/stk_util/parallel/MPITag.cpp b/packages/stk/stk_util/stk_util/parallel/MPITag.cpp new file mode 100644 index 000000000000..37e064955ec5 --- /dev/null +++ b/packages/stk/stk_util/stk_util/parallel/MPITag.cpp @@ -0,0 +1,23 @@ +#include "stk_util/parallel/MPITag.hpp" +#include "stk_util/parallel/MPITagManager.hpp" + +namespace stk { +namespace impl { + +MPITagData::~MPITagData() +{ + if (!m_isFree) + m_manager->free_tag_local(*this); +} + +MPIKeyManager::CommKey MPITagData::get_comm_key() +{ +#ifdef MPI_KEY_MANAGER_COMM_DESTRUCTOR_CALLBACK_BROKEN + return m_manager->m_keyManager->get_key(m_commInternal); +#else + return m_manager->m_keyManager->get_key(m_comm); +#endif +} + +} // namespace +} // namespace \ No newline at end of file diff --git a/packages/stk/stk_util/stk_util/parallel/MPITag.hpp b/packages/stk/stk_util/stk_util/parallel/MPITag.hpp new file mode 100644 index 000000000000..01a9cba9b208 --- /dev/null +++ b/packages/stk/stk_util/stk_util/parallel/MPITag.hpp @@ -0,0 +1,123 @@ +#ifndef stk_util_parallel_MPITag +#define stk_util_parallel_MPITag + +#include +#include +#include "stk_util/parallel/Parallel.hpp" // for MPI +#include "stk_util/parallel/MPICommKey.hpp" +#include "stk_util/util/ReportHandler.hpp" // for ThrowAssertMsg, ThrowRequire + + +namespace stk { + +class MPITagManager; + +namespace impl { + +class MPITagData +{ + public: + + MPITagData(MPITagManager* manager, + MPI_Comm comm, +#ifdef MPI_KEY_MANAGER_COMM_DESTRUCTOR_CALLBACK_BROKEN + MPI_Comm commInternal, +#endif + int tag) : + m_manager(manager), + m_comm(comm), +#ifdef MPI_KEY_MANAGER_COMM_DESTRUCTOR_CALLBACK_BROKEN + m_commInternal(commInternal), +#endif + m_tag(tag) + {} + + ~MPITagData(); + + MPITagData(const MPITagData&) = delete; + + MPITagData& operator=(const MPITagData&) = delete; + + int get_tag() { return m_tag;} + + MPI_Comm get_comm() { return m_comm;} + +#ifdef MPI_KEY_MANAGER_COMM_DESTRUCTOR_CALLBACK_BROKEN + MPI_Comm get_comm_internal() { return m_commInternal; } +#endif + + MPIKeyManager::CommKey get_comm_key(); + + void set_free() { m_isFree = true;} + + bool is_free() { return m_isFree; } + + MPITagManager* get_tag_manager() { return m_manager; } + + private: + MPITagManager* m_manager; + MPI_Comm m_comm; +#ifdef MPI_KEY_MANAGER_COMM_DESTRUCTOR_CALLBACK_BROKEN + MPI_Comm m_commInternal; +#endif + int m_tag; + bool m_isFree = false; +}; + +} // namespace + + +// an MPI tag that is currently in use. Note that it is implicitly convertable +// to int, so it can be passed directly into MPI routines. +class MPITag +{ + public: + explicit MPITag(std::shared_ptr data) : + m_data(data) + {} + + operator int() const { return m_data->get_tag(); } + + MPI_Comm get_comm() const { return m_data->get_comm(); } + + private: + void set_free() + { + m_data->set_free(); + } + + std::shared_ptr m_data; + + friend MPITagManager; + + friend bool operator==(const MPITag& lhs, const MPITag& rhs); + friend bool operator!=(const MPITag& lhs, const MPITag& rhs); + friend std::ostream& operator<<(std::ostream& os, const MPITag& tag); +}; + +inline bool operator==(const MPITag& lhs, const MPITag& rhs) +{ + ThrowRequireMsg(lhs.m_data->get_tag_manager() == rhs.m_data->get_tag_manager(), + "Cannot compare MPITags on different MPITagManagers"); + + return static_cast(lhs) == static_cast(rhs) && + !lhs.m_data->is_free() && !rhs.m_data->is_free() && + lhs.m_data->get_comm_key() == rhs.m_data->get_comm_key(); +} + +inline bool operator!=(const MPITag& lhs, const MPITag& rhs) +{ + return !(lhs == rhs); +} + +inline std::ostream& operator<<(std::ostream& os, const MPITag& tag) +{ + os << "MPITag with value " << tag.m_data->get_tag() << " on Comm with key " + << tag.m_data->get_comm_key() << ", is_free = " << tag.m_data->is_free(); + + return os; +} + +} // namespace + +#endif \ No newline at end of file diff --git a/packages/stk/stk_util/stk_util/parallel/MPITagManager.cpp b/packages/stk/stk_util/stk_util/parallel/MPITagManager.cpp index bd40edf61028..205e1d9e235a 100644 --- a/packages/stk/stk_util/stk_util/parallel/MPITagManager.cpp +++ b/packages/stk/stk_util/stk_util/parallel/MPITagManager.cpp @@ -3,20 +3,12 @@ namespace stk { -namespace Impl { +MPITagManager::MPITagManager(int deletionGroupSize, int delayCount) : + m_keyManager(std::make_shared()), + m_commData(impl::CommCompare(m_keyManager)), -MPITagData::~MPITagData() -{ - if (!m_isFree) - m_manager->free_tag(*this); -} - -} // namespace - -MPITagManager::MPITagManager() : - m_keyManager(std::make_shared()), - m_commCompare(m_keyManager), - m_tags(m_commCompare) + m_deletionGroupSize(deletionGroupSize), + m_delayCount(delayCount) { int isInitialized; MPI_Initialized(&isInitialized); @@ -28,92 +20,135 @@ MPITagManager::MPITagManager() : ThrowRequireMsg(flag, "This MPI implementation is erroneous"); ThrowRequireMsg(*val >= m_tagMax, "MPI_TAG_UB must be at least " + std::to_string(m_tagMax)); m_tagMax = *val; -} + m_callbackUID = m_keyManager->get_UID(); +} -MPITag MPITagManager::get_tag(MPI_Comm comm) +MPITagManager::~MPITagManager() { - return get_tag(comm, m_tagMin); + m_keyManager->execute_callbacks_immediately(m_callbackUID); } -MPITag MPITagManager::get_tag(MPI_Comm comm, int tagHint) + +MPITag MPITagManager::get_tag(MPI_Comm userComm, int tagHint) { + MPI_Comm comm; +#ifdef MPI_KEY_MANAGER_COMM_DESTRUCTOR_CALLBACK_BROKEN + comm = m_commReplacer.get_copied_comm(userComm); +#else + comm = userComm; +#endif + if (!m_keyManager->has_key(comm)) { - m_keyManager->get_key(comm); - m_keyManager->register_callback(comm, std::bind(&MPITagManager::free_comm_keys, this, std::placeholders::_1)); + m_keyManager->register_callback(userComm, m_callbackUID, std::bind(&MPITagManager::erase_comm, this, std::placeholders::_1)); + m_commData.emplace(std::piecewise_construct, std::make_tuple(comm), std::make_tuple(comm, m_tagMin, m_deletionGroupSize, m_delayCount)); } - auto& commRecord = m_tags[comm]; - auto& tags = commRecord.tags; + auto& commData = m_commData.at(comm); + auto newTag = get_new_tag(commData, tagHint); - auto it = tags.find(tagHint); +#ifdef MPI_KEY_MANAGER_COMM_DESTRUCTOR_CALLBACK_BROKEN + auto tagData = std::make_shared(this, userComm, comm, newTag); +#else + auto tagData = std::make_shared(this, comm, newTag); +#endif + commData.insert(tagData); + + return MPITag(tagData); +} + + +int MPITagManager::get_new_tag(impl::CommTagInUseList& commData, int tagHint) +{ + int newTag = -1; + if (tagHint == MPI_ANY_TAG) { + newTag = get_any_tag(commData); + } else { + newTag = new_tag_search(commData, tagHint); + } + + assert(newTag >= 0); + ThrowRequireMsg(newTag <= m_tagMax, "New tag must be <= " + std::to_string(m_tagMax)); + check_same_value_on_all_procs_debug_only(commData.get_comm(), newTag); + + return newTag; +} + + +int MPITagManager::get_any_tag(impl::CommTagInUseList& commData) +{ + int newTag = commData.get_min_free_tag(); + ThrowRequireMsg(newTag <= m_tagMax, std::string("MPI tag supply exhausted: there can only be ") + + std::to_string(m_tagMax) + " tags in use at any time"); + + return newTag; +} + + +int MPITagManager::new_tag_search(impl::CommTagInUseList& commData, int tagHint) +{ + const auto& tags = commData.get_tags(); int newTag = -1; + auto it = tags.find(tagHint); if (it == tags.end()) { newTag = tagHint; } else { // find next available tag - int prevVal = *it; + int prevVal = it->first; while (it != tags.end()) { - if ( (*it - prevVal) > 1) + if ( (it->first - prevVal) > 1) { newTag = prevVal + 1; break; } - prevVal = *it; + prevVal = it->first; it++; } if (newTag == -1) { // if no spaces between existing tags found - newTag = *(std::prev(tags.end())) + 1; + newTag = (std::prev(tags.end()))->first + 1; } } - assert(newTag != -1); - ThrowRequireMsg(newTag <= m_tagMax, "New tag must be <= " + std::to_string(m_tagMax)); - debug_check(comm, newTag); - - auto tagData = std::make_shared(this, comm, newTag); - commRecord.insert(tagData); - - return MPITag(tagData); + return newTag; } -void MPITagManager::free_tag(MPITag& tag) +void MPITagManager::free_tag_local(impl::MPITagData& tag) { - free_tag(*(tag.m_data)); -} - -void MPITagManager::free_tag(Impl::MPITagData& tag) -{ - m_tags.at(tag.get_comm()).erase(tag); - tag.set_free(); + MPI_Comm comm; +#ifdef MPI_KEY_MANAGER_COMM_DESTRUCTOR_CALLBACK_BROKEN + comm = tag.get_comm_internal(); +#else + comm = tag.get_comm(); +#endif + m_commData.at(comm).erase(tag); } -//----------------------------------------------------------------------------- -// MPI_Comm key management - - -void MPITagManager::free_comm_keys(MPI_Comm comm) +void MPITagManager::erase_comm(MPI_Comm origComm) { - ThrowRequireMsg(m_tags.count(comm) == 1, "Cannot free MPI Comm that is not assigned (possible double free)"); + MPI_Comm comm; +#ifdef MPI_KEY_MANAGER_COMM_DESTRUCTOR_CALLBACK_BROKEN + comm = m_commReplacer.get_copied_comm(origComm); +#else + comm = origComm; +#endif - auto& commRecords = m_tags[comm]; - for (auto& weak_tag_ptr : commRecords.tagPtrs) { - if (auto tag_ptr = weak_tag_ptr.second.lock()) { - tag_ptr->set_free(); - } - } + ThrowRequireMsg(m_commData.count(comm) == 1, "Cannot free MPI Comm that is not assigned (possible double free)"); + m_commData.erase(comm); - m_tags.erase(comm); +#ifdef MPI_KEY_MANAGER_COMM_DESTRUCTOR_CALLBACK_BROKEN + m_commReplacer.delete_comm_pair(origComm); +#endif } -void MPITagManager::debug_check(MPI_Comm comm, int newVal) + +void MPITagManager::check_same_value_on_all_procs_debug_only(MPI_Comm comm, int newVal) { #ifndef NDEBUG int commSize, myrank; @@ -136,36 +171,23 @@ void MPITagManager::debug_check(MPI_Comm comm, int newVal) MPI_Barrier(comm); #endif - } -//----------------------------------------------------------------------------- -// CommRecord - -void MPITagManager::CommRecord::insert(std::shared_ptr new_tag) -{ - int tag_val = new_tag->get_tag(); - ThrowRequireMsg(tags.count(tag_val) == 0, "Cannot create new tag with same value as existing tag"); - - tags.insert(tag_val); - tagPtrs[tag_val] = new_tag; -} - -void MPITagManager::CommRecord::erase(Impl::MPITagData& tag) -{ - int tag_val = tag.get_tag(); - ThrowRequireMsg(tags.count(tag_val) == 1, "Cannot free tag this has not been assigned (possible double free"); - - tags.erase(tag_val); - tagPtrs.erase(tag_val); -} - - - MPITagManager& get_mpi_tag_manager() { - static MPITagManager tagManager; + int deletionGroupSize = 32; + static int delayCount = -1; + if (delayCount < 0) + { + int commSize; + MPI_Comm_size(MPI_COMM_WORLD, &commSize); + // some MPI_Barrier algorithms use a tree based algorithm, + // travering it down and them up again, which likely takes + // 2 * log2(number of ranks) + delayCount = std::max(2*std::ceil(std::log2(commSize)), 4.0); + } + static MPITagManager tagManager(deletionGroupSize, delayCount); return tagManager; } diff --git a/packages/stk/stk_util/stk_util/parallel/MPITagManager.hpp b/packages/stk/stk_util/stk_util/parallel/MPITagManager.hpp index 66b51bffbb31..24f3ce6bec8e 100644 --- a/packages/stk/stk_util/stk_util/parallel/MPITagManager.hpp +++ b/packages/stk/stk_util/stk_util/parallel/MPITagManager.hpp @@ -35,23 +35,26 @@ #ifndef stk_util_parallel_MPITagManager #define stk_util_parallel_MPITagManager +#include "stk_util/stk_config.h" // for STK_HAS_MPI +#ifdef STK_HAS_MPI + #include #include +#include +#include #include #include +#include #include "MPICommKey.hpp" #include "stk_util/parallel/Parallel.hpp" // for MPI #include "stk_util/parallel/MPICommKey.hpp" // for MPIKeyManager +#include "stk_util/parallel/MPITag.hpp" #include "stk_util/util/ReportHandler.hpp" // for ThrowAssertMsg, ThrowRequire +#include "stk_util/parallel/CommReplacer.hpp" +#include "stk_util/parallel/CommTagInUseList.hpp" -namespace stk { - -class MPITag; - -namespace Impl { - class MPITagData; -} +namespace stk { // class for managing which MPI tags are in use on which communicator // Note: all operations on this class are logically collective: they @@ -59,152 +62,67 @@ namespace Impl { // same order. class MPITagManager { - public: + protected: + //TODO: writeup delayCount theory into manual + MPITagManager(int deletionGroupSize, int delayCount); + public: - ~MPITagManager() {} + ~MPITagManager(); MPITagManager(const MPITagManager&) = delete; MPITagManager& operator=(const MPITagManager&) = delete; - //using CommKey = int; + MPITagManager(MPITagManager&&) = delete; - // get an unused tag - MPITag get_tag(MPI_Comm comm); + MPITagManager& operator=(MPITagManager&&) = delete; // try to get tag given tag, or a nearby one if that specified one is unavailable - MPITag get_tag(MPI_Comm comm, int tagHint); + // Note: this is a collective operation + MPITag get_tag(MPI_Comm comm, int tagHint=MPI_ANY_TAG); private: + //------------------------------------------------------------------------- + // Tag generation - MPITagManager(); - - struct CommRecord - { - CommRecord() = default; - - CommRecord(const CommRecord&) = delete; + int get_new_tag(impl::CommTagInUseList& commData, int tagHint); - CommRecord& operator=(const CommRecord&) = delete; + int get_any_tag(impl::CommTagInUseList& commData); - void insert(std::shared_ptr new_tag); + int new_tag_search(impl::CommTagInUseList& commData, int tagHint); - void erase(Impl::MPITagData& tag); + //------------------------------------------------------------------------- + // Tag and Comm freeing - std::set tags; - std::map> tagPtrs; // maps tag values to the MPITagData objects (pointers) - }; + void free_tag_local(impl::MPITagData& tag); - void free_tag(MPITag& tag); + void erase_comm(MPI_Comm comm); - void free_tag(Impl::MPITagData& tag); + void check_same_value_on_all_procs_debug_only(MPI_Comm comm, int newVal); - void free_comm_keys(MPI_Comm comm); - - // checks that new_val is the same on all procs (in debug mode only) - void debug_check(MPI_Comm comm, int newVal); - - std::shared_ptr m_keyManager; - CommCompare m_commCompare; - std::map m_tags; + std::shared_ptr m_keyManager; + std::map m_commData; +#ifdef MPI_KEY_MANAGER_COMM_DESTRUCTOR_CALLBACK_BROKEN + impl::CommReplacer m_commReplacer; +#endif + const unsigned int m_deletionGroupSize; // number of tags to free as a group + const unsigned int m_delayCount; // wait on MPI_Ibarriers after this many + // entries to get_tag() with the same MPI_Comm const int m_tagMin = 1024; int m_tagMax = 32767; - int m_mpiAttrKey; + impl::MPIKeyManager::CallerUID m_callbackUID = 0; - friend Impl::MPITagData; - friend MPITag; + friend impl::MPITagData; friend MPITagManager& get_mpi_tag_manager(); }; -namespace Impl { - -class MPITagData -{ - public: - - MPITagData(MPITagManager* manager, MPI_Comm comm, int tag) : - m_manager(manager), - m_comm(comm), - m_tag(tag) - {} - - ~MPITagData(); - - int get_tag() { return m_tag;} - - MPI_Comm get_comm() { return m_comm;} - - MPIKeyManager::CommKey get_comm_key() { return m_manager->m_keyManager->get_key(m_comm); } - - void set_free() { m_isFree = true;} - - bool is_free() { return m_isFree; } - - MPITagManager* get_tag_manager() { return m_manager; } - - private: - MPITagManager* m_manager; - MPI_Comm m_comm; - int m_tag; - bool m_isFree = false; -}; - -} // namespace Impl -// an MPI tag that is currently in use. Note that it is implicitly convertable -// to int, so it can be passed directly into MPI routines. -class MPITag -{ - public: - explicit MPITag(std::shared_ptr data) : - m_data(data) - {} - - operator int() const { return m_data->get_tag(); } - - private: - void set_free() - { - m_data->set_free(); - } - - std::shared_ptr m_data; - - friend MPITagManager; - - friend bool operator==(const MPITag& lhs, const MPITag& rhs); - friend bool operator!=(const MPITag& lhs, const MPITag& rhs); - friend std::ostream& operator<<(std::ostream& os, const MPITag& tag); -}; - -inline bool operator==(const MPITag& lhs, const MPITag& rhs) -{ - ThrowRequireMsg(lhs.m_data->get_tag_manager() == rhs.m_data->get_tag_manager(), - "Cannot compare MPITags on different MPITagManagers"); - - return static_cast(lhs) == static_cast(rhs) && - !lhs.m_data->is_free() && !rhs.m_data->is_free() && - lhs.m_data->get_comm_key() == rhs.m_data->get_comm_key(); -} - -inline bool operator!=(const MPITag& lhs, const MPITag& rhs) -{ - return !(lhs == rhs); -} - -inline std::ostream& operator<<(std::ostream& os, const MPITag& tag) -{ - os << "MPITag with value " << tag.m_data->get_tag() << " on Comm with key " - << tag.m_data->get_comm_key() << ", is_free = " << tag.m_data->is_free(); - - return os; +MPITagManager& get_mpi_tag_manager(); } -MPITagManager& get_mpi_tag_manager(); - -} -#endif \ No newline at end of file +#endif +#endif diff --git a/packages/stk/stk_util/stk_util/registry/ProductRegistry.cpp b/packages/stk/stk_util/stk_util/registry/ProductRegistry.cpp index 7bdb05e005cc..256d49ed514e 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.7.1-554-gc83e8fe2" +#define STK_VERSION_STRING "5.7.2-179-g3f1355cd" #endif namespace stk { From 2e66248ab52d57480897f6c0141e95a97d3c2c4c Mon Sep 17 00:00:00 2001 From: James Elliott Date: Wed, 18 May 2022 11:05:25 -0700 Subject: [PATCH 16/21] Fix issue with Clang gpu compilation. Clang does not like dynamic initialization of a class variable when using a gpu/device target. It may be possible to address this in other ways, namely adding an explicit initialization when the class ETI is processed. Given that most (every?) solver replicated this default pattern, and all use std::cout as the default, this change removes the explicit variable with the default variable (which was const anyway). This potentialy may causes issues with Windows, which was already using a workaround to capture a pointer to cout. packages/belos/src/BelosBlockGmresSolMgr.hpp:340:37: error: dynamic initialization is not supported for __device__, __constant__, __shared__, and __managed__ variables. static constexpr std::ostream * outputStream_default_ = &std::cout; ^ ~~~~~~~~~~ Fixes #10535 --- packages/belos/src/BelosBiCGStabSolMgr.hpp | 13 +++---------- packages/belos/src/BelosBlockCGSolMgr.hpp | 13 +++---------- packages/belos/src/BelosBlockGmresSolMgr.hpp | 13 +++---------- packages/belos/src/BelosFixedPointSolMgr.hpp | 13 +++---------- packages/belos/src/BelosGCRODRSolMgr.hpp | 11 ++--------- packages/belos/src/BelosGmresPolyOp.hpp | 9 +-------- packages/belos/src/BelosGmresPolySolMgr.hpp | 13 +++---------- packages/belos/src/BelosPCPGSolMgr.hpp | 13 +++---------- packages/belos/src/BelosPseudoBlockCGSolMgr.hpp | 13 +++---------- packages/belos/src/BelosPseudoBlockGmresSolMgr.hpp | 13 +++---------- .../src/BelosPseudoBlockStochasticCGSolMgr.hpp | 13 +++---------- packages/belos/src/BelosPseudoBlockTFQMRSolMgr.hpp | 13 +++---------- packages/belos/src/BelosRCGSolMgr.hpp | 11 ++--------- packages/belos/src/BelosTFQMRSolMgr.hpp | 13 +++---------- 14 files changed, 38 insertions(+), 136 deletions(-) diff --git a/packages/belos/src/BelosBiCGStabSolMgr.hpp b/packages/belos/src/BelosBiCGStabSolMgr.hpp index 061e4bcd981a..d74b2fc8c24b 100644 --- a/packages/belos/src/BelosBiCGStabSolMgr.hpp +++ b/packages/belos/src/BelosBiCGStabSolMgr.hpp @@ -272,13 +272,6 @@ namespace Belos { static constexpr int defQuorum_default_ = 1; static constexpr const char * resScale_default_ = "Norm of Initial Residual"; static constexpr const char * label_default_ = "Belos"; -// https://stackoverflow.com/questions/24398102/constexpr-and-initialization-of-a-static-const-void-pointer-with-reinterpret-cas -#if defined(_WIN32) && defined(__clang__) - static constexpr std::ostream * outputStream_default_ = - __builtin_constant_p(reinterpret_cast(&std::cout)); -#else - static constexpr std::ostream * outputStream_default_ = &std::cout; -#endif // Current solver values. MagnitudeType convtol_,achievedTol_; @@ -298,7 +291,7 @@ namespace Belos { // Empty Constructor template BiCGStabSolMgr::BiCGStabSolMgr() : - outputStream_(Teuchos::rcp(outputStream_default_,false)), + outputStream_(Teuchos::rcpFromRef(std::cout)), convtol_(DefaultSolverParameters::convTol), maxIters_(maxIters_default_), numIters_(0), @@ -318,7 +311,7 @@ BiCGStabSolMgr:: BiCGStabSolMgr (const Teuchos::RCP > &problem, const Teuchos::RCP &pl ) : problem_(problem), - outputStream_(Teuchos::rcp(outputStream_default_,false)), + outputStream_(Teuchos::rcpFromRef(std::cout)), convtol_(DefaultSolverParameters::convTol), maxIters_(maxIters_default_), numIters_(0), @@ -590,7 +583,7 @@ BiCGStabSolMgr::getValidParameters() const pl->set("Deflation Quorum", static_cast(defQuorum_default_), "The number of linear systems that need to converge before\n" "they are deflated. This number should be <= block size."); - pl->set("Output Stream", Teuchos::rcp(outputStream_default_,false), + pl->set("Output Stream", Teuchos::rcpFromRef(std::cout), "A reference-counted pointer to the output stream where all\n" "solver output is sent."); pl->set("Show Maximum Residual Norm Only", static_cast(showMaxResNormOnly_default_), diff --git a/packages/belos/src/BelosBlockCGSolMgr.hpp b/packages/belos/src/BelosBlockCGSolMgr.hpp index 151e1a3c90ef..33aab3d90679 100644 --- a/packages/belos/src/BelosBlockCGSolMgr.hpp +++ b/packages/belos/src/BelosBlockCGSolMgr.hpp @@ -362,13 +362,6 @@ namespace Belos { static constexpr const char * label_default_ = "Belos"; static constexpr const char * orthoType_default_ = "ICGS"; static constexpr bool assertPositiveDefiniteness_default_ = true; -// https://stackoverflow.com/questions/24398102/constexpr-and-initialization-of-a-static-const-void-pointer-with-reinterpret-cas -#if defined(_WIN32) && defined(__clang__) - static constexpr std::ostream * outputStream_default_ = - __builtin_constant_p(reinterpret_cast(&std::cout)); -#else - static constexpr std::ostream * outputStream_default_ = &std::cout; -#endif // // Current solver parameters and other values. @@ -414,7 +407,7 @@ namespace Belos { // Empty Constructor template BlockCGSolMgr::BlockCGSolMgr() : - outputStream_(Teuchos::rcp(outputStream_default_,false)), + outputStream_(Teuchos::rcpFromRef(std::cout)), convtol_(DefaultSolverParameters::convTol), orthoKappa_(DefaultSolverParameters::orthoKappa), achievedTol_(Teuchos::ScalarTraits::zero()), @@ -442,7 +435,7 @@ BlockCGSolMgr:: BlockCGSolMgr(const Teuchos::RCP > &problem, const Teuchos::RCP &pl) : problem_(problem), - outputStream_(Teuchos::rcp(outputStream_default_,false)), + outputStream_(Teuchos::rcpFromRef(std::cout)), convtol_(DefaultSolverParameters::convTol), orthoKappa_(DefaultSolverParameters::orthoKappa), achievedTol_(Teuchos::ScalarTraits::zero()), @@ -788,7 +781,7 @@ BlockCGSolMgr::getValidParameters() const pl->set("Output Frequency", static_cast(outputFreq_default_), "How often convergence information should be outputted\n" "to the output stream."); - pl->set("Output Stream", Teuchos::rcp(outputStream_default_,false), + pl->set("Output Stream", Teuchos::rcpFromRef(std::cout), "A reference-counted pointer to the output stream where all\n" "solver output is sent."); pl->set("Show Maximum Residual Norm Only", static_cast(showMaxResNormOnly_default_), diff --git a/packages/belos/src/BelosBlockGmresSolMgr.hpp b/packages/belos/src/BelosBlockGmresSolMgr.hpp index ccb54ddfe9f8..8204640d1167 100644 --- a/packages/belos/src/BelosBlockGmresSolMgr.hpp +++ b/packages/belos/src/BelosBlockGmresSolMgr.hpp @@ -332,13 +332,6 @@ class BlockGmresSolMgr : public SolverManager { static constexpr const char * expResScale_default_ = "Norm of Initial Residual"; static constexpr const char * label_default_ = "Belos"; static constexpr const char * orthoType_default_ = "ICGS"; -// https://stackoverflow.com/questions/24398102/constexpr-and-initialization-of-a-static-const-void-pointer-with-reinterpret-cas -#if defined(_WIN32) && defined(__clang__) - static constexpr std::ostream * outputStream_default_ = - __builtin_constant_p(reinterpret_cast(&std::cout)); -#else - static constexpr std::ostream * outputStream_default_ = &std::cout; -#endif // Current solver values. MagnitudeType convtol_, orthoKappa_, achievedTol_; @@ -361,7 +354,7 @@ class BlockGmresSolMgr : public SolverManager { // Empty Constructor template BlockGmresSolMgr::BlockGmresSolMgr() : - outputStream_(Teuchos::rcp(outputStream_default_,false)), + outputStream_(Teuchos::rcpFromRef(std::cout)), convtol_(DefaultSolverParameters::convTol), orthoKappa_(DefaultSolverParameters::orthoKappa), achievedTol_(Teuchos::ScalarTraits::magnitudeType>::zero()), @@ -393,7 +386,7 @@ BlockGmresSolMgr:: BlockGmresSolMgr (const Teuchos::RCP > &problem, const Teuchos::RCP &pl) : problem_(problem), - outputStream_(Teuchos::rcp(outputStream_default_,false)), + outputStream_(Teuchos::rcpFromRef(std::cout)), convtol_(DefaultSolverParameters::convTol), orthoKappa_(DefaultSolverParameters::orthoKappa), achievedTol_(Teuchos::ScalarTraits::magnitudeType>::zero()), @@ -465,7 +458,7 @@ BlockGmresSolMgr::getValidParameters() const pl->set("Output Frequency", static_cast(outputFreq_default_), "How often convergence information should be outputted\n" "to the output stream."); - pl->set("Output Stream", Teuchos::rcp(outputStream_default_,false), + pl->set("Output Stream", Teuchos::rcpFromRef(std::cout), "A reference-counted pointer to the output stream where all\n" "solver output is sent."); pl->set("Show Maximum Residual Norm Only", static_cast(showMaxResNormOnly_default_), diff --git a/packages/belos/src/BelosFixedPointSolMgr.hpp b/packages/belos/src/BelosFixedPointSolMgr.hpp index eaed86b92833..e3f83f13b63c 100644 --- a/packages/belos/src/BelosFixedPointSolMgr.hpp +++ b/packages/belos/src/BelosFixedPointSolMgr.hpp @@ -285,13 +285,6 @@ namespace Belos { static constexpr int outputStyle_default_ = Belos::General; static constexpr int outputFreq_default_ = -1; static constexpr const char * label_default_ = "Belos"; -// https://stackoverflow.com/questions/24398102/constexpr-and-initialization-of-a-static-const-void-pointer-with-reinterpret-cas -#if defined(_WIN32) && defined(__clang__) - static constexpr std::ostream * outputStream_default_ = - __builtin_constant_p(reinterpret_cast(&std::cout)); -#else - static constexpr std::ostream * outputStream_default_ = &std::cout; -#endif // // Current solver parameters and other values. @@ -330,7 +323,7 @@ namespace Belos { // Empty Constructor template FixedPointSolMgr::FixedPointSolMgr() : - outputStream_(Teuchos::rcp(outputStream_default_,false)), + outputStream_(Teuchos::rcpFromRef(std::cout)), convtol_(DefaultSolverParameters::convTol), achievedTol_(Teuchos::ScalarTraits::zero()), maxIters_(maxIters_default_), @@ -351,7 +344,7 @@ FixedPointSolMgr:: FixedPointSolMgr(const Teuchos::RCP > &problem, const Teuchos::RCP &pl) : problem_(problem), - outputStream_(Teuchos::rcp(outputStream_default_,false)), + outputStream_(Teuchos::rcpFromRef(std::cout)), convtol_(DefaultSolverParameters::convTol), achievedTol_(Teuchos::ScalarTraits::zero()), maxIters_(maxIters_default_), @@ -574,7 +567,7 @@ FixedPointSolMgr::getValidParameters() const pl->set("Output Frequency", static_cast(outputFreq_default_), "How often convergence information should be outputted\n" "to the output stream."); - pl->set("Output Stream", Teuchos::rcp(outputStream_default_,false), + pl->set("Output Stream", Teuchos::rcpFromRef(std::cout), "A reference-counted pointer to the output stream where all\n" "solver output is sent."); pl->set("Show Maximum Residual Norm Only", static_cast(showMaxResNormOnly_default_), diff --git a/packages/belos/src/BelosGCRODRSolMgr.hpp b/packages/belos/src/BelosGCRODRSolMgr.hpp index d630849cd962..cae41efc6611 100644 --- a/packages/belos/src/BelosGCRODRSolMgr.hpp +++ b/packages/belos/src/BelosGCRODRSolMgr.hpp @@ -490,13 +490,6 @@ Systems," SIAM Journal on Scientific Computing, 28(5), pp. 1651-1674, static constexpr const char * expResScale_default_ = "Norm of Initial Residual"; static constexpr const char * label_default_ = "Belos"; static constexpr const char * orthoType_default_ = "ICGS"; -// https://stackoverflow.com/questions/24398102/constexpr-and-initialization-of-a-static-const-void-pointer-with-reinterpret-cas -#if defined(_WIN32) && defined(__clang__) - static constexpr std::ostream * outputStream_default_ = - __builtin_constant_p(reinterpret_cast(&std::cout)); -#else - static constexpr std::ostream * outputStream_default_ = &std::cout; -#endif // Current solver values. MagnitudeType convTol_, orthoKappa_, achievedTol_; @@ -592,7 +585,7 @@ GCRODRSolMgr(const Teuchos::RCP >& problem, // Common instructions executed in all constructors template void GCRODRSolMgr::init () { - outputStream_ = Teuchos::rcp(outputStream_default_,false); + outputStream_ = Teuchos::rcpFromRef(std::cout); convTol_ = DefaultSolverParameters::convTol; orthoKappa_ = orthoKappa_default_; maxRestarts_ = maxRestarts_default_; @@ -1175,7 +1168,7 @@ GCRODRSolMgr::getValidParameters() const pl->set("Output Frequency", static_cast(outputFreq_default_), "How often convergence information should be outputted\n" "to the output stream."); - pl->set("Output Stream", Teuchos::rcp(outputStream_default_,false), + pl->set("Output Stream", Teuchos::rcpFromRef(std::cout), "A reference-counted pointer to the output stream where all\n" "solver output is sent."); pl->set("Implicit Residual Scaling", static_cast(impResScale_default_), diff --git a/packages/belos/src/BelosGmresPolyOp.hpp b/packages/belos/src/BelosGmresPolyOp.hpp index 73421f8b4737..28f92caa112b 100644 --- a/packages/belos/src/BelosGmresPolyOp.hpp +++ b/packages/belos/src/BelosGmresPolyOp.hpp @@ -302,13 +302,6 @@ namespace Belos { static constexpr const char * label_default_ = "Belos"; static constexpr const char * polyType_default_ = "Roots"; static constexpr const char * orthoType_default_ = "DGKS"; -// https://stackoverflow.com/questions/24398102/constexpr-and-initialization-of-a-static-const-void-pointer-with-reinterpret-cas -#if defined(_WIN32) && defined(__clang__) - static constexpr std::ostream * outputStream_default_ = - __builtin_constant_p(reinterpret_cast(&std::cout)); -#else - static constexpr std::ostream * outputStream_default_ = &std::cout; -#endif static constexpr bool damp_default_ = false; static constexpr bool addRoots_default_ = true; @@ -319,7 +312,7 @@ namespace Belos { // Output manager. Teuchos::RCP > printer_; - Teuchos::RCP outputStream_ = Teuchos::rcp(outputStream_default_,false); + Teuchos::RCP outputStream_ = Teuchos::rcpFromRef(std::cout); // Orthogonalization manager. Teuchos::RCP > ortho_; diff --git a/packages/belos/src/BelosGmresPolySolMgr.hpp b/packages/belos/src/BelosGmresPolySolMgr.hpp index 9efe11da115d..1d41c6a8be34 100644 --- a/packages/belos/src/BelosGmresPolySolMgr.hpp +++ b/packages/belos/src/BelosGmresPolySolMgr.hpp @@ -342,13 +342,6 @@ class GmresPolySolMgr : public SolverManager { static constexpr bool addRoots_default_ = true; static constexpr bool dampPoly_default_ = false; static constexpr bool randomRHS_default_ = true; -// https://stackoverflow.com/questions/24398102/constexpr-and-initialization-of-a-static-const-void-pointer-with-reinterpret-cas -#if defined(_WIN32) && defined(__clang__) - static constexpr std::ostream * outputStream_default_ = - __builtin_constant_p(reinterpret_cast(&std::cout)); -#else - static constexpr std::ostream * outputStream_default_ = &std::cout; -#endif // Current solver values. MagnitudeType polyTol_, achievedTol_; @@ -381,7 +374,7 @@ class GmresPolySolMgr : public SolverManager { template GmresPolySolMgr::GmresPolySolMgr () : - outputStream_ (Teuchos::rcp(outputStream_default_,false)), + outputStream_ (Teuchos::rcpFromRef(std::cout)), polyTol_ (DefaultSolverParameters::polyTol), achievedTol_(MTS::zero()), maxDegree_ (maxDegree_default_), @@ -406,7 +399,7 @@ GmresPolySolMgr:: GmresPolySolMgr (const Teuchos::RCP > &problem, const Teuchos::RCP &pl) : problem_ (problem), - outputStream_ (Teuchos::rcp(outputStream_default_,false)), + outputStream_ (Teuchos::rcpFromRef(std::cout)), polyTol_ (DefaultSolverParameters::polyTol), maxDegree_ (maxDegree_default_), numIters_ (0), @@ -459,7 +452,7 @@ GmresPolySolMgr::getValidParameters() const pl->set("Verbosity", static_cast(verbosity_default_), "What type(s) of solver information should be outputted\n" "to the output stream."); - pl->set("Output Stream", Teuchos::rcp(outputStream_default_,false), + pl->set("Output Stream", Teuchos::rcpFromRef(std::cout), "A reference-counted pointer to the output stream where all\n" "solver output is sent."); pl->set("Timer Label", static_cast(label_default_), diff --git a/packages/belos/src/BelosPCPGSolMgr.hpp b/packages/belos/src/BelosPCPGSolMgr.hpp index 2f49381ffec8..c2fd577abdc6 100644 --- a/packages/belos/src/BelosPCPGSolMgr.hpp +++ b/packages/belos/src/BelosPCPGSolMgr.hpp @@ -377,13 +377,6 @@ namespace Belos { static constexpr int outputFreq_default_ = -1; static constexpr const char * label_default_ = "Belos"; static constexpr const char * orthoType_default_ = "ICGS"; -// https://stackoverflow.com/questions/24398102/constexpr-and-initialization-of-a-static-const-void-pointer-with-reinterpret-cas -#if defined(_WIN32) && defined(__clang__) - static constexpr std::ostream * outputStream_default_ = - __builtin_constant_p(reinterpret_cast(&std::cout)); -#else - static constexpr std::ostream * outputStream_default_ = &std::cout; -#endif // // Current solver values. @@ -425,7 +418,7 @@ namespace Belos { // Empty Constructor template PCPGSolMgr::PCPGSolMgr() : - outputStream_(Teuchos::rcp(outputStream_default_,false)), + outputStream_(Teuchos::rcpFromRef(std::cout)), convtol_(DefaultSolverParameters::convTol), orthoKappa_(DefaultSolverParameters::orthoKappa), achievedTol_(Teuchos::ScalarTraits::zero()), @@ -449,7 +442,7 @@ PCPGSolMgr::PCPGSolMgr( const Teuchos::RCP > &problem, const Teuchos::RCP &pl ) : problem_(problem), - outputStream_(Teuchos::rcp(outputStream_default_,false)), + outputStream_(Teuchos::rcpFromRef(std::cout)), convtol_(DefaultSolverParameters::convTol), orthoKappa_(DefaultSolverParameters::orthoKappa), @@ -720,7 +713,7 @@ PCPGSolMgr::getValidParameters() const pl->set("Output Frequency", static_cast(outputFreq_default_), "How often convergence information should be outputted\n" "to the output stream."); - pl->set("Output Stream", Teuchos::rcp(outputStream_default_,false), + pl->set("Output Stream", Teuchos::rcpFromRef(std::cout), "A reference-counted pointer to the output stream where all\n" "solver output is sent."); pl->set("Timer Label", static_cast(label_default_), diff --git a/packages/belos/src/BelosPseudoBlockCGSolMgr.hpp b/packages/belos/src/BelosPseudoBlockCGSolMgr.hpp index 874696379d40..67c931ca56fe 100644 --- a/packages/belos/src/BelosPseudoBlockCGSolMgr.hpp +++ b/packages/belos/src/BelosPseudoBlockCGSolMgr.hpp @@ -339,13 +339,6 @@ namespace Belos { static constexpr bool foldConvergenceDetectionIntoAllreduce_default_ = false; static constexpr const char * resScale_default_ = "Norm of Initial Residual"; static constexpr const char * label_default_ = "Belos"; -// https://stackoverflow.com/questions/24398102/constexpr-and-initialization-of-a-static-const-void-pointer-with-reinterpret-cas -#if defined(_WIN32) && defined(__clang__) - static constexpr std::ostream * outputStream_default_ = - __builtin_constant_p(reinterpret_cast(&std::cout)); -#else - static constexpr std::ostream * outputStream_default_ = &std::cout; -#endif static constexpr bool genCondEst_default_ = false; // Current solver values. @@ -370,7 +363,7 @@ namespace Belos { // Empty Constructor template PseudoBlockCGSolMgr::PseudoBlockCGSolMgr() : - outputStream_(Teuchos::rcp(outputStream_default_,false)), + outputStream_(Teuchos::rcpFromRef(std::cout)), convtol_(DefaultSolverParameters::convTol), maxIters_(maxIters_default_), numIters_(0), @@ -394,7 +387,7 @@ PseudoBlockCGSolMgr:: PseudoBlockCGSolMgr (const Teuchos::RCP > &problem, const Teuchos::RCP &pl ) : problem_(problem), - outputStream_(Teuchos::rcp(outputStream_default_,false)), + outputStream_(Teuchos::rcpFromRef(std::cout)), convtol_(DefaultSolverParameters::convTol), maxIters_(maxIters_default_), numIters_(0), @@ -723,7 +716,7 @@ PseudoBlockCGSolMgr::getValidParameters() const pl->set("Deflation Quorum", static_cast(defQuorum_default_), "The number of linear systems that need to converge before\n" "they are deflated. This number should be <= block size."); - pl->set("Output Stream", Teuchos::rcp(outputStream_default_,false), + pl->set("Output Stream", Teuchos::rcpFromRef(std::cout), "A reference-counted pointer to the output stream where all\n" "solver output is sent."); pl->set("Show Maximum Residual Norm Only", static_cast(showMaxResNormOnly_default_), diff --git a/packages/belos/src/BelosPseudoBlockGmresSolMgr.hpp b/packages/belos/src/BelosPseudoBlockGmresSolMgr.hpp index 0431419280d3..c09c3f55e6be 100644 --- a/packages/belos/src/BelosPseudoBlockGmresSolMgr.hpp +++ b/packages/belos/src/BelosPseudoBlockGmresSolMgr.hpp @@ -501,13 +501,6 @@ namespace Belos { static constexpr const char * expResScale_default_ = "Norm of Initial Residual"; static constexpr const char * label_default_ = "Belos"; static constexpr const char * orthoType_default_ = "ICGS"; -// https://stackoverflow.com/questions/24398102/constexpr-and-initialization-of-a-static-const-void-pointer-with-reinterpret-cas -#if defined(_WIN32) && defined(__clang__) - static constexpr std::ostream * outputStream_default_ = - __builtin_constant_p(reinterpret_cast(&std::cout)); -#else - static constexpr std::ostream * outputStream_default_ = &std::cout; -#endif // Current solver values. MagnitudeType convtol_, orthoKappa_, achievedTol_; @@ -531,7 +524,7 @@ namespace Belos { // Empty Constructor template PseudoBlockGmresSolMgr::PseudoBlockGmresSolMgr() : - outputStream_(Teuchos::rcp(outputStream_default_,false)), + outputStream_(Teuchos::rcpFromRef(std::cout)), taggedTests_(Teuchos::null), convtol_(DefaultSolverParameters::convTol), orthoKappa_(DefaultSolverParameters::orthoKappa), @@ -563,7 +556,7 @@ PseudoBlockGmresSolMgr:: PseudoBlockGmresSolMgr (const Teuchos::RCP > &problem, const Teuchos::RCP &pl) : problem_(problem), - outputStream_(Teuchos::rcp(outputStream_default_,false)), + outputStream_(Teuchos::rcpFromRef(std::cout)), taggedTests_(Teuchos::null), convtol_(DefaultSolverParameters::convTol), orthoKappa_(DefaultSolverParameters::orthoKappa), @@ -1053,7 +1046,7 @@ PseudoBlockGmresSolMgr::getValidParameters() const pl->set("Deflation Quorum", static_cast(defQuorum_default_), "The number of linear systems that need to converge before\n" "they are deflated. This number should be <= block size."); - pl->set("Output Stream", Teuchos::rcp(outputStream_default_,false), + pl->set("Output Stream", Teuchos::rcpFromRef(std::cout), "A reference-counted pointer to the output stream where all\n" "solver output is sent."); pl->set("Show Maximum Residual Norm Only", static_cast(showMaxResNormOnly_default_), diff --git a/packages/belos/src/BelosPseudoBlockStochasticCGSolMgr.hpp b/packages/belos/src/BelosPseudoBlockStochasticCGSolMgr.hpp index 24c685802ae9..ed61559040fa 100644 --- a/packages/belos/src/BelosPseudoBlockStochasticCGSolMgr.hpp +++ b/packages/belos/src/BelosPseudoBlockStochasticCGSolMgr.hpp @@ -255,13 +255,6 @@ namespace Belos { static constexpr int defQuorum_default_ = 1; static constexpr const char * resScale_default_ = "Norm of Initial Residual"; static constexpr const char * label_default_ = "Belos"; -// https://stackoverflow.com/questions/24398102/constexpr-and-initialization-of-a-static-const-void-pointer-with-reinterpret-cas -#if defined(_WIN32) && defined(__clang__) - static constexpr std::ostream * outputStream_default_ = - __builtin_constant_p(reinterpret_cast(&std::cout)); -#else - static constexpr std::ostream * outputStream_default_ = &std::cout; -#endif // Current solver values. MagnitudeType convtol_; @@ -286,7 +279,7 @@ namespace Belos { // Empty Constructor template PseudoBlockStochasticCGSolMgr::PseudoBlockStochasticCGSolMgr() : - outputStream_(Teuchos::rcp(outputStream_default_,false)), + outputStream_(Teuchos::rcpFromRef(std::cout)), convtol_(DefaultSolverParameters::convTol), maxIters_(maxIters_default_), numIters_(0), @@ -307,7 +300,7 @@ PseudoBlockStochasticCGSolMgr:: PseudoBlockStochasticCGSolMgr (const Teuchos::RCP > &problem, const Teuchos::RCP &pl ) : problem_(problem), - outputStream_(Teuchos::rcp(outputStream_default_,false)), + outputStream_(Teuchos::rcpFromRef(std::cout)), convtol_(DefaultSolverParameters::convTol), maxIters_(maxIters_default_), numIters_(0), @@ -591,7 +584,7 @@ PseudoBlockStochasticCGSolMgr::getValidParameters() const pl->set("Deflation Quorum", static_cast(defQuorum_default_), "The number of linear systems that need to converge before\n" "they are deflated. This number should be <= block size."); - pl->set("Output Stream", Teuchos::rcp(outputStream_default_,false), + pl->set("Output Stream", Teuchos::rcpFromRef(std::cout), "A reference-counted pointer to the output stream where all\n" "solver output is sent."); pl->set("Show Maximum Residual Norm Only", static_cast(showMaxResNormOnly_default_), diff --git a/packages/belos/src/BelosPseudoBlockTFQMRSolMgr.hpp b/packages/belos/src/BelosPseudoBlockTFQMRSolMgr.hpp index 69be86a4100e..6c2a3eaffa25 100644 --- a/packages/belos/src/BelosPseudoBlockTFQMRSolMgr.hpp +++ b/packages/belos/src/BelosPseudoBlockTFQMRSolMgr.hpp @@ -270,13 +270,6 @@ namespace Belos { static constexpr const char * impResScale_default_ = "Norm of Preconditioned Initial Residual"; static constexpr const char * expResScale_default_ = "Norm of Initial Residual"; static constexpr const char * label_default_ = "Belos"; -// https://stackoverflow.com/questions/24398102/constexpr-and-initialization-of-a-static-const-void-pointer-with-reinterpret-cas -#if defined(_WIN32) && defined(__clang__) - static constexpr std::ostream * outputStream_default_ = - __builtin_constant_p(reinterpret_cast(&std::cout)); -#else - static constexpr std::ostream * outputStream_default_ = &std::cout; -#endif // Current solver values. MagnitudeType convtol_, impTolScale_, achievedTol_; @@ -297,7 +290,7 @@ namespace Belos { // Empty Constructor template PseudoBlockTFQMRSolMgr::PseudoBlockTFQMRSolMgr() : - outputStream_(Teuchos::rcp(outputStream_default_,false)), + outputStream_(Teuchos::rcpFromRef(std::cout)), convtol_(DefaultSolverParameters::convTol), impTolScale_(DefaultSolverParameters::impTolScale), achievedTol_(Teuchos::ScalarTraits::magnitudeType>::zero()), @@ -322,7 +315,7 @@ PseudoBlockTFQMRSolMgr::PseudoBlockTFQMRSolMgr( const Teuchos::RCP > &problem, const Teuchos::RCP &pl ) : problem_(problem), - outputStream_(Teuchos::rcp(outputStream_default_,false)), + outputStream_(Teuchos::rcpFromRef(std::cout)), convtol_(DefaultSolverParameters::convTol), impTolScale_(DefaultSolverParameters::impTolScale), achievedTol_(Teuchos::ScalarTraits::magnitudeType>::zero()), @@ -620,7 +613,7 @@ PseudoBlockTFQMRSolMgr::getValidParameters() const "to the output stream."); pl->set("Deflation Quorum", static_cast(defQuorum_default_), "The number of linear systems that need to converge before they are deflated."); - pl->set("Output Stream", Teuchos::rcp(outputStream_default_,false), + pl->set("Output Stream", Teuchos::rcpFromRef(std::cout), "A reference-counted pointer to the output stream where all\n" "solver output is sent."); pl->set("Explicit Residual Test", static_cast(expResTest_default_), diff --git a/packages/belos/src/BelosRCGSolMgr.hpp b/packages/belos/src/BelosRCGSolMgr.hpp index 605139509ad1..9114b02298a9 100644 --- a/packages/belos/src/BelosRCGSolMgr.hpp +++ b/packages/belos/src/BelosRCGSolMgr.hpp @@ -372,13 +372,6 @@ namespace Belos { static constexpr int outputStyle_default_ = Belos::General; static constexpr int outputFreq_default_ = -1; static constexpr const char * label_default_ = "Belos"; -// https://stackoverflow.com/questions/24398102/constexpr-and-initialization-of-a-static-const-void-pointer-with-reinterpret-cas -#if defined(_WIN32) && defined(__clang__) - static constexpr std::ostream * outputStream_default_ = - __builtin_constant_p(reinterpret_cast(&std::cout)); -#else - static constexpr std::ostream * outputStream_default_ = &std::cout; -#endif // // Current solver values. @@ -506,7 +499,7 @@ RCGSolMgr::RCGSolMgr( template void RCGSolMgr::init() { - outputStream_ = Teuchos::rcp(outputStream_default_,false); + outputStream_ = Teuchos::rcpFromRef(std::cout); convtol_ = DefaultSolverParameters::convTol; maxIters_ = maxIters_default_; numBlocks_ = numBlocks_default_; @@ -764,7 +757,7 @@ RCGSolMgr::getValidParameters() const pl->set("Output Frequency", static_cast(outputFreq_default_), "How often convergence information should be outputted\n" "to the output stream."); - pl->set("Output Stream", Teuchos::rcp(outputStream_default_,false), + pl->set("Output Stream", Teuchos::rcpFromRef(std::cout), "A reference-counted pointer to the output stream where all\n" "solver output is sent."); pl->set("Show Maximum Residual Norm Only", static_cast(showMaxResNormOnly_default_), diff --git a/packages/belos/src/BelosTFQMRSolMgr.hpp b/packages/belos/src/BelosTFQMRSolMgr.hpp index 91e3d5ac485e..36b2000b3983 100644 --- a/packages/belos/src/BelosTFQMRSolMgr.hpp +++ b/packages/belos/src/BelosTFQMRSolMgr.hpp @@ -269,13 +269,6 @@ namespace Belos { static constexpr const char * impResScale_default_ = "Norm of Preconditioned Initial Residual"; static constexpr const char * expResScale_default_ = "Norm of Initial Residual"; static constexpr const char * label_default_ = "Belos"; -// https://stackoverflow.com/questions/24398102/constexpr-and-initialization-of-a-static-const-void-pointer-with-reinterpret-cas -#if defined(_WIN32) && defined(__clang__) - static constexpr std::ostream * outputStream_default_ = - __builtin_constant_p(reinterpret_cast(&std::cout)); -#else - static constexpr std::ostream * outputStream_default_ = &std::cout; -#endif // Current solver values. MagnitudeType convtol_, impTolScale_, achievedTol_; @@ -297,7 +290,7 @@ namespace Belos { // Empty Constructor template TFQMRSolMgr::TFQMRSolMgr() : - outputStream_(Teuchos::rcp(outputStream_default_,false)), + outputStream_(Teuchos::rcpFromRef(std::cout)), convtol_(DefaultSolverParameters::convTol), impTolScale_(DefaultSolverParameters::impTolScale), achievedTol_(Teuchos::ScalarTraits::magnitudeType>::zero()), @@ -322,7 +315,7 @@ TFQMRSolMgr::TFQMRSolMgr( const Teuchos::RCP > &problem, const Teuchos::RCP &pl ) : problem_(problem), - outputStream_(Teuchos::rcp(outputStream_default_,false)), + outputStream_(Teuchos::rcpFromRef(std::cout)), convtol_(DefaultSolverParameters::convTol), impTolScale_(DefaultSolverParameters::impTolScale), achievedTol_(Teuchos::ScalarTraits::magnitudeType>::zero()), @@ -622,7 +615,7 @@ TFQMRSolMgr::getValidParameters() const pl->set("Output Frequency", static_cast(outputFreq_default_), "How often convergence information should be outputted\n" "to the output stream."); - pl->set("Output Stream", Teuchos::rcp(outputStream_default_,false), + pl->set("Output Stream", Teuchos::rcpFromRef(std::cout), "A reference-counted pointer to the output stream where all\n" "solver output is sent."); pl->set("Explicit Residual Test", static_cast(expResTest_default_), From d084dc4aef2295fc5421c5e3f9968bc894b0b3e9 Mon Sep 17 00:00:00 2001 From: Paul Kuberry Date: Thu, 19 May 2022 12:02:53 -0600 Subject: [PATCH 17/21] Teuchos: use reinterpret_cast instead of invalid implicit cast for complex number --- packages/teuchos/numerics/src/Teuchos_LAPACK.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/teuchos/numerics/src/Teuchos_LAPACK.cpp b/packages/teuchos/numerics/src/Teuchos_LAPACK.cpp index 11173ecf123b..fcd36a90f8b0 100644 --- a/packages/teuchos/numerics/src/Teuchos_LAPACK.cpp +++ b/packages/teuchos/numerics/src/Teuchos_LAPACK.cpp @@ -1360,7 +1360,8 @@ namespace Teuchos #ifdef HAVE_TEUCHOS_LAPACKLARND std::complex LAPACK >::LARND( const int& idist, int* seed ) const { - return(CLARND_F77(&idist, seed)); + auto val = CLARND_F77(&idist, seed); + return(reinterpret_cast&>(val)); } #endif @@ -1782,7 +1783,8 @@ namespace Teuchos #ifdef HAVE_TEUCHOS_LAPACKLARND std::complex LAPACK >::LARND( const int& idist, int* seed ) const { - return(ZLARND_F77(&idist, seed)); + auto val = ZLARND_F77(&idist, seed); + return(reinterpret_cast&>(val)); } #endif From 75e66448befdbacb04a364404b4af927136a4217 Mon Sep 17 00:00:00 2001 From: Chris Siefert Date: Thu, 19 May 2022 12:31:48 -0600 Subject: [PATCH 18/21] TrilinosCouplings: Minor driver fixes --- .../examples/scaling/example_Poisson_stk.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/trilinoscouplings/examples/scaling/example_Poisson_stk.cpp b/packages/trilinoscouplings/examples/scaling/example_Poisson_stk.cpp index 20575a44a6fa..acece92c3676 100644 --- a/packages/trilinoscouplings/examples/scaling/example_Poisson_stk.cpp +++ b/packages/trilinoscouplings/examples/scaling/example_Poisson_stk.cpp @@ -557,8 +557,8 @@ int main(int argc, char *argv[]) { #if defined(HAVE_TRILINOSCOUPLINGS_MUELU) && defined(HAVE_MUELU_EPETRA) MachineLearningStatistics_Hex3D MLStatistics(numGlobalElements); - bool do_statistics = !strcmp(cellType.getName(),"Hexahedron_8"); - std::cout<<"do_statistics = "<::data_type* init_np = nullptr; // gcc 4.8 hack - stk::mesh::put_field_on_mesh( *m_coordinatesField, m_metaData->universal_part(), init_np); + stk::mesh::put_field_on_mesh( *m_coordinatesField, m_metaData->universal_part(), nullptr); } m_isOpen = true; m_filename = ""; @@ -1986,8 +1985,7 @@ { //std::cout << "createField scalar: " << name << std::endl; ScalarIntFieldType & sfield = m_metaData->declare_field(static_cast(entity_rank), name); - stk::mesh::FieldTraits::data_type* init_np = nullptr; // gcc 4.8 hack - stk::mesh::put_field_on_mesh( sfield , *part , init_np); + stk::mesh::put_field_on_mesh( sfield , *part , nullptr); field = &sfield; } break; @@ -1996,8 +1994,7 @@ { //std::cout << "createField vector: " << name << std::endl; VectorIntFieldType & vfield = m_metaData->declare_field(static_cast(entity_rank), name); - stk::mesh::FieldTraits::data_type* init_np = nullptr; // gcc 4.8 hack - stk::mesh::put_field_on_mesh( vfield , *part, dimensions[0] , init_np); + stk::mesh::put_field_on_mesh( vfield , *part, dimensions[0] , nullptr); field = &vfield; } break; @@ -2020,8 +2017,7 @@ { //std::cout << "createField scalar: " << name << std::endl; ScalarFieldType & sfield = m_metaData->declare_field(static_cast(entity_rank), name); - stk::mesh::FieldTraits::data_type* init_np = nullptr; // gcc 4.8 hack - stk::mesh::put_field_on_mesh( sfield , *part , init_np); + stk::mesh::put_field_on_mesh( sfield , *part , nullptr); field = &sfield; } break; @@ -2030,8 +2026,7 @@ { //std::cout << "createField vector: " << name << std::endl; CoordinatesFieldType & vfield = m_metaData->declare_field(static_cast(entity_rank), name); - stk::mesh::FieldTraits::data_type* init_np = nullptr; // gcc 4.8 hack - stk::mesh::put_field_on_mesh( vfield , *part, dimensions[0] , init_np); + stk::mesh::put_field_on_mesh( vfield , *part, dimensions[0] , nullptr); field = &vfield; } break; @@ -4339,8 +4334,7 @@ { typedef stk::mesh::Field GlobalIdField; GlobalIdField& cg_gid_field = m_metaData->declare_field(node_rank(), "cg_gid"); - stk::mesh::FieldTraits::data_type* init_np = nullptr; // gcc 4.8 hack - stk::mesh::put_field_on_mesh( cg_gid_field , m_metaData->universal_part(), init_np); + stk::mesh::put_field_on_mesh( cg_gid_field , m_metaData->universal_part(), nullptr); stk::io::set_field_role(cg_gid_field, Ioss::Field::TRANSIENT); } } @@ -6017,8 +6011,7 @@ if(!m_parent_element_field) { ParentElementType& pe_field = get_fem_meta_data()->declare_field(stk::topology::ELEMENT_RANK, "parent_element"); - stk::mesh::FieldTraits::data_type* init_np = nullptr; // gcc 4.8 hack - stk::mesh::put_field_on_mesh( pe_field , get_fem_meta_data()->universal_part(), init_np); + stk::mesh::put_field_on_mesh( pe_field , get_fem_meta_data()->universal_part(), nullptr); stk::io::set_field_role(pe_field, Ioss::Field::TRANSIENT); m_parent_element_field = &pe_field; } @@ -6026,8 +6019,7 @@ if(!m_parent_element_field_side) { ParentElementType& pe_field = get_fem_meta_data()->declare_field(side_rank(), "parent_element_side"); - stk::mesh::FieldTraits::data_type* init_np = nullptr; // gcc 4.8 hack - stk::mesh::put_field_on_mesh( pe_field , get_fem_meta_data()->universal_part(), init_np); + stk::mesh::put_field_on_mesh( pe_field , get_fem_meta_data()->universal_part(), nullptr); stk::io::set_field_role(pe_field, Ioss::Field::TRANSIENT); m_parent_element_field_side = &pe_field; } @@ -6062,8 +6054,7 @@ if (!m_weights_field) { m_weights_field = &get_fem_meta_data()->declare_field(stk::topology::ELEMENT_RANK, "rebalance_weights"); - stk::mesh::FieldTraits::data_type* init_np = nullptr; // gcc 4.8 hack - stk::mesh::put_field_on_mesh( *m_weights_field , get_fem_meta_data()->universal_part(), init_np); + stk::mesh::put_field_on_mesh( *m_weights_field , get_fem_meta_data()->universal_part(), nullptr); stk::io::set_field_role(*m_weights_field, Ioss::Field::TRANSIENT); } } @@ -6095,8 +6086,7 @@ m_unprojected_coordinates = &get_fem_meta_data()->declare_field(node_rank(), "unprojected_coordinates"); // we use first 3 slots for coordinates, last for the flag for if it has been set yet - stk::mesh::FieldTraits::data_type* init_np = nullptr; // gcc 4.8 hack - stk::mesh::put_field_on_mesh( *m_unprojected_coordinates, get_fem_meta_data()->universal_part(), 4, init_np); + stk::mesh::put_field_on_mesh( *m_unprojected_coordinates, get_fem_meta_data()->universal_part(), 4, nullptr); stk::io::set_field_role(*m_unprojected_coordinates, Ioss::Field::TRANSIENT); } ADD_FIELD(m_unprojected_coordinates); @@ -6106,8 +6096,7 @@ { m_wall_distance_field = &get_fem_meta_data()->declare_field(node_rank(), "wall_distance"); - stk::mesh::FieldTraits::data_type* init_np = nullptr; // gcc 4.8 hack - stk::mesh::put_field_on_mesh( *m_wall_distance_field, get_fem_meta_data()->universal_part(), init_np); + stk::mesh::put_field_on_mesh( *m_wall_distance_field, get_fem_meta_data()->universal_part(), nullptr); stk::io::set_field_role(*m_wall_distance_field, Ioss::Field::TRANSIENT); } ADD_FIELD(m_wall_distance_field); diff --git a/packages/percept/src/percept/eigen_verify/EigenVerify.cpp b/packages/percept/src/percept/eigen_verify/EigenVerify.cpp index 471c0acc3f93..b54aa433f744 100644 --- a/packages/percept/src/percept/eigen_verify/EigenVerify.cpp +++ b/packages/percept/src/percept/eigen_verify/EigenVerify.cpp @@ -73,22 +73,20 @@ void EigenVerify::create_fields(const int num_time_steps) // allocate data for the eigenvectors (sending) fieldAll[m] = & (mesh_data[m]->meta_data().declare_field >(stk::topology::NODE_RANK, field_name_all)); - stk::mesh::FieldTraits>::data_type* init_np = nullptr; // gcc 4.8 hack stk::mesh::put_field_on_mesh( *fieldAll[m], mesh_data[m]->meta_data().universal_part(), mesh_data[m]->meta_data().spatial_dimension(), num_time_steps, - init_np); + nullptr); // allocate data for the eigenvectors (receiving) xferFieldAll[m] = & (mesh_data[m]->meta_data().declare_field >(stk::topology::NODE_RANK, xfer_field_name_all)); - stk::mesh::FieldTraits>::data_type* init_np2 = nullptr; // gcc 4.8 hack stk::mesh::put_field_on_mesh( *xferFieldAll[m], mesh_data[m]->meta_data().universal_part(), mesh_data[m]->meta_data().spatial_dimension(), num_time_steps, - init_np2); + nullptr); // get eigenvector field inputField[m] = mesh_data[m]->meta_data().get_field >(stk::topology::NODE_RANK, field_name); @@ -103,8 +101,7 @@ void EigenVerify::create_fields(const int num_time_steps) // create fields to store nodal errors std::string error_field_name = "error." + field_name; errorField = & ( mesh_data[1]->meta_data().declare_field >(stk::topology::NODE_RANK, error_field_name) ); - stk::mesh::FieldTraits>::data_type* init_np = nullptr; // gcc 4.8 hack - stk::mesh::put_field_on_mesh( *errorField, mesh_data[1]->meta_data().universal_part() , init_np); + stk::mesh::put_field_on_mesh( *errorField, mesh_data[1]->meta_data().universal_part() , nullptr); } void EigenVerify::load_field_data(const int m) diff --git a/packages/percept/src/percept/fixtures/BeamFixture.cpp b/packages/percept/src/percept/fixtures/BeamFixture.cpp index c1acb74414c9..4910265168d3 100644 --- a/packages/percept/src/percept/fixtures/BeamFixture.cpp +++ b/packages/percept/src/percept/fixtures/BeamFixture.cpp @@ -26,7 +26,7 @@ #include #include - +#include //---------------------------------------------------------------------- namespace percept { @@ -35,8 +35,10 @@ BeamFixture::BeamFixture( stk::ParallelMachine comm, bool doCommit ) : m_spatial_dimension(3) - , m_metaData(m_spatial_dimension ) - , m_bulkData(m_metaData, comm ) + , m_bulkDataPtr(stk::mesh::MeshBuilder(comm).set_spatial_dimension(m_spatial_dimension) + .create()) + , m_bulkData(*m_bulkDataPtr) + , m_metaData(m_bulkData.mesh_meta_data()) , m_block_beam( m_metaData.declare_part_with_topology( "block_2", stk::topology::BEAM_2 ) ) , m_coordinates_field( m_metaData.declare_field< CoordinatesFieldType >( stk::topology::NODE_RANK, "coordinates" )) , m_centroid_field( m_metaData.declare_field< CoordinatesFieldType >( stk::topology::ELEMENT_RANK, "centroid" )) @@ -46,12 +48,10 @@ // Define where fields exist on the mesh: stk::mesh::Part & universal = m_metaData.universal_part(); - stk::mesh::FieldTraits::data_type* init_c = nullptr; // gcc 4.8 hack - stk::mesh::FieldTraits::data_type* init_s = nullptr; // gcc 4.8 hack - put_field_on_mesh( m_coordinates_field , universal, init_c); - put_field_on_mesh( m_centroid_field , universal, init_c); - put_field_on_mesh( m_temperature_field, universal, init_s); - put_field_on_mesh( m_volume_field, m_block_beam, init_s); + put_field_on_mesh( m_coordinates_field , universal, nullptr); + put_field_on_mesh( m_centroid_field , universal, nullptr); + put_field_on_mesh( m_temperature_field, universal, nullptr); + put_field_on_mesh( m_volume_field, m_block_beam, nullptr); if (doCommit) m_metaData.commit(); diff --git a/packages/percept/src/percept/fixtures/BeamFixture.hpp b/packages/percept/src/percept/fixtures/BeamFixture.hpp index 97ece636ed53..8b0dadc5f4b5 100644 --- a/packages/percept/src/percept/fixtures/BeamFixture.hpp +++ b/packages/percept/src/percept/fixtures/BeamFixture.hpp @@ -33,6 +33,7 @@ #include #include +#include /** stk_mesh Use Case 3 - copied and modified here */ @@ -59,8 +60,9 @@ void populate(); const int m_spatial_dimension; - stk::mesh::MetaData m_metaData; - stk::mesh::BulkData m_bulkData; + std::shared_ptr m_bulkDataPtr; + stk::mesh::BulkData& m_bulkData; + stk::mesh::MetaData& m_metaData; stk::mesh::Part & m_block_beam; diff --git a/packages/percept/src/percept/fixtures/HeterogeneousFixture.cpp b/packages/percept/src/percept/fixtures/HeterogeneousFixture.cpp index 207484af3d0a..b413788bac60 100644 --- a/packages/percept/src/percept/fixtures/HeterogeneousFixture.cpp +++ b/packages/percept/src/percept/fixtures/HeterogeneousFixture.cpp @@ -33,7 +33,7 @@ #include #include - +#include //---------------------------------------------------------------------- namespace percept { @@ -51,8 +51,11 @@ HeterogeneousFixture::HeterogeneousFixture( stk::ParallelMachine comm, bool doCommit, bool do_sidesets, bool do_one_sideset ) : m_spatial_dimension(3) - , m_metaData(m_spatial_dimension, entity_rank_names_and_family_tree()) - , m_bulkData(m_metaData, comm ) + , m_bulkDataPtr(stk::mesh::MeshBuilder(comm).set_spatial_dimension(m_spatial_dimension) + .set_entity_rank_names(entity_rank_names_and_family_tree()) + .create()) + , m_bulkData(*m_bulkDataPtr) + , m_metaData(m_bulkData.mesh_meta_data()) , m_block_hex( m_metaData.declare_part_with_topology( "block_1", stk::topology::HEX_8 )) , m_block_wedge( m_metaData.declare_part_with_topology( "block_2", stk::topology::WEDGE_6 )) , m_block_tet( m_metaData.declare_part_with_topology( "block_3", stk::topology::TET_4 )) @@ -72,16 +75,14 @@ { // Define where fields exist on the mesh: stk::mesh::Part & universal = m_metaData.universal_part(); - stk::mesh::FieldTraits::data_type* init_c = nullptr; // gcc 4.8 hack - stk::mesh::FieldTraits::data_type* init_s = nullptr; // gcc 4.8 hack - - put_field_on_mesh( m_coordinates_field , universal, init_c); - put_field_on_mesh( m_centroid_field , universal, init_c); - put_field_on_mesh( m_temperature_field, universal, init_s); - put_field_on_mesh( m_volume_field, m_block_hex, init_s); - put_field_on_mesh( m_volume_field, m_block_wedge, init_s); - put_field_on_mesh( m_volume_field, m_block_tet, init_s); - put_field_on_mesh( m_volume_field, m_block_pyramid, init_s); + + put_field_on_mesh( m_coordinates_field , universal, nullptr); + put_field_on_mesh( m_centroid_field , universal, nullptr); + put_field_on_mesh( m_temperature_field, universal, nullptr); + put_field_on_mesh( m_volume_field, m_block_hex, nullptr); + put_field_on_mesh( m_volume_field, m_block_wedge, nullptr); + put_field_on_mesh( m_volume_field, m_block_tet, nullptr); + put_field_on_mesh( m_volume_field, m_block_pyramid, nullptr); stk::io::put_io_part_attribute( m_block_hex ); stk::io::put_io_part_attribute( m_block_wedge ); diff --git a/packages/percept/src/percept/fixtures/HeterogeneousFixture.hpp b/packages/percept/src/percept/fixtures/HeterogeneousFixture.hpp index f4b4b75b8cbb..2fe9a02188fe 100644 --- a/packages/percept/src/percept/fixtures/HeterogeneousFixture.hpp +++ b/packages/percept/src/percept/fixtures/HeterogeneousFixture.hpp @@ -28,6 +28,7 @@ #include #include +#include /** stk_mesh Use Case 3 - copied and modified here */ @@ -53,8 +54,9 @@ void populate(); const int m_spatial_dimension; - stk::mesh::MetaData m_metaData; - stk::mesh::BulkData m_bulkData; + std::shared_ptr m_bulkDataPtr; + stk::mesh::BulkData& m_bulkData; + stk::mesh::MetaData& m_metaData; stk::mesh::Part & m_block_hex; stk::mesh::Part & m_block_wedge; diff --git a/packages/percept/src/percept/fixtures/PyramidFixture.cpp b/packages/percept/src/percept/fixtures/PyramidFixture.cpp index 884f452ce745..8500c1eef487 100644 --- a/packages/percept/src/percept/fixtures/PyramidFixture.cpp +++ b/packages/percept/src/percept/fixtures/PyramidFixture.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -51,8 +52,11 @@ PyramidFixture::PyramidFixture( stk::ParallelMachine comm, bool doCommit, bool do_sidesets ) : m_spatial_dimension(3) - , m_metaData(m_spatial_dimension, entity_rank_names_and_family_tree()) - , m_bulkData(m_metaData , comm ) + , m_bulkDataPtr(stk::mesh::MeshBuilder(comm).set_spatial_dimension(m_spatial_dimension) + .set_entity_rank_names(entity_rank_names_and_family_tree()) + .create()) + , m_bulkData(*m_bulkDataPtr) + , m_metaData(m_bulkData.mesh_meta_data()) , m_block_pyramid( m_metaData.declare_part_with_topology( "block_4", stk::topology::PYRAMID_5 )) , m_sideset_quad(0), m_sideset_quad_subset(0) , m_sideset_tri(0), m_sideset_tri_subset(0) @@ -80,14 +84,12 @@ stk::io::put_io_part_attribute(*m_sideset_tri); m_metaData.declare_part_subset(*m_sideset_tri, *m_sideset_tri_subset); } - stk::mesh::FieldTraits::data_type* init_c = nullptr; // gcc 4.8 hack - stk::mesh::FieldTraits::data_type* init_s = nullptr; // gcc 4.8 hack - put_field_on_mesh( m_coordinates_field , universal, init_c); - put_field_on_mesh( m_centroid_field , universal, init_c); - put_field_on_mesh( m_temperature_field, universal, init_s); + put_field_on_mesh( m_coordinates_field , universal, nullptr); + put_field_on_mesh( m_centroid_field , universal, nullptr); + put_field_on_mesh( m_temperature_field, universal, nullptr); - put_field_on_mesh( m_volume_field, m_block_pyramid, init_s); + put_field_on_mesh( m_volume_field, m_block_pyramid, nullptr); stk::io::put_io_part_attribute( m_block_pyramid ); diff --git a/packages/percept/src/percept/fixtures/PyramidFixture.hpp b/packages/percept/src/percept/fixtures/PyramidFixture.hpp index 73d78e54a313..11e7ab3b6597 100644 --- a/packages/percept/src/percept/fixtures/PyramidFixture.hpp +++ b/packages/percept/src/percept/fixtures/PyramidFixture.hpp @@ -30,6 +30,7 @@ #include #include +#include /** stk_mesh Use Case 3 - copied and modified here */ @@ -112,8 +113,9 @@ const int m_spatial_dimension; - stk::mesh::MetaData m_metaData; - stk::mesh::BulkData m_bulkData; + std::shared_ptr m_bulkDataPtr; + stk::mesh::BulkData& m_bulkData; + stk::mesh::MetaData& m_metaData; stk::mesh::Part & m_block_pyramid; stk::mesh::Part * m_sideset_quad; diff --git a/packages/percept/src/percept/fixtures/QuadFixture.hpp b/packages/percept/src/percept/fixtures/QuadFixture.hpp index 11583bb60e16..04592bb86ac8 100644 --- a/packages/percept/src/percept/fixtures/QuadFixture.hpp +++ b/packages/percept/src/percept/fixtures/QuadFixture.hpp @@ -22,9 +22,9 @@ #include #include #include -#include #include +#include #include #include #include @@ -82,8 +82,11 @@ QuadFixture( stk::ParallelMachine pm , unsigned nx , unsigned ny, bool generate_sidesets_in, bool debug_geom_side_sets_as_blocks_in=false ) - : meta_data(2, get_entity_rank_names(2) ), - bulk_data( meta_data, pm ), + : bulk_data_ptr(stk::mesh::MeshBuilder(pm).set_spatial_dimension(2) + .set_entity_rank_names(get_entity_rank_names(2)) + .create()), + bulk_data(*bulk_data_ptr), + meta_data(bulk_data_ptr->mesh_meta_data()), quad_part( meta_data.declare_part("block_1", stk::topology::ELEMENT_RANK ) ), coord_field( meta_data.declare_field(stk::topology::NODE_RANK, "coordinates") ), NX( nx ), @@ -100,12 +103,11 @@ stk::io::put_io_part_attribute(quad_part); //put coord-field on all nodes: - stk::mesh::FieldTraits::data_type* init_np = nullptr; // gcc 4.8 hack put_field_on_mesh( coord_field, meta_data.universal_part(), SpatialDim, - init_np + nullptr ); #if PERCEPT_QF_USE_COORD_GATHER_FIELD @@ -300,8 +302,9 @@ } - stk::mesh::MetaData meta_data ; - stk::mesh::BulkData bulk_data ; + std::shared_ptr bulk_data_ptr; + stk::mesh::BulkData& bulk_data ; + stk::mesh::MetaData& meta_data ; stk::mesh::Part & quad_part ; CoordinatesFieldType & coord_field ; const unsigned NX ; diff --git a/packages/percept/src/percept/fixtures/SingleTetFixture.cpp b/packages/percept/src/percept/fixtures/SingleTetFixture.cpp index b0626c66dc33..e9b916e7fb52 100644 --- a/packages/percept/src/percept/fixtures/SingleTetFixture.cpp +++ b/packages/percept/src/percept/fixtures/SingleTetFixture.cpp @@ -30,7 +30,7 @@ #include #include #include - +#include //---------------------------------------------------------------------- namespace percept { @@ -39,8 +39,10 @@ stk::mesh::EntityId elem_id_start ) : m_spatial_dimension(3) - , m_metaData(m_spatial_dimension) - , m_bulkData(m_metaData, comm ) + , m_bulkDataPtr(stk::mesh::MeshBuilder(comm).set_spatial_dimension(m_spatial_dimension) + .create()) + , m_bulkData(*m_bulkDataPtr) + , m_metaData(m_bulkData.mesh_meta_data()) , m_block_tet( m_metaData.declare_part_with_topology( "block_1", stk::topology::TET_4 )) , m_elem_rank( stk::topology::ELEMENT_RANK ) , m_coordinates_field( m_metaData.declare_field< CoordinatesFieldType >( stk::topology::NODE_RANK, "coordinates" )) @@ -50,9 +52,8 @@ { // Define where fields exist on the mesh: stk::mesh::Part & universal = m_metaData.universal_part(); - stk::mesh::FieldTraits::data_type* init_np = nullptr; // gcc 4.8 hack - put_field_on_mesh( m_coordinates_field , universal, init_np); + put_field_on_mesh( m_coordinates_field , universal, nullptr); if (doCommit) m_metaData.commit(); diff --git a/packages/percept/src/percept/fixtures/SingleTetFixture.hpp b/packages/percept/src/percept/fixtures/SingleTetFixture.hpp index 554e9ccf58ad..97c1fb6327e9 100644 --- a/packages/percept/src/percept/fixtures/SingleTetFixture.hpp +++ b/packages/percept/src/percept/fixtures/SingleTetFixture.hpp @@ -30,7 +30,7 @@ #include #include - +#include /** stk_mesh Use Case 3 - copied and modified here */ #define HET_FIX_INCLUDE_EXTRA_ELEM_TYPES 0 @@ -59,8 +59,9 @@ void populate(); int m_spatial_dimension; - stk::mesh::MetaData m_metaData; - stk::mesh::BulkData m_bulkData; + std::shared_ptr m_bulkDataPtr; + stk::mesh::BulkData& m_bulkData; + stk::mesh::MetaData& m_metaData; stk::mesh::Part & m_block_tet; diff --git a/packages/percept/src/percept/fixtures/TetWedgeFixture.cpp b/packages/percept/src/percept/fixtures/TetWedgeFixture.cpp index 7470a73be5ab..98579d5edbf0 100644 --- a/packages/percept/src/percept/fixtures/TetWedgeFixture.cpp +++ b/packages/percept/src/percept/fixtures/TetWedgeFixture.cpp @@ -26,7 +26,7 @@ #include #include - +#include //---------------------------------------------------------------------- namespace percept { @@ -39,8 +39,9 @@ TetWedgeFixture::TetWedgeFixture( stk::ParallelMachine comm, bool doCommit, bool do_sidesets ) : m_spatial_dimension(3) - , m_metaData(m_spatial_dimension, stk::mesh::entity_rank_names() ) - , m_bulkData(m_metaData, comm ) + , m_bulkDataPtr(stk::mesh::MeshBuilder(comm).set_spatial_dimension(m_spatial_dimension).create()) + , m_bulkData(*m_bulkDataPtr) + , m_metaData(m_bulkDataPtr->mesh_meta_data()) , m_block_wedge( m_metaData.declare_part_with_topology( "block_2", stk::topology::WEDGE_6 )) , m_block_tet( m_metaData.declare_part_with_topology( "block_3", stk::topology::TET_4 )) @@ -54,14 +55,12 @@ { // Define where fields exist on the mesh: stk::mesh::Part & universal = m_metaData.universal_part(); - stk::mesh::FieldTraits::data_type* init_c = nullptr; // gcc 4.8 hack - stk::mesh::FieldTraits::data_type* init_s = nullptr; // gcc 4.8 hack - - put_field_on_mesh( m_coordinates_field , universal, init_c); - put_field_on_mesh( m_centroid_field , universal, init_c); - put_field_on_mesh( m_temperature_field, universal, init_s); - put_field_on_mesh( m_volume_field, m_block_wedge, init_s); - put_field_on_mesh( m_volume_field, m_block_tet, init_s); + + put_field_on_mesh( m_coordinates_field , universal, nullptr); + put_field_on_mesh( m_centroid_field , universal, nullptr); + put_field_on_mesh( m_temperature_field, universal, nullptr); + put_field_on_mesh( m_volume_field, m_block_wedge, nullptr); + put_field_on_mesh( m_volume_field, m_block_tet, nullptr); stk::io::put_io_part_attribute( m_block_wedge ); stk::io::put_io_part_attribute( m_block_tet ); diff --git a/packages/percept/src/percept/fixtures/TetWedgeFixture.hpp b/packages/percept/src/percept/fixtures/TetWedgeFixture.hpp index f4e07767519a..257c3f5c349a 100644 --- a/packages/percept/src/percept/fixtures/TetWedgeFixture.hpp +++ b/packages/percept/src/percept/fixtures/TetWedgeFixture.hpp @@ -53,8 +53,9 @@ void populate(); const int m_spatial_dimension; - stk::mesh::MetaData m_metaData; - stk::mesh::BulkData m_bulkData; + std::shared_ptr m_bulkDataPtr; + stk::mesh::BulkData& m_bulkData; + stk::mesh::MetaData& m_metaData; stk::mesh::Part & m_block_wedge; stk::mesh::Part & m_block_tet; diff --git a/packages/percept/src/percept/fixtures/TriQuadSurfaceMesh3D.cpp b/packages/percept/src/percept/fixtures/TriQuadSurfaceMesh3D.cpp index f0582694fe11..2f4200cd5309 100644 --- a/packages/percept/src/percept/fixtures/TriQuadSurfaceMesh3D.cpp +++ b/packages/percept/src/percept/fixtures/TriQuadSurfaceMesh3D.cpp @@ -28,7 +28,7 @@ #include #include - +#include #include //---------------------------------------------------------------------- @@ -47,8 +47,11 @@ typedef stk::topology::topology_type Triangle3; TriQuadSurfaceMesh3D::TriQuadSurfaceMesh3D( stk::ParallelMachine comm, bool doCommit ) - : m_metaData(3, stk::mesh::entity_rank_names() ) - , m_bulkData(m_metaData, comm ) + : m_bulkDataPtr(stk::mesh::MeshBuilder(comm).set_spatial_dimension(3) + .set_entity_rank_names(stk::mesh::entity_rank_names()) + .create()) + , m_bulkData(*m_bulkDataPtr) + , m_metaData(m_bulkData.mesh_meta_data()) , m_sideset(0) , m_block_quad_shell( m_metaData.declare_part_with_topology( "block_1", stk::topology::SHELL_QUAD_4 )) @@ -62,16 +65,14 @@ { // Define where fields exist on the mesh: stk::mesh::Part & universal = m_metaData.universal_part(); - stk::mesh::FieldTraits::data_type* init_c = nullptr; // gcc 4.8 hack - // stk::mesh::FieldTraits::data_type* init_s = nullptr; // gcc 4.8 hack - - put_field_on_mesh( m_coordinates_field , universal , init_c); - // put_field_on_mesh( m_centroid_field , universal , init_c); - // put_field_on_mesh( m_temperature_field, universal , init_s); - // put_field_on_mesh( m_volume_field, m_block_hex , init_s); - // put_field_on_mesh( m_volume_field, m_block_wedge , init_s); - // put_field_on_mesh( m_volume_field, m_block_tet , init_s); - // put_field_on_mesh( m_volume_field, m_block_pyramid , init_s); + + put_field_on_mesh( m_coordinates_field , universal , nullptr); + // put_field_on_mesh( m_centroid_field , universal , nullptr); + // put_field_on_mesh( m_temperature_field, universal , nullptr); + // put_field_on_mesh( m_volume_field, m_block_hex , nullptr); + // put_field_on_mesh( m_volume_field, m_block_wedge , nullptr); + // put_field_on_mesh( m_volume_field, m_block_tet , nullptr); + // put_field_on_mesh( m_volume_field, m_block_pyramid , nullptr); stk::io::put_io_part_attribute( m_block_tri_shell); stk::io::put_io_part_attribute( m_block_quad_shell); diff --git a/packages/percept/src/percept/fixtures/TriQuadSurfaceMesh3D.hpp b/packages/percept/src/percept/fixtures/TriQuadSurfaceMesh3D.hpp index 960d4891258c..c78bd14063ab 100644 --- a/packages/percept/src/percept/fixtures/TriQuadSurfaceMesh3D.hpp +++ b/packages/percept/src/percept/fixtures/TriQuadSurfaceMesh3D.hpp @@ -30,6 +30,7 @@ #include #include +#include namespace percept { @@ -55,8 +56,9 @@ void populate(unsigned nNodes, unsigned nTriFaces, unsigned nQuadFaces, Point *coords, TriIds *triFaces, QuadIds *quadFaces, stk::mesh::EntityId *nodeIdMap = 0); - stk::mesh::MetaData m_metaData; - stk::mesh::BulkData m_bulkData; + std::shared_ptr m_bulkDataPtr; + stk::mesh::BulkData& m_bulkData; + stk::mesh::MetaData& m_metaData; stk::mesh::Part * m_sideset; stk::mesh::Part& m_block_quad_shell; diff --git a/packages/percept/src/percept/fixtures/WedgeFixture.hpp b/packages/percept/src/percept/fixtures/WedgeFixture.hpp index 722f742c2f07..5054817960be 100644 --- a/packages/percept/src/percept/fixtures/WedgeFixture.hpp +++ b/packages/percept/src/percept/fixtures/WedgeFixture.hpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include diff --git a/packages/percept/src/percept/mesh/gen/SweepMesher.cpp b/packages/percept/src/percept/mesh/gen/SweepMesher.cpp index 4726dc1eeac9..0b4c136a56e2 100644 --- a/packages/percept/src/percept/mesh/gen/SweepMesher.cpp +++ b/packages/percept/src/percept/mesh/gen/SweepMesher.cpp @@ -113,9 +113,8 @@ namespace percept // Field restrictions: stk::mesh::Part & universal = m_metaData->universal_part(); - stk::mesh::FieldTraits::data_type* init_np = nullptr; // gcc 4.8 hack - put_field_on_mesh( *m_coordinates_field , universal , init_np); + put_field_on_mesh( *m_coordinates_field , universal , nullptr); for (unsigned ieletype = 0; ieletype < NUM_ELEM_TYPES; ieletype++) diff --git a/packages/percept/src/percept/mesh/geometry/stk_geom/3D/FitGregoryPatches.cpp b/packages/percept/src/percept/mesh/geometry/stk_geom/3D/FitGregoryPatches.cpp index b3ec57c70eb1..1f4a0ea7dca7 100644 --- a/packages/percept/src/percept/mesh/geometry/stk_geom/3D/FitGregoryPatches.cpp +++ b/packages/percept/src/percept/mesh/geometry/stk_geom/3D/FitGregoryPatches.cpp @@ -120,8 +120,7 @@ namespace percept { // 3 slots for "left" of an edge, 3 for "right" if (is_surface_topology(part.topology())) { - stk::mesh::FieldTraits::data_type* init_np = nullptr; // gcc 4.8 hack - stk::mesh::put_field_on_mesh(*m_eMesh.m_node_normals, part, 3, init_np); + stk::mesh::put_field_on_mesh(*m_eMesh.m_node_normals, part, 3, nullptr); } if (!in_surface_sets(part.name())) @@ -129,14 +128,12 @@ namespace percept { if (pv[ii]->primary_entity_rank() == m_eMesh.side_rank()) { - stk::mesh::FieldTraits::data_type* init_np = nullptr; // gcc 4.8 hack - stk::mesh::put_field_on_mesh(*m_eMesh.m_gregory_control_points_field, part, numControlPoints, init_np); + stk::mesh::put_field_on_mesh(*m_eMesh.m_gregory_control_points_field, part, numControlPoints, nullptr); } else if (pv[ii]->primary_entity_rank() == m_eMesh.element_rank() && (pv[ii]->topology() == stk::topology::SHELL_QUAD_4 || pv[ii]->topology() == stk::topology::SHELL_TRI_3)) { - stk::mesh::FieldTraits::data_type* init_np = nullptr; // gcc 4.8 hack - stk::mesh::put_field_on_mesh(*m_eMesh.m_gregory_control_points_field_shell, part, numControlPoints, init_np); + stk::mesh::put_field_on_mesh(*m_eMesh.m_gregory_control_points_field_shell, part, numControlPoints, nullptr); } } } diff --git a/packages/percept/src/percept/uq/main/RFRealizeMain.cpp b/packages/percept/src/percept/uq/main/RFRealizeMain.cpp index 85e8d4ddf83e..c72e1645e538 100644 --- a/packages/percept/src/percept/uq/main/RFRealizeMain.cpp +++ b/packages/percept/src/percept/uq/main/RFRealizeMain.cpp @@ -98,8 +98,7 @@ int main(int argc, char **argv) stk::mesh::Field & alpha = mesh_data.meta_data().declare_field >(stk::topology::ELEMENT_RANK, "alpha"); - stk::mesh::FieldTraits>::data_type* init_np = nullptr; // gcc 4.8 hack - stk::mesh::put_field_on_mesh(alpha, mesh_data.meta_data().universal_part(), 1, init_np); + stk::mesh::put_field_on_mesh(alpha, mesh_data.meta_data().universal_part(), 1, nullptr); mesh_data.add_all_mesh_fields_as_input_fields(); stk::mesh::FieldBase& phi = *mesh_data.meta_data().get_field (stk::topology::ELEMENT_RANK, "phi"); diff --git a/packages/percept/src/percept/uq/main/RFSuiteMain.cpp b/packages/percept/src/percept/uq/main/RFSuiteMain.cpp index d0b78bcde2d9..0063ba28b554 100644 --- a/packages/percept/src/percept/uq/main/RFSuiteMain.cpp +++ b/packages/percept/src/percept/uq/main/RFSuiteMain.cpp @@ -148,8 +148,7 @@ int main(int argc, char **argv) stk::mesh::Field & phi = mesh_data.meta_data().declare_field >(stk::topology::ELEMENT_RANK, "phi"); - stk::mesh::FieldTraits>::data_type* init_np = nullptr; // gcc 4.8 hack - stk::mesh::put_field_on_mesh(phi, mesh_data.meta_data().universal_part(), maxNev, init_np); + stk::mesh::put_field_on_mesh(phi, mesh_data.meta_data().universal_part(), maxNev, nullptr); mesh_data.populate_bulk_data(); diff --git a/packages/stk/stk_balance/stk_balance/internal/privateDeclarations.cpp b/packages/stk/stk_balance/stk_balance/internal/privateDeclarations.cpp index 06b3ed4f5aa7..b3145b77e66c 100644 --- a/packages/stk/stk_balance/stk_balance/internal/privateDeclarations.cpp +++ b/packages/stk/stk_balance/stk_balance/internal/privateDeclarations.cpp @@ -659,19 +659,18 @@ void register_internal_fields(stk::mesh::BulkData & bulk, const stk::balance::Ba { if (balanceSettings.shouldFixSpiders()) { stk::mesh::MetaData& meta = bulk.mesh_meta_data(); - const int initValue = 0; stk::mesh::Field & beamField = meta.declare_field(stk::topology::NODE_RANK, balanceSettings.getSpiderBeamConnectivityCountFieldName()); - stk::mesh::put_field_on_mesh(beamField, meta.universal_part(), &initValue); + stk::mesh::put_field_on_mesh(beamField, meta.universal_part(), nullptr); stk::mesh::Field & volumeField = meta.declare_field(stk::topology::ELEM_RANK, balanceSettings.getSpiderVolumeConnectivityCountFieldName()); - stk::mesh::put_field_on_mesh(volumeField, meta.universal_part(), &initValue); + stk::mesh::put_field_on_mesh(volumeField, meta.universal_part(), nullptr); stk::mesh::Field & outputSubdomainField = meta.declare_field(stk::topology::ELEM_RANK, balanceSettings.getOutputSubdomainFieldName()); - stk::mesh::put_field_on_mesh(outputSubdomainField, meta.universal_part(), &initValue); + stk::mesh::put_field_on_mesh(outputSubdomainField, meta.universal_part(), nullptr); } } diff --git a/packages/stk/stk_doc_tests/stk_io/appendResults.cpp b/packages/stk/stk_doc_tests/stk_io/appendResults.cpp index db2b8c799875..f59520658d70 100644 --- a/packages/stk/stk_doc_tests/stk_io/appendResults.cpp +++ b/packages/stk/stk_doc_tests/stk_io/appendResults.cpp @@ -53,8 +53,7 @@ class StkIoHowToAppend : public stk::unit_test_util::simple_fields::MeshFixture { setup_empty_mesh(stk::mesh::BulkData::AUTO_AURA); nodeField = &get_meta().declare_field (stk::topology::NODE_RANK, "nodal"); - stk::mesh::put_field_on_mesh(*nodeField, get_meta().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(*nodeField, get_meta().universal_part(), nullptr); stk::io::fill_mesh("generated:8x8x8|sideset:xX|nodeset:xX", get_bulk()); } diff --git a/packages/stk/stk_doc_tests/stk_io/handleMissingFieldOnRead.cpp b/packages/stk/stk_doc_tests/stk_io/handleMissingFieldOnRead.cpp index 4fc00b57b16d..c57262db384e 100644 --- a/packages/stk/stk_doc_tests/stk_io/handleMissingFieldOnRead.cpp +++ b/packages/stk/stk_doc_tests/stk_io/handleMissingFieldOnRead.cpp @@ -75,8 +75,7 @@ namespace { stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); size_t fh = stkIo.create_output_mesh(ic_name, stk::io::WRITE_RESULTS); @@ -121,13 +120,11 @@ namespace { stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stk::mesh::Field &displacement = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "displacement", 3); - stk::mesh::put_field_on_mesh(displacement, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(displacement, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); // The name of the field on the database is "temp" diff --git a/packages/stk/stk_doc_tests/stk_io/handleMissingFieldOnReadThrow.cpp b/packages/stk/stk_doc_tests/stk_io/handleMissingFieldOnReadThrow.cpp index 5eaa06947e15..4215cd978b86 100644 --- a/packages/stk/stk_doc_tests/stk_io/handleMissingFieldOnReadThrow.cpp +++ b/packages/stk/stk_doc_tests/stk_io/handleMissingFieldOnReadThrow.cpp @@ -75,8 +75,7 @@ TEST(StkMeshIoBrokerHowTo, handleMissingFieldOnReadThrow) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); size_t fh = stkIo.create_output_mesh(ic_name, stk::io::WRITE_RESULTS); @@ -120,13 +119,11 @@ TEST(StkMeshIoBrokerHowTo, handleMissingFieldOnReadThrow) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stk::mesh::Field &displacement = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "displacement", 1); - stk::mesh::put_field_on_mesh(displacement, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(displacement, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); // The name of the field on the database is "temp" diff --git a/packages/stk/stk_doc_tests/stk_io/howToWriteRestartWithEdges.cpp b/packages/stk/stk_doc_tests/stk_io/howToWriteRestartWithEdges.cpp index 7e554fe47570..53afba8a0e08 100644 --- a/packages/stk/stk_doc_tests/stk_io/howToWriteRestartWithEdges.cpp +++ b/packages/stk/stk_doc_tests/stk_io/howToWriteRestartWithEdges.cpp @@ -29,8 +29,7 @@ TEST(StkIoHowTo, WriteRestartWithEdges) stk::mesh::Part* part = &meta.declare_part_with_topology("edgeBlock", stk::topology::LINE_2); stk::mesh::Field& edgeField = meta.declare_field(stk::topology::EDGE_RANK, "edgeField", numStates); - stk::mesh::put_field_on_mesh(edgeField, meta.universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(edgeField, meta.universal_part(), nullptr); stk::io::put_edge_block_io_part_attribute(*part); stk::io::fill_mesh("generated:1x1x1", *bulk); stk::mesh::create_edges(*bulk, meta.universal_part(), part); @@ -55,8 +54,7 @@ TEST(StkIoHowTo, WriteRestartWithEdges) meta.use_simple_fields(); stk::mesh::Field& edgeField = meta.declare_field(stk::topology::EDGE_RANK, "edgeField", numStates); - stk::mesh::put_field_on_mesh(edgeField, meta.universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(edgeField, meta.universal_part(), nullptr); stk::io::set_field_role(edgeField, Ioss::Field::TRANSIENT); diff --git a/packages/stk/stk_doc_tests/stk_io/howToWriteRestartWithFaces.cpp b/packages/stk/stk_doc_tests/stk_io/howToWriteRestartWithFaces.cpp index cac10b77d082..9ad000659e19 100644 --- a/packages/stk/stk_doc_tests/stk_io/howToWriteRestartWithFaces.cpp +++ b/packages/stk/stk_doc_tests/stk_io/howToWriteRestartWithFaces.cpp @@ -29,8 +29,7 @@ TEST(StkIoHowTo, WriteRestartWithFaceBlock) stk::mesh::Part* part = &meta.declare_part_with_topology("faceBlock", stk::topology::QUAD_4); stk::mesh::Field& faceField = meta.declare_field(stk::topology::FACE_RANK, "faceField", numStates); - stk::mesh::put_field_on_mesh(faceField, meta.universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(faceField, meta.universal_part(), nullptr); stk::io::put_face_block_io_part_attribute(*part); stk::io::fill_mesh("generated:1x1x1", *bulk); bool connectFacesToEdges = true; @@ -56,8 +55,7 @@ TEST(StkIoHowTo, WriteRestartWithFaceBlock) meta.use_simple_fields(); stk::mesh::Field& faceField = meta.declare_field(stk::topology::FACE_RANK, "faceField", numStates); - stk::mesh::put_field_on_mesh(faceField, meta.universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(faceField, meta.universal_part(), nullptr); stk::io::set_field_role(faceField, Ioss::Field::TRANSIENT); diff --git a/packages/stk/stk_doc_tests/stk_io/interpolateFieldCyclic.cpp b/packages/stk/stk_doc_tests/stk_io/interpolateFieldCyclic.cpp index dccbd78a592b..4d68ee8df6f7 100644 --- a/packages/stk/stk_doc_tests/stk_io/interpolateFieldCyclic.cpp +++ b/packages/stk/stk_doc_tests/stk_io/interpolateFieldCyclic.cpp @@ -76,8 +76,7 @@ TEST(StkMeshIoBrokerHowTo, interpolateFieldCyclic) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); size_t fh = stkIo.create_output_mesh(ic_name, stk::io::WRITE_RESULTS); @@ -135,8 +134,7 @@ TEST(StkMeshIoBrokerHowTo, interpolateFieldCyclic) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); diff --git a/packages/stk/stk_doc_tests/stk_io/interpolateFieldNegativeTime.cpp b/packages/stk/stk_doc_tests/stk_io/interpolateFieldNegativeTime.cpp index 074d228e9444..7d456b9b68de 100644 --- a/packages/stk/stk_doc_tests/stk_io/interpolateFieldNegativeTime.cpp +++ b/packages/stk/stk_doc_tests/stk_io/interpolateFieldNegativeTime.cpp @@ -76,8 +76,7 @@ TEST(StkMeshIoBrokerHowTo, interpolateFieldNegativeTime) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); size_t fh = stkIo.create_output_mesh(ic_name, stk::io::WRITE_RESULTS); @@ -122,8 +121,7 @@ TEST(StkMeshIoBrokerHowTo, interpolateFieldNegativeTime) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); diff --git a/packages/stk/stk_doc_tests/stk_io/interpolateFieldNonMonotonicTime.cpp b/packages/stk/stk_doc_tests/stk_io/interpolateFieldNonMonotonicTime.cpp index b3db1c8c6eb4..a371794376df 100644 --- a/packages/stk/stk_doc_tests/stk_io/interpolateFieldNonMonotonicTime.cpp +++ b/packages/stk/stk_doc_tests/stk_io/interpolateFieldNonMonotonicTime.cpp @@ -76,8 +76,7 @@ TEST(StkMeshIoBrokerHowTo, interpolateFieldNonMonotonicTime) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); size_t fh = stkIo.create_output_mesh(ic_name, stk::io::WRITE_RESULTS); @@ -122,8 +121,7 @@ TEST(StkMeshIoBrokerHowTo, interpolateFieldNonMonotonicTime) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); diff --git a/packages/stk/stk_doc_tests/stk_io/interpolateIntegerFieldInvalid.cpp b/packages/stk/stk_doc_tests/stk_io/interpolateIntegerFieldInvalid.cpp index 51df4a1d1d81..aaa3d8fabd51 100644 --- a/packages/stk/stk_doc_tests/stk_io/interpolateIntegerFieldInvalid.cpp +++ b/packages/stk/stk_doc_tests/stk_io/interpolateIntegerFieldInvalid.cpp @@ -72,8 +72,7 @@ TEST(StkMeshIoBrokerHowTo, interpolateIntegerFieldInvalid) stk::mesh::Field &integer_field = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "int_field", 1); - stk::mesh::put_field_on_mesh(integer_field, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(integer_field, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); EXPECT_ANY_THROW(stkIo.add_input_field(stk::io::MeshField(integer_field, "int_field", diff --git a/packages/stk/stk_doc_tests/stk_io/interpolateNodalField.cpp b/packages/stk/stk_doc_tests/stk_io/interpolateNodalField.cpp index 4c854b54b4d3..29c04d80875b 100644 --- a/packages/stk/stk_doc_tests/stk_io/interpolateNodalField.cpp +++ b/packages/stk/stk_doc_tests/stk_io/interpolateNodalField.cpp @@ -74,8 +74,7 @@ TEST(StkMeshIoBrokerHowTo, interpolateNodalField) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); size_t fh = stkIo.create_output_mesh(ic_name, stk::io::WRITE_RESULTS); @@ -120,8 +119,7 @@ TEST(StkMeshIoBrokerHowTo, interpolateNodalField) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); diff --git a/packages/stk/stk_doc_tests/stk_io/interpolateOutsideRange.cpp b/packages/stk/stk_doc_tests/stk_io/interpolateOutsideRange.cpp index f268590cf6b4..3f81eeefc3e1 100644 --- a/packages/stk/stk_doc_tests/stk_io/interpolateOutsideRange.cpp +++ b/packages/stk/stk_doc_tests/stk_io/interpolateOutsideRange.cpp @@ -74,8 +74,7 @@ TEST(StkMeshIoBrokerHowTo, interpolateOutsideRange) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK,"temperature",1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); size_t fh = stkIo.create_output_mesh(ic_name, stk::io::WRITE_RESULTS); @@ -128,8 +127,7 @@ TEST(StkMeshIoBrokerHowTo, interpolateOutsideRange) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); diff --git a/packages/stk/stk_doc_tests/stk_io/interpolateSingleStep.cpp b/packages/stk/stk_doc_tests/stk_io/interpolateSingleStep.cpp index fab170e676a4..4f12073abc8c 100644 --- a/packages/stk/stk_doc_tests/stk_io/interpolateSingleStep.cpp +++ b/packages/stk/stk_doc_tests/stk_io/interpolateSingleStep.cpp @@ -74,8 +74,7 @@ TEST(StkMeshIoBrokerHowTo, interpolateSingleStep) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); size_t fh = stkIo.create_output_mesh(ic_name, stk::io::WRITE_RESULTS); @@ -119,8 +118,7 @@ TEST(StkMeshIoBrokerHowTo, interpolateSingleStep) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK,"temperature",1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); // The name of the field on the database is "temp" stkIo.add_input_field(stk::io::MeshField(temperature, "temp", diff --git a/packages/stk/stk_doc_tests/stk_io/readInitialCondition.cpp b/packages/stk/stk_doc_tests/stk_io/readInitialCondition.cpp index 5bb83c326101..73a6f26e5195 100644 --- a/packages/stk/stk_doc_tests/stk_io/readInitialCondition.cpp +++ b/packages/stk/stk_doc_tests/stk_io/readInitialCondition.cpp @@ -76,8 +76,7 @@ TEST(StkMeshIoBrokerHowTo, readInitialCondition) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); size_t fh = stkIo.create_output_mesh(ic_name, stk::io::WRITE_RESULTS); @@ -119,8 +118,7 @@ TEST(StkMeshIoBrokerHowTo, readInitialCondition) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); //+ The name of the field on the database is "temp" diff --git a/packages/stk/stk_doc_tests/stk_io/readInitialConditionMultiSubset.cpp b/packages/stk/stk_doc_tests/stk_io/readInitialConditionMultiSubset.cpp index e01b3b8079de..a037d39a516e 100644 --- a/packages/stk/stk_doc_tests/stk_io/readInitialConditionMultiSubset.cpp +++ b/packages/stk/stk_doc_tests/stk_io/readInitialConditionMultiSubset.cpp @@ -92,8 +92,7 @@ TEST(StkMeshIoBrokerHowTo, readInitialConditionMultiSubset) const stk::mesh::PartVector &all_parts = meta_data.get_mesh_parts(); for (size_t i=0; i < all_parts.size(); i++) { //+ Put the field on all element block parts... - stk::mesh::put_field_on_mesh(pressure, *all_parts[i], - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(pressure, *all_parts[i], nullptr); } // This commits BulkData and populates the coordinates, connectivity, mesh... diff --git a/packages/stk/stk_doc_tests/stk_io/readInitialConditionNodalSubset.cpp b/packages/stk/stk_doc_tests/stk_io/readInitialConditionNodalSubset.cpp index f41923722fdc..7780be900d2c 100644 --- a/packages/stk/stk_doc_tests/stk_io/readInitialConditionNodalSubset.cpp +++ b/packages/stk/stk_doc_tests/stk_io/readInitialConditionNodalSubset.cpp @@ -104,8 +104,7 @@ TEST(StkMeshIoBrokerHowTo, readInitialConditionNodalSubset) const stk::mesh::Part *part = all_parts[i]; //+ It exists on all nodes in the mesh... - stk::mesh::put_field_on_mesh(temperature, *part, - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, *part, nullptr); stk::topology topo = part->topology(); if (topo == stk::topology::SHELL_QUAD_4) { diff --git a/packages/stk/stk_doc_tests/stk_io/readInitialConditionOnce.cpp b/packages/stk/stk_doc_tests/stk_io/readInitialConditionOnce.cpp index 4490fe4f9bd4..eef67bf0861b 100644 --- a/packages/stk/stk_doc_tests/stk_io/readInitialConditionOnce.cpp +++ b/packages/stk/stk_doc_tests/stk_io/readInitialConditionOnce.cpp @@ -76,8 +76,7 @@ TEST(StkMeshIoBrokerHowTo, readInitialConditionOnce) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); size_t fh = stkIo.create_output_mesh(ic_name, stk::io::WRITE_RESULTS); @@ -122,8 +121,7 @@ TEST(StkMeshIoBrokerHowTo, readInitialConditionOnce) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); //+ The name of the field on the database is "temp" diff --git a/packages/stk/stk_doc_tests/stk_io/readInitialConditionSpecifiedTime.cpp b/packages/stk/stk_doc_tests/stk_io/readInitialConditionSpecifiedTime.cpp index 8f813263ee2c..2049e3575503 100644 --- a/packages/stk/stk_doc_tests/stk_io/readInitialConditionSpecifiedTime.cpp +++ b/packages/stk/stk_doc_tests/stk_io/readInitialConditionSpecifiedTime.cpp @@ -76,13 +76,11 @@ TEST(StkMeshIoBrokerHowTo, readInitialConditionSpecifiedTime) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stk::mesh::Field &heat_flux = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "heat_flux", 1); - stk::mesh::put_field_on_mesh(heat_flux, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(heat_flux, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); size_t fh = stkIo.create_output_mesh(ic_name, stk::io::WRITE_RESULTS); @@ -135,13 +133,11 @@ TEST(StkMeshIoBrokerHowTo, readInitialConditionSpecifiedTime) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stk::mesh::Field &heat_flux = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "heat_flux", 1); - stk::mesh::put_field_on_mesh(heat_flux, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(heat_flux, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); // The name of the field on the database is "temp" diff --git a/packages/stk/stk_doc_tests/stk_io/readInitialConditionSubset.cpp b/packages/stk/stk_doc_tests/stk_io/readInitialConditionSubset.cpp index d42cdad979de..f89bf9d8047e 100644 --- a/packages/stk/stk_doc_tests/stk_io/readInitialConditionSubset.cpp +++ b/packages/stk/stk_doc_tests/stk_io/readInitialConditionSubset.cpp @@ -95,8 +95,7 @@ TEST(StkMeshIoBrokerHowTo, readInitialConditionSubset) const stk::mesh::Part *part = all_parts[i]; //+ Put the field on all element block parts... - stk::mesh::put_field_on_mesh(pressure, *part, - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(pressure, *part, nullptr); stk::topology topo = part->topology(); if (topo == stk::topology::SHELL_QUAD_4) { diff --git a/packages/stk/stk_doc_tests/stk_io/readInitialConditionTwoFieldSubset.cpp b/packages/stk/stk_doc_tests/stk_io/readInitialConditionTwoFieldSubset.cpp index fc730d4fca87..255adab8a6ae 100644 --- a/packages/stk/stk_doc_tests/stk_io/readInitialConditionTwoFieldSubset.cpp +++ b/packages/stk/stk_doc_tests/stk_io/readInitialConditionTwoFieldSubset.cpp @@ -96,8 +96,7 @@ TEST(StkMeshIoBrokerHowTo, readInitialConditionTwoFieldSubset) const stk::mesh::Part *part = all_parts[i]; //+ Put the field on all element block parts... - stk::mesh::put_field_on_mesh(pressure, *part, - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(pressure, *part, nullptr); stk::topology topo = part->topology(); if (topo == stk::topology::SHELL_QUAD_4) { diff --git a/packages/stk/stk_doc_tests/stk_io/replaceBulkData.cpp b/packages/stk/stk_doc_tests/stk_io/replaceBulkData.cpp index 9ac13d013d01..a99483dfeb23 100644 --- a/packages/stk/stk_doc_tests/stk_io/replaceBulkData.cpp +++ b/packages/stk/stk_doc_tests/stk_io/replaceBulkData.cpp @@ -98,8 +98,7 @@ TEST(StkMeshIoBrokerHowTo, replaceBulkData) //+ since it commits the meta data. const std::string fieldName = "disp"; stk::mesh::Field &field = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, fieldName, 1); - stk::mesh::put_field_on_mesh(field, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(field, stkIo.meta_data().universal_part(), nullptr); //+ commit the meta data and create the bulk data. //+ populate the bulk data with data from the mesh file. diff --git a/packages/stk/stk_doc_tests/stk_io/requestedResultsFieldName.cpp b/packages/stk/stk_doc_tests/stk_io/requestedResultsFieldName.cpp index dbf2be0997bf..8ef782f081ff 100644 --- a/packages/stk/stk_doc_tests/stk_io/requestedResultsFieldName.cpp +++ b/packages/stk/stk_doc_tests/stk_io/requestedResultsFieldName.cpp @@ -89,8 +89,7 @@ TEST(StkMeshIoBrokerHowTo, writeResults) //+ since it commits the meta data. const std::string fieldName = "disp"; stk::mesh::Field &field = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, fieldName, 1); - stk::mesh::put_field_on_mesh(field, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(field, stkIo.meta_data().universal_part(), nullptr); //+ commit the meta data and create the bulk data. //+ populate the bulk data with data from the mesh file. diff --git a/packages/stk/stk_doc_tests/stk_io/restartInterpolatedField.cpp b/packages/stk/stk_doc_tests/stk_io/restartInterpolatedField.cpp index 342e1eb0bcc2..be1672938399 100644 --- a/packages/stk/stk_doc_tests/stk_io/restartInterpolatedField.cpp +++ b/packages/stk/stk_doc_tests/stk_io/restartInterpolatedField.cpp @@ -111,8 +111,7 @@ TEST(StkMeshIoBrokerHowTo, restartInterpolatedField) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); size_t fh = stkIo.create_output_mesh(ic_name, stk::io::WRITE_RESULTS); @@ -170,8 +169,7 @@ TEST(StkMeshIoBrokerHowTo, restartInterpolatedField) stk::mesh::Field &temperature = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "temperature", 1); - stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, stkIo.meta_data().universal_part(), nullptr); // The name of the field on the initial condition database is "temp" stkIo.add_input_field(ic, stk::io::MeshField(temperature, "temp", diff --git a/packages/stk/stk_doc_tests/stk_io/restartTestUtils.hpp b/packages/stk/stk_doc_tests/stk_io/restartTestUtils.hpp index 94a3a1843a1d..bbda3dc62c51 100644 --- a/packages/stk/stk_doc_tests/stk_io/restartTestUtils.hpp +++ b/packages/stk/stk_doc_tests/stk_io/restartTestUtils.hpp @@ -74,8 +74,7 @@ inline stk::mesh::Field & declareNodalField(stk::mesh::MetaData &stkMesh int numberOfStates) { stk::mesh::Field &multiStateField = stkMeshMetaData.declare_field(stk::topology::NODE_RANK, fieldName, numberOfStates); - stk::mesh::put_field_on_mesh(multiStateField, stkMeshMetaData.universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(multiStateField, stkMeshMetaData.universal_part(), nullptr); return multiStateField; } diff --git a/packages/stk/stk_doc_tests/stk_io/singleStepOnRestart.cpp b/packages/stk/stk_doc_tests/stk_io/singleStepOnRestart.cpp index 75b3f801f819..b55678f2b4df 100644 --- a/packages/stk/stk_doc_tests/stk_io/singleStepOnRestart.cpp +++ b/packages/stk/stk_doc_tests/stk_io/singleStepOnRestart.cpp @@ -64,8 +64,7 @@ TEST(StkMeshIoBrokerHowTo, singleStepOnRestart) stkIo.create_input_mesh(); stk::mesh::Field &field = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "disp", 3); - stk::mesh::put_field_on_mesh(field, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(field, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); diff --git a/packages/stk/stk_doc_tests/stk_io/useNodesetDbVarForNodalField.cpp b/packages/stk/stk_doc_tests/stk_io/useNodesetDbVarForNodalField.cpp index 93d5d8339ee3..24c32f20323f 100644 --- a/packages/stk/stk_doc_tests/stk_io/useNodesetDbVarForNodalField.cpp +++ b/packages/stk/stk_doc_tests/stk_io/useNodesetDbVarForNodalField.cpp @@ -98,8 +98,7 @@ TEST(StkMeshIoBrokerHowTo, useNodesetDbVarForNodalFields) const stk::mesh::Part *part = all_parts[i]; stk::topology topo = part->topology(); if (topo == stk::topology::SHELL_QUAD_4) { - stk::mesh::put_field_on_mesh(temperature, *part, - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(temperature, *part, nullptr); } } diff --git a/packages/stk/stk_doc_tests/stk_io/usingResults.cpp b/packages/stk/stk_doc_tests/stk_io/usingResults.cpp index 6283ee65ddf0..7a2043bf786f 100644 --- a/packages/stk/stk_doc_tests/stk_io/usingResults.cpp +++ b/packages/stk/stk_doc_tests/stk_io/usingResults.cpp @@ -87,8 +87,7 @@ TEST(StkMeshIoBrokerHowTo, writeResultsWithMultistateField) //+ since it commits the meta data. stk::mesh::Field &field = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, fieldName, 3); - stk::mesh::put_field_on_mesh(field, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(field, stkIo.meta_data().universal_part(), nullptr); stkIo.populate_bulk_data(); diff --git a/packages/stk/stk_doc_tests/stk_io/writeResults.cpp b/packages/stk/stk_doc_tests/stk_io/writeResults.cpp index 2f8c798e4fb0..6806bddf11de 100644 --- a/packages/stk/stk_doc_tests/stk_io/writeResults.cpp +++ b/packages/stk/stk_doc_tests/stk_io/writeResults.cpp @@ -97,8 +97,7 @@ TEST(StkMeshIoBrokerHowTo, writeResults) //+ since it commits the meta data. const std::string fieldName = "disp"; stk::mesh::Field &field = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, fieldName, 1); - stk::mesh::put_field_on_mesh(field, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(field, stkIo.meta_data().universal_part(), nullptr); //+ commit the meta data and create the bulk data. //+ populate the bulk data with data from the mesh file. @@ -212,8 +211,7 @@ TEST(StkMeshIoBrokerHowTo, DISABLED_brokenWriteResults) const std::string fieldName = "disp"; stk::mesh::Field &field = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, fieldName, 1); - stk::mesh::put_field_on_mesh(field, stkIo.meta_data().universal_part(), 3, 2, - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(field, stkIo.meta_data().universal_part(), 3, 2, nullptr); stk::io::set_field_output_type(field, "Vector_3D"); //+ commit the meta data and create the bulk data. diff --git a/packages/stk/stk_doc_tests/stk_io/writeResultsAndRestart.cpp b/packages/stk/stk_doc_tests/stk_io/writeResultsAndRestart.cpp index 732572e46bed..377cc2dc4232 100644 --- a/packages/stk/stk_doc_tests/stk_io/writeResultsAndRestart.cpp +++ b/packages/stk/stk_doc_tests/stk_io/writeResultsAndRestart.cpp @@ -98,14 +98,12 @@ TEST(StkMeshIoBrokerHowTo, writeResultsAndRestart) //+ since it commits the meta data. const std::string fieldName = "disp"; stk::mesh::Field &field = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, fieldName, 3); - stk::mesh::put_field_on_mesh(field, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(field, stkIo.meta_data().universal_part(), nullptr); const stk::mesh::Part& block_1 = *stkIo.meta_data().get_part("block_1"); //+ create a two-state field stk::mesh::Field &fooSubset = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "fooSubset", 2); - stk::mesh::put_field_on_mesh(fooSubset, block_1, - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(fooSubset, block_1, nullptr); //+ commit the meta data and create the bulk data. //+ populate the bulk data with data from the mesh file. @@ -182,15 +180,13 @@ TEST(StkMeshIoBrokerHowTo, writeResultsAndRestart) //create a 3-state field stk::mesh::Field &foo = stkIo.meta_data().declare_field(stk::topology::NODE_RANK, "foo", 3); - stk::mesh::put_field_on_mesh(foo, stkIo.meta_data().universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(foo, stkIo.meta_data().universal_part(), nullptr); const stk::mesh::Part& block_1 = *stkIo.meta_data().get_part("block_1"); //create a 3-state field stk::mesh::Field &fooSubset = stkIo.meta_data(). declare_field(stk::topology::NODE_RANK, "fooSubset", 3); - stk::mesh::put_field_on_mesh(fooSubset, block_1, - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(fooSubset, block_1, nullptr); //add the new fields to the stk-io-broker, even though we know it isn't present //in the restart database. This is to test the 'missing-fields' argument below. diff --git a/packages/stk/stk_doc_tests/stk_mesh/useSimpleFields.cpp b/packages/stk/stk_doc_tests/stk_mesh/useSimpleFields.cpp index 686cfbcfb671..435b950101d5 100644 --- a/packages/stk/stk_doc_tests/stk_mesh/useSimpleFields.cpp +++ b/packages/stk/stk_doc_tests/stk_mesh/useSimpleFields.cpp @@ -148,8 +148,8 @@ TEST(stkMeshHowTo, declareVectorFields_omitOutputType_noSubscriptNaming) DoubleField& displacements = metaData.declare_field(stk::topology::NODE_RANK, "displacements"); unsigned fieldLength = 3; - stk::mesh::put_field_on_mesh(velocities, metaData.universal_part(), fieldLength, static_cast(nullptr)); - stk::mesh::put_field_on_mesh(displacements, metaData.universal_part(), fieldLength, static_cast(nullptr)); + stk::mesh::put_field_on_mesh(velocities, metaData.universal_part(), fieldLength, nullptr); + stk::mesh::put_field_on_mesh(displacements, metaData.universal_part(), fieldLength, nullptr); stk::io::set_field_output_type(velocities, "Vector_3D"); diff --git a/packages/stk/stk_integration_tests/stk_balance/IntegrationTestLoadBalanceMultipleCriteria.cpp b/packages/stk/stk_integration_tests/stk_balance/IntegrationTestLoadBalanceMultipleCriteria.cpp index 7def719495a6..1a5edda671ec 100644 --- a/packages/stk/stk_integration_tests/stk_balance/IntegrationTestLoadBalanceMultipleCriteria.cpp +++ b/packages/stk/stk_integration_tests/stk_balance/IntegrationTestLoadBalanceMultipleCriteria.cpp @@ -61,9 +61,9 @@ class MultipleCriteria : public stk::unit_test_util::simple_fields::MeshFixture stk::mesh::Field &criteria2 = get_meta().declare_field(stk::topology::ELEM_RANK, "criteria2"); stk::mesh::Field &procId = get_meta().declare_field(stk::topology::ELEM_RANK, "proc_id"); - stk::mesh::put_field_on_mesh(criteria1, get_meta().universal_part(), static_cast(nullptr)); - stk::mesh::put_field_on_mesh(criteria2, get_meta().universal_part(), static_cast(nullptr)); - stk::mesh::put_field_on_mesh(procId, get_meta().universal_part(), static_cast(nullptr)); + stk::mesh::put_field_on_mesh(criteria1, get_meta().universal_part(), nullptr); + stk::mesh::put_field_on_mesh(criteria2, get_meta().universal_part(), nullptr); + stk::mesh::put_field_on_mesh(procId, get_meta().universal_part(), nullptr); stk::io::fill_mesh("generated:4x4x4", get_bulk()); diff --git a/packages/stk/stk_integration_tests/stk_balance/IntegrationTestLoadBalanceParentChild.cpp b/packages/stk/stk_integration_tests/stk_balance/IntegrationTestLoadBalanceParentChild.cpp index cbbf06f939b9..a5478dd56645 100644 --- a/packages/stk/stk_integration_tests/stk_balance/IntegrationTestLoadBalanceParentChild.cpp +++ b/packages/stk/stk_integration_tests/stk_balance/IntegrationTestLoadBalanceParentChild.cpp @@ -398,10 +398,10 @@ class RebalanceParentChildMesh : public ::testing::Test void register_fields() { m_elementWeightField = & get_meta().declare_field(stk::topology::ELEM_RANK, "Element Weights", 1); - stk::mesh::put_field_on_mesh(*m_elementWeightField, get_meta().universal_part(), static_cast(nullptr)); + stk::mesh::put_field_on_mesh(*m_elementWeightField, get_meta().universal_part(), nullptr); stk::mesh::FieldBase & coordinateField = get_meta().declare_field(stk::topology::NODE_RANK, "model_coordinates", 2); - stk::mesh::put_field_on_mesh(coordinateField, get_meta().universal_part(), static_cast(nullptr)); + stk::mesh::put_field_on_mesh(coordinateField, get_meta().universal_part(), nullptr); } void allocate_bulk(stk::mesh::BulkData::AutomaticAuraOption auraOption) diff --git a/packages/stk/stk_io/stk_io/IossBridge.cpp b/packages/stk/stk_io/stk_io/IossBridge.cpp index a22e408252ad..eda99307a09a 100644 --- a/packages/stk/stk_io/stk_io/IossBridge.cpp +++ b/packages/stk/stk_io/stk_io/IossBridge.cpp @@ -493,7 +493,7 @@ stk::mesh::FieldBase* add_stk_field(stk::mesh::MetaData& meta, { using StkField = stk::mesh::Field; StkField& field = meta.declare_field(entityRank, fieldName); - stk::mesh::put_field_on_mesh(field, part, numComponents, (typename stk::mesh::FieldTraits::data_type*)nullptr); + stk::mesh::put_field_on_mesh(field, part, numComponents, nullptr); return &field; } @@ -552,21 +552,18 @@ const stk::mesh::FieldBase *declare_stk_field_internal(stk::mesh::MetaData &meta if (field_type == "scalar" || num_components == 1) { if (!use_cartesian_for_scalar) { stk::mesh::Field & field = meta.declare_field>(entity_rank, name); - stk::mesh::put_field_on_mesh(field, part, - (stk::mesh::FieldTraits>::data_type*) nullptr); + stk::mesh::put_field_on_mesh(field, part, nullptr); field_ptr = &field; } else { stk::mesh::Field & field = meta.declare_field>(entity_rank, name); - stk::mesh::put_field_on_mesh(field, part, 1, - (stk::mesh::FieldTraits>::data_type*) nullptr); + stk::mesh::put_field_on_mesh(field, part, 1, nullptr); field_ptr = &field; } } else if (stk::string_starts_with(sierra::make_lower(field_type), "real[")) { stk::mesh::Field & field = meta.declare_field>(entity_rank, name); - stk::mesh::put_field_on_mesh(field, part, num_components, - (stk::mesh::FieldTraits>::data_type*) nullptr); + stk::mesh::put_field_on_mesh(field, part, num_components, nullptr); field_ptr = &field; } else if ((field_type == "vector_2d") || (field_type == "vector_3d")) { diff --git a/packages/stk/stk_io/stk_io/ProcessSetsOrBlocks.cpp b/packages/stk/stk_io/stk_io/ProcessSetsOrBlocks.cpp index 4f14c2872384..de3146def953 100644 --- a/packages/stk/stk_io/stk_io/ProcessSetsOrBlocks.cpp +++ b/packages/stk/stk_io/stk_io/ProcessSetsOrBlocks.cpp @@ -58,15 +58,13 @@ void process_nodeblocks(Ioss::Region ®ion, stk::mesh::MetaData &meta) stk::mesh::FieldBase * coord_field = nullptr; if (meta.is_using_simple_fields()) { coord_field = &meta.declare_field(stk::topology::NODE_RANK, meta.coordinate_field_name()); - stk::mesh::put_field_on_mesh(*coord_field, meta.universal_part(), meta.spatial_dimension(), - (stk::mesh::FieldTraits>::data_type*)nullptr); + stk::mesh::put_field_on_mesh(*coord_field, meta.universal_part(), meta.spatial_dimension(), nullptr); stk::io::set_field_output_type(*coord_field, "Vector_3D"); } else { coord_field = &meta.declare_field>(stk::topology::NODE_RANK, meta.coordinate_field_name()); - stk::mesh::put_field_on_mesh(*coord_field, meta.universal_part(), meta.spatial_dimension(), - (stk::mesh::FieldTraits>::data_type*)nullptr); + stk::mesh::put_field_on_mesh(*coord_field, meta.universal_part(), meta.spatial_dimension(), nullptr); } stk::io::set_field_role(*coord_field, Ioss::Field::MESH); @@ -113,8 +111,7 @@ void process_nodesets(Ioss::Region ®ion, stk::mesh::MetaData &meta) meta.declare_field(stk::topology::NODE_RANK, nodesetDistFieldName); stk::io::set_field_role(distribution_factors_field_per_nodeset, Ioss::Field::MESH); - stk::mesh::put_field_on_mesh(distribution_factors_field_per_nodeset, *part, - (stk::mesh::FieldTraits>::data_type*) nullptr); + stk::mesh::put_field_on_mesh(distribution_factors_field_per_nodeset, *part, nullptr); } } } @@ -158,12 +155,10 @@ void process_surface_entity(Ioss::SideSet *sset, stk::mesh::MetaData &meta) stk::io::set_distribution_factor_field(*sb_part, *distribution_factors_field); int side_node_count = sb->topology()->number_nodes(); if (meta.is_using_simple_fields()) { - stk::mesh::put_field_on_mesh(*distribution_factors_field, *sb_part, side_node_count, - (stk::mesh::FieldTraits>::data_type*)nullptr); + stk::mesh::put_field_on_mesh(*distribution_factors_field, *sb_part, side_node_count, nullptr); } else { - stk::mesh::put_field_on_mesh(*distribution_factors_field, *sb_part, side_node_count, - (stk::mesh::FieldTraits>::data_type*)nullptr); + stk::mesh::put_field_on_mesh(*distribution_factors_field, *sb_part, side_node_count, nullptr); } } } diff --git a/packages/stk/stk_mesh/stk_mesh/base/DeviceField.hpp b/packages/stk/stk_mesh/stk_mesh/base/DeviceField.hpp index 8fe4f741f95d..07368d21f3ba 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/DeviceField.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/DeviceField.hpp @@ -474,7 +474,12 @@ class DeviceField : public NgpFieldBase newDeviceSelectedBucketOffset = UnsignedViewType(Kokkos::view_alloc(Kokkos::WithoutInitializing, hostField->name() + "_bucket_offset"), allBuckets.size()); +#ifndef NEW_TRILINOS_INTEGRATION newHostSelectedBucketOffset = Kokkos::create_mirror_view(Kokkos::HostSpace(), newDeviceSelectedBucketOffset, Kokkos::WithoutInitializing); +#else + newHostSelectedBucketOffset = + Kokkos::create_mirror_view(Kokkos::WithoutInitializing, Kokkos::HostSpace(), newDeviceSelectedBucketOffset); +#endif for(unsigned i = 0; i < allBuckets.size(); i++) { if(selector(*allBuckets[i])) { diff --git a/packages/stk/stk_mesh/stk_mesh/base/DeviceMesh.cpp b/packages/stk/stk_mesh/stk_mesh/base/DeviceMesh.cpp index 6481f55e257c..30bd8e5479ce 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/DeviceMesh.cpp +++ b/packages/stk/stk_mesh/stk_mesh/base/DeviceMesh.cpp @@ -48,7 +48,11 @@ void DeviceBucket::initialize_bucket_attributes(const stk::mesh::Bucket &bucket) void DeviceBucket::allocate(const stk::mesh::Bucket &bucket) { nodeOffsets = OrdinalViewType(Kokkos::view_alloc(Kokkos::WithoutInitializing, "NodeOffsets"), bucket.size()+1); +#ifndef NEW_TRILINOS_INTEGRATION hostNodeOffsets = Kokkos::create_mirror_view(Kokkos::HostSpace(), nodeOffsets, Kokkos::WithoutInitializing); +#else + hostNodeOffsets = Kokkos::create_mirror_view(Kokkos::WithoutInitializing, Kokkos::HostSpace(), nodeOffsets); +#endif unsigned maxNodesPerEntity = bucketTopology.num_nodes(); unsigned totalNumNodes = bucketTopology.num_nodes()*bucketCapacity; @@ -64,17 +68,33 @@ void DeviceBucket::allocate(const stk::mesh::Bucket &bucket) const stk::mesh::PartVector& parts = bucket.supersets(); entities = EntityViewType(Kokkos::view_alloc(Kokkos::WithoutInitializing, "BucketEntities"), bucketCapacity); +#ifndef NEW_TRILINOS_INTEGRATION hostEntities = Kokkos::create_mirror_view(Kokkos::HostSpace(), entities, Kokkos::WithoutInitializing); +#else + hostEntities = Kokkos::create_mirror_view(Kokkos::WithoutInitializing, Kokkos::HostSpace(), entities); +#endif nodeConnectivity = BucketConnectivityType(Kokkos::view_alloc(Kokkos::WithoutInitializing, "BucketConnectivity"), totalNumNodes); +#ifndef NEW_TRILINOS_INTEGRATION hostNodeConnectivity = Kokkos::create_mirror_view(Kokkos::HostSpace(), nodeConnectivity, Kokkos::WithoutInitializing); +#else + hostNodeConnectivity = Kokkos::create_mirror_view(Kokkos::WithoutInitializing, Kokkos::HostSpace(), nodeConnectivity); +#endif nodeOrdinals = OrdinalViewType(Kokkos::view_alloc(Kokkos::WithoutInitializing, "NodeOrdinals"), static_cast(maxNodesPerEntity)); +#ifndef NEW_TRILINOS_INTEGRATION hostNodeOrdinals = Kokkos::create_mirror_view(Kokkos::HostSpace(), nodeOrdinals, Kokkos::WithoutInitializing); +#else + hostNodeOrdinals = Kokkos::create_mirror_view(Kokkos::WithoutInitializing, Kokkos::HostSpace(), nodeOrdinals); +#endif partOrdinals = PartOrdinalViewType(Kokkos::view_alloc(Kokkos::WithoutInitializing, "PartOrdinals"), parts.size()); +#ifndef NEW_TRILINOS_INTEGRATION hostPartOrdinals = Kokkos::create_mirror_view(Kokkos::HostSpace(), partOrdinals, Kokkos::WithoutInitializing); +#else + hostPartOrdinals = Kokkos::create_mirror_view(Kokkos::WithoutInitializing, Kokkos::HostSpace(), partOrdinals); +#endif } void DeviceBucket::initialize_from_host(const stk::mesh::Bucket &bucket) @@ -107,7 +127,11 @@ void DeviceBucket::update_from_host(const stk::mesh::Bucket &bucket) if (bucketSize+1 != hostNodeOffsets.size()) { nodeOffsets = OrdinalViewType(Kokkos::view_alloc(Kokkos::WithoutInitializing, "NodeOffsets"), bucketSize+1); +#ifndef NEW_TRILINOS_INTEGRATION hostNodeOffsets = Kokkos::create_mirror_view(Kokkos::HostSpace(), nodeOffsets, Kokkos::WithoutInitializing); +#else + hostNodeOffsets = Kokkos::create_mirror_view(Kokkos::WithoutInitializing, Kokkos::HostSpace(), nodeOffsets); +#endif } unsigned totalNumNodes = bucket.topology().num_nodes()*bucketCapacity; @@ -123,13 +147,23 @@ void DeviceBucket::update_from_host(const stk::mesh::Bucket &bucket) if (totalNumNodes != hostNodeConnectivity.size()) { nodeConnectivity = BucketConnectivityType(Kokkos::view_alloc(Kokkos::WithoutInitializing, "BucketConnectivity"), totalNumNodes); - hostNodeConnectivity = Kokkos::create_mirror_view(Kokkos::HostSpace(), nodeConnectivity, Kokkos::WithoutInitializing); +#ifndef NEW_TRILINOS_INTEGRATION + hostNodeConnectivity = + Kokkos::create_mirror_view(Kokkos::HostSpace(), nodeConnectivity, Kokkos::WithoutInitializing); +#else + hostNodeConnectivity = + Kokkos::create_mirror_view(Kokkos::WithoutInitializing, Kokkos::HostSpace(), nodeConnectivity); +#endif } if (maxNodesPerEntity != hostNodeOrdinals.size()) { nodeOrdinals = OrdinalViewType(Kokkos::view_alloc(Kokkos::WithoutInitializing, "NodeOrdinals"), static_cast(maxNodesPerEntity)); +#ifndef NEW_TRILINOS_INTEGRATION hostNodeOrdinals = Kokkos::create_mirror_view(Kokkos::HostSpace(), nodeOrdinals, Kokkos::WithoutInitializing); +#else + hostNodeOrdinals = Kokkos::create_mirror_view(Kokkos::WithoutInitializing, Kokkos::HostSpace(), nodeOrdinals); +#endif for (unsigned i = 0; i < maxNodesPerEntity; ++i) { hostNodeOrdinals(i) = static_cast(i); } @@ -243,7 +277,11 @@ inline void reallocate_views(DEVICE_VIEW & deviceView, HOST_VIEW & hostView, siz if (needGrowth || needShrink) { const size_t newSize = requiredSize + static_cast(resizeFactor*requiredSize); deviceView = DEVICE_VIEW(Kokkos::view_alloc(Kokkos::WithoutInitializing, deviceView.label()), newSize); +#ifndef NEW_TRILINOS_INTEGRATION hostView = Kokkos::create_mirror_view(Kokkos::HostSpace(), deviceView, Kokkos::WithoutInitializing); +#else + hostView = Kokkos::create_mirror_view(Kokkos::WithoutInitializing, Kokkos::HostSpace(), deviceView); +#endif } } @@ -472,4 +510,3 @@ void DeviceMesh::copy_volatile_fast_shared_comm_map_to_device() } } - diff --git a/packages/stk/stk_mesh/stk_mesh/base/FieldBase.hpp b/packages/stk/stk_mesh/stk_mesh/base/FieldBase.hpp index 2723bebd4cb3..aa2ca40f0893 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/FieldBase.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/FieldBase.hpp @@ -63,7 +63,6 @@ namespace mesh { class BulkData; class MetaData; class UnitTestFieldImpl; -class DataTraits; class FieldBase; template class NgpDebugger> class DeviceField; diff --git a/packages/stk/stk_mesh/stk_mesh/base/FieldDataManager.cpp b/packages/stk/stk_mesh/stk_mesh/base/FieldDataManager.cpp index 652df5078862..07851aad1704 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/FieldDataManager.cpp +++ b/packages/stk/stk_mesh/stk_mesh/base/FieldDataManager.cpp @@ -39,7 +39,6 @@ #include // for FieldMetaData, etc #include #include -#include "stk_mesh/base/DataTraits.hpp" // for DataTraits #include "stk_mesh/base/Types.hpp" // for EntityRank, PartVector #include "stk_util/util/ReportHandler.hpp" // for ThrowRequire, etc #include "stk_util/util/AdjustForAlignment.hpp" diff --git a/packages/stk/stk_mesh/stk_mesh/base/FieldParallel.cpp b/packages/stk/stk_mesh/stk_mesh/base/FieldParallel.cpp index 15b17990ebbf..d67af7495295 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/FieldParallel.cpp +++ b/packages/stk/stk_mesh/stk_mesh/base/FieldParallel.cpp @@ -528,7 +528,6 @@ void parallel_op_impl(const BulkData& mesh, std::vector fields }; MPI_Comm comm = mesh.parallel(); - std::cout << "mesh comm = " << comm << ", rank " << stk::parallel_machine_rank(comm) << " of " << stk::parallel_machine_size(comm) << std::endl; stk::parallel_data_exchange_sym_pack_unpack(comm, comm_procs, msgPacker, msgUnpacker, deterministic); } diff --git a/packages/stk/stk_mesh/stk_mesh/base/MetaData.hpp b/packages/stk/stk_mesh/stk_mesh/base/MetaData.hpp index cecf968fe408..997c55e80357 100644 --- a/packages/stk/stk_mesh/stk_mesh/base/MetaData.hpp +++ b/packages/stk/stk_mesh/stk_mesh/base/MetaData.hpp @@ -769,15 +769,13 @@ field_type & put_field_on_entire_mesh_with_initial_value(field_type & field, template< class field_type > field_type & put_field_on_entire_mesh(field_type & field) { - typename FieldTraits::data_type* init_value = nullptr; - return put_field_on_entire_mesh_with_initial_value(field, init_value); + return put_field_on_entire_mesh_with_initial_value(field, nullptr); } template< class field_type > field_type & put_field_on_entire_mesh(field_type & field, unsigned n1) { - typename FieldTraits::data_type* init_value = nullptr; - return put_field_on_entire_mesh_with_initial_value(field, n1, init_value); + return put_field_on_entire_mesh_with_initial_value(field, n1, nullptr); } /** \} */ diff --git a/packages/stk/stk_mesh/stk_mesh/baseImpl/DebugWriter.hpp b/packages/stk/stk_mesh/stk_mesh/baseImpl/DebugWriter.hpp index 2f04cadc97e0..6737c9d490ca 100644 --- a/packages/stk/stk_mesh/stk_mesh/baseImpl/DebugWriter.hpp +++ b/packages/stk/stk_mesh/stk_mesh/baseImpl/DebugWriter.hpp @@ -38,7 +38,6 @@ #include // for BulkData #include // for size_t #include // for operator<<, etc -#include // for DataTraits #include #include // for FieldBase, etc #include // for EntityVector, etc diff --git a/packages/stk/stk_performance_tests/stk_mesh/NgpFieldAccess.cpp b/packages/stk/stk_performance_tests/stk_mesh/NgpFieldAccess.cpp index 28b5e0c98592..e47386bdb75c 100644 --- a/packages/stk/stk_performance_tests/stk_mesh/NgpFieldAccess.cpp +++ b/packages/stk/stk_performance_tests/stk_mesh/NgpFieldAccess.cpp @@ -68,12 +68,10 @@ class NgpFieldAccess : public stk::unit_test_util::simple_fields::MeshFixture void declare_centroid_field() { centroid = &get_meta().declare_field(stk::topology::ELEM_RANK, "centroid"); - stk::mesh::put_field_on_mesh(*centroid, get_meta().universal_part(), 3, - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(*centroid, get_meta().universal_part(), 3, nullptr); hostCentroid = &get_meta().declare_field(stk::topology::ELEM_RANK, "hostCentroid"); - stk::mesh::put_field_on_mesh(*hostCentroid, get_meta().universal_part(), 3, - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(*hostCentroid, get_meta().universal_part(), 3, nullptr); } void declare_centroid_partial_mesh(unsigned numBlocks) @@ -82,8 +80,7 @@ class NgpFieldAccess : public stk::unit_test_util::simple_fields::MeshFixture for(unsigned i = 1; i <= numBlocks; i++) { const std::string partName = "block_" + std::to_string(i); stk::mesh::Part& part = get_meta().declare_part(partName, stk::topology::ELEM_RANK); - stk::mesh::put_field_on_mesh(*centroid, part, 3, - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(*centroid, part, 3, nullptr); } } diff --git a/packages/stk/stk_performance_tests/stk_mesh/NgpFieldUpdate.cpp b/packages/stk/stk_performance_tests/stk_mesh/NgpFieldUpdate.cpp index aa06479a906f..342a7a29ecd1 100644 --- a/packages/stk/stk_performance_tests/stk_mesh/NgpFieldUpdate.cpp +++ b/packages/stk/stk_performance_tests/stk_mesh/NgpFieldUpdate.cpp @@ -74,8 +74,8 @@ class NgpFieldSyncTest : public stk::unit_test_util::simple_fields::MeshFixture auto vectorField = &get_meta().declare_field(stk::topology::ELEMENT_RANK, "VectorField"); auto stkIntField = &get_meta().declare_field(stk::topology::ELEMENT_RANK, "intField", 1); - stk::mesh::put_field_on_mesh(*tensorField, get_meta().universal_part(), tensorFieldSizePerElem, static_cast(nullptr)); - stk::mesh::put_field_on_mesh(*vectorField, get_meta().universal_part(), vectorFieldSizePerElem, static_cast(nullptr)); + stk::mesh::put_field_on_mesh(*tensorField, get_meta().universal_part(), tensorFieldSizePerElem, nullptr); + stk::mesh::put_field_on_mesh(*vectorField, get_meta().universal_part(), vectorFieldSizePerElem, nullptr); stk::mesh::put_field_on_mesh(*stkIntField, get_meta().universal_part(), numComponent, init.data()); } @@ -188,8 +188,8 @@ class NgpFieldUpdateFixture : public stk::unit_test_util::simple_fields::MeshFix { tensorField = &get_meta().declare_field(stk::topology::ELEMENT_RANK, "TensorField"); vectorField = &get_meta().declare_field(stk::topology::ELEMENT_RANK, "VectorField"); - stk::mesh::put_field_on_mesh(*tensorField, get_meta().universal_part(), tensorFieldSizePerElem, static_cast(nullptr)); - stk::mesh::put_field_on_mesh(*vectorField, get_meta().universal_part(), vectorFieldSizePerElem, static_cast(nullptr)); + stk::mesh::put_field_on_mesh(*tensorField, get_meta().universal_part(), tensorFieldSizePerElem, nullptr); + stk::mesh::put_field_on_mesh(*vectorField, get_meta().universal_part(), vectorFieldSizePerElem, nullptr); stk::performance_tests::setup_multiple_blocks(get_meta(), numElemBlocks); stk::io::fill_mesh(meshSpecification, get_bulk()); stk::performance_tests::move_elements_to_other_blocks(get_bulk(), numElemsPerDim); diff --git a/packages/stk/stk_performance_tests/stk_mesh/perfElemGraph.cpp b/packages/stk/stk_performance_tests/stk_mesh/perfElemGraph.cpp index 1051c75a12ca..4640d2c2b756 100644 --- a/packages/stk/stk_performance_tests/stk_mesh/perfElemGraph.cpp +++ b/packages/stk/stk_performance_tests/stk_mesh/perfElemGraph.cpp @@ -86,8 +86,7 @@ class AnimateMeshDeletion void initialize_status_field() { - int val = 0; - stk::mesh::put_field_on_mesh(m_statusField, m_bulkData.mesh_meta_data().universal_part(), &val); + stk::mesh::put_field_on_mesh(m_statusField, m_bulkData.mesh_meta_data().universal_part(), nullptr); } void create_output_mesh() @@ -139,8 +138,7 @@ void declare_animation_field(stk::mesh::MetaData &metaData, std::string &animati if("" != animationFile) { ScalarIntField &deathField = metaData.declare_field(stk::topology::ELEMENT_RANK, "death"); - int val = 0; - stk::mesh::put_field_on_mesh(deathField, metaData.universal_part(), &val); + stk::mesh::put_field_on_mesh(deathField, metaData.universal_part(), nullptr); } } diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/ConstructedMesh.cpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/ConstructedMesh.cpp index 37ede728ed60..b367b9ae598f 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/ConstructedMesh.cpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/ConstructedMesh.cpp @@ -76,7 +76,7 @@ void ConstructedMesh::populate_bulk_data(stk::mesh::BulkData& bulk) } stk::mesh::Field & coordsField = meta.declare_field>(stk::topology::NODE_RANK, "coordinates", 1); - stk::mesh::put_field_on_mesh(coordsField, meta.universal_part(), m_spatialDimension, static_cast(nullptr)); + stk::mesh::put_field_on_mesh(coordsField, meta.universal_part(), m_spatialDimension, nullptr); bulk.modification_begin(); if(bulk.parallel_rank() == 0) { @@ -169,7 +169,7 @@ void ConstructedMesh::populate_bulk_data(stk::mesh::BulkData& bulk) } stk::mesh::Field & coordsField = meta.declare_field(stk::topology::NODE_RANK, "coordinates", 1); - stk::mesh::put_field_on_mesh(coordsField, meta.universal_part(), m_spatialDimension, static_cast(nullptr)); + stk::mesh::put_field_on_mesh(coordsField, meta.universal_part(), m_spatialDimension, nullptr); stk::io::set_field_output_type(coordsField, "Vector_3D"); bulk.modification_begin(); diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/GeneratedMeshToFile.cpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/GeneratedMeshToFile.cpp index abe03a21dcb8..5c61929f1dec 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/GeneratedMeshToFile.cpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/GeneratedMeshToFile.cpp @@ -58,10 +58,8 @@ GeneratedMeshToFileWithTransientFields::GeneratedMeshToFileWithTransientFields(s scalarField(meta.declare_field >(fieldRank, fieldBaseName+"_scalar", 1)), vectorField(meta.declare_field >(fieldRank, fieldBaseName+"_vector", 1)) { - stk::mesh::put_field_on_mesh(scalarField, meta.universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); - stk::mesh::put_field_on_mesh(vectorField, meta.universal_part(), 3, - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(scalarField, meta.universal_part(), nullptr); + stk::mesh::put_field_on_mesh(vectorField, meta.universal_part(), 3, nullptr); } void GeneratedMeshToFileWithTransientFields::write_mesh_with_field(const std::vector& timeSteps, @@ -132,10 +130,8 @@ GeneratedMeshToFileWithTransientFields::GeneratedMeshToFileWithTransientFields(s scalarField(meta.declare_field(fieldRank, fieldBaseName+"_scalar", 1)), vectorField(meta.declare_field(fieldRank, fieldBaseName+"_vector", 1)) { - stk::mesh::put_field_on_mesh(scalarField, meta.universal_part(), - (stk::mesh::FieldTraits>::data_type*) nullptr); - stk::mesh::put_field_on_mesh(vectorField, meta.universal_part(), 3, - (stk::mesh::FieldTraits>::data_type*) nullptr); + stk::mesh::put_field_on_mesh(scalarField, meta.universal_part(), nullptr); + stk::mesh::put_field_on_mesh(vectorField, meta.universal_part(), 3, nullptr); stk::io::set_field_output_type(vectorField, "Vector_3D"); } diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/MeshFixture.hpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/MeshFixture.hpp index 3eedcb24111d..33d8dce59f87 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/MeshFixture.hpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/MeshFixture.hpp @@ -42,7 +42,7 @@ #include // for MetaData, put_field #include #include -#include +#include "stk_util/util/ReportHandler.hpp" // for set_report_handler namespace stk { @@ -233,7 +233,7 @@ class MeshFixtureNoTest : communicator(MPI_COMM_WORLD), m_spatialDim(3), m_entityRankNames(), - metaData(nullptr), bulkData() + metaData(), bulkData() { } @@ -241,7 +241,7 @@ class MeshFixtureNoTest : communicator(MPI_COMM_WORLD), m_spatialDim(spatial_dim), m_entityRankNames(), - metaData(nullptr), bulkData() + metaData(), bulkData() { } @@ -249,13 +249,13 @@ class MeshFixtureNoTest : communicator(MPI_COMM_WORLD), m_spatialDim(spatial_dim), m_entityRankNames(entityRankNames), - metaData(nullptr), bulkData() + metaData(), bulkData() { } virtual ~MeshFixtureNoTest() { - metaData = nullptr; + } void set_spatial_dimension(unsigned spatialDim) @@ -293,7 +293,7 @@ class MeshFixtureNoTest void reset_mesh() { bulkData.reset(); - metaData = nullptr; + metaData.reset(); } int get_parallel_rank() const @@ -327,23 +327,47 @@ class MeshFixtureNoTest builder.set_aura_option(auraOption); builder.set_bucket_capacity(bucketCapacity); - bulkData = builder.create(); - metaData = &(bulkData->mesh_meta_data()); - metaData->use_simple_fields(); + if(nullptr == metaData) { + metaData = builder.create_meta_data(); + metaData->use_simple_fields(); + } + + if(nullptr == bulkData) { + bulkData = builder.create(metaData); + m_auraOption = auraOption; + m_bucketCapacity = bucketCapacity; + } + + ThrowRequireMsg((auraOption == m_auraOption) && (bucketCapacity == m_bucketCapacity), + "allocate_bulk being called with different arguments from previous call: auraOption = " + << auraOption << " (previously: " << m_auraOption << ") bucketCapacity = " + << bucketCapacity << " (previously: " << m_bucketCapacity << ")" ); + } + + void set_meta(std::shared_ptr inMetaData) + { + ThrowRequireMsg(metaData==nullptr, "Unit test error. Trying to reset non NULL meta data."); + metaData = inMetaData; } void set_bulk(std::shared_ptr inBulkData) { ThrowRequireMsg(bulkData==nullptr, "Unit test error. Trying to reset non NULL bulk data."); bulkData = inBulkData; + + ThrowRequireMsg(metaData==nullptr || metaData==bulkData->mesh_meta_data_ptr(), + "Unit test error. Trying to reset non NULL meta data."); } protected: MPI_Comm communicator; unsigned m_spatialDim; std::vector m_entityRankNames; - stk::mesh::MetaData *metaData = nullptr; + std::shared_ptr metaData; std::shared_ptr bulkData; + + stk::mesh::BulkData::AutomaticAuraOption m_auraOption{stk::mesh::BulkData::AUTO_AURA}; + unsigned m_bucketCapacity{0}; }; class MeshFixture : public MeshFixtureNoTest, public ::ngp_testing::Test { diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/TextMesh.cpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/TextMesh.cpp index 8e4b99e2f939..d43c30d0a254 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/TextMesh.cpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/TextMesh.cpp @@ -80,8 +80,7 @@ class MetaDataInitializer m_meta.declare_field>(stk::topology::NODE_RANK, nodesetDistFieldName); stk::io::set_field_role(distributionFactorsFieldPerNodeset, Ioss::Field::MESH); - stk::mesh::put_field_on_mesh(distributionFactorsFieldPerNodeset, *part, - (stk::mesh::FieldTraits>::data_type*) nullptr); + stk::mesh::put_field_on_mesh(distributionFactorsFieldPerNodeset, *part, nullptr); } } @@ -92,8 +91,7 @@ class MetaDataInitializer if (nullptr != distributionFactorsField) { stk::io::set_distribution_factor_field(*sideBlockPart, *distributionFactorsField); - stk::mesh::put_field_on_mesh(*distributionFactorsField, *sideBlockPart, sideBlock.numNodesPerSide, - (stk::mesh::FieldTraits>::data_type*) nullptr); + stk::mesh::put_field_on_mesh(*distributionFactorsField, *sideBlockPart, sideBlock.numNodesPerSide, nullptr); } } @@ -104,8 +102,7 @@ class MetaDataInitializer if (nullptr != distributionFactorsField) { stk::io::set_distribution_factor_field(*sideBlockPart, *distributionFactorsField); - stk::mesh::put_field_on_mesh(*distributionFactorsField, *sideBlockPart, sideBlock.numNodesPerSide, - (stk::mesh::FieldTraits>::data_type*) nullptr); + stk::mesh::put_field_on_mesh(*distributionFactorsField, *sideBlockPart, sideBlock.numNodesPerSide, nullptr); } } @@ -268,14 +265,14 @@ class MetaDataInitializer void declare_coordinate_field_with_type() { F& coordsField = m_meta.declare_field(stk::topology::NODE_RANK, m_meta.coordinate_field_name()); - stk::mesh::put_field_on_mesh(coordsField, m_meta.universal_part(), m_data.spatialDim, static_cast(nullptr)); + stk::mesh::put_field_on_mesh(coordsField, m_meta.universal_part(), m_data.spatialDim, nullptr); } template void declare_coordinate_field_with_datatype() { stk::mesh::Field& coordsField = m_meta.declare_field(stk::topology::NODE_RANK, m_meta.coordinate_field_name()); - stk::mesh::put_field_on_mesh(coordsField, m_meta.universal_part(), m_data.spatialDim, static_cast(nullptr)); + stk::mesh::put_field_on_mesh(coordsField, m_meta.universal_part(), m_data.spatialDim, nullptr); stk::io::set_field_output_type(coordsField, "Vector_3D"); } diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/GearsFixture.cpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/GearsFixture.cpp index beef67132ed9..99223703a58f 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/GearsFixture.cpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/GearsFixture.cpp @@ -82,17 +82,10 @@ GearsFixture::GearsFixture(ParallelMachine pm, size_t num_gears, GearParams gear m_gears() { - put_field_on_mesh(cartesian_coord_field, meta_data.universal_part(), SpatialDimension, - (stk::mesh::FieldTraits >::data_type*)nullptr); - - put_field_on_mesh(displacement_field, meta_data.universal_part(), SpatialDimension, - (stk::mesh::FieldTraits >::data_type*)nullptr); - - put_field_on_mesh(translation_field, cylindrical_coord_part, SpatialDimension, - (stk::mesh::FieldTraits >::data_type*)nullptr); - - put_field_on_mesh(cylindrical_coord_field, cylindrical_coord_part, SpatialDimension, - (stk::mesh::FieldTraits >::data_type*)nullptr); + put_field_on_mesh(cartesian_coord_field, meta_data.universal_part(), SpatialDimension, nullptr); + put_field_on_mesh(displacement_field, meta_data.universal_part(), SpatialDimension, nullptr); + put_field_on_mesh(translation_field, cylindrical_coord_part, SpatialDimension, nullptr); + put_field_on_mesh(cylindrical_coord_field, cylindrical_coord_part, SpatialDimension, nullptr); m_gears.resize(NUM_GEARS); @@ -305,20 +298,16 @@ GearsFixture::GearsFixture(ParallelMachine pm, size_t num_gears, GearParams gear translation_field = &meta_data.declare_field(stk::topology::NODE_RANK, "translation", ONE_STATE); cylindrical_coord_field = &meta_data.declare_field(stk::topology::NODE_RANK, "cylindrical_coordinates", ONE_STATE); - put_field_on_mesh(*cartesian_coord_field, meta_data.universal_part(), SpatialDimension, - (stk::mesh::FieldTraits>::data_type*)nullptr); + put_field_on_mesh(*cartesian_coord_field, meta_data.universal_part(), SpatialDimension, nullptr); stk::io::set_field_output_type(*cartesian_coord_field, "Vector_3D"); - put_field_on_mesh(*displacement_field, meta_data.universal_part(), SpatialDimension, - (stk::mesh::FieldTraits>::data_type*)nullptr); + put_field_on_mesh(*displacement_field, meta_data.universal_part(), SpatialDimension, nullptr); stk::io::set_field_output_type(*displacement_field, "Vector_3D"); - put_field_on_mesh(*translation_field, cylindrical_coord_part, SpatialDimension, - (stk::mesh::FieldTraits>::data_type*)nullptr); + put_field_on_mesh(*translation_field, cylindrical_coord_part, SpatialDimension, nullptr); stk::io::set_field_output_type(*translation_field, "Vector_3D"); - put_field_on_mesh(*cylindrical_coord_field, cylindrical_coord_part, SpatialDimension, - (stk::mesh::FieldTraits>::data_type*)nullptr); + put_field_on_mesh(*cylindrical_coord_field, cylindrical_coord_part, SpatialDimension, nullptr); m_gears.resize(NUM_GEARS); diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/Hex20Fixture.cpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/Hex20Fixture.cpp index be800a579ab9..2b00cbe60eed 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/Hex20Fixture.cpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/Hex20Fixture.cpp @@ -71,8 +71,7 @@ Hex20Fixture::Hex20Fixture(MetaData& meta, m_coord_field( m_meta.declare_field(stk::topology::NODE_RANK, "Coordinates") ) { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } Hex20Fixture::Hex20Fixture(stk::ParallelMachine pm, @@ -97,8 +96,7 @@ Hex20Fixture::Hex20Fixture(stk::ParallelMachine pm, { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } @@ -125,8 +123,7 @@ Hex20Fixture::Hex20Fixture(stk::ParallelMachine pm, { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } @@ -320,8 +317,7 @@ Hex20Fixture::Hex20Fixture(MetaData& meta, m_coord_field( &m_meta.declare_field(stk::topology::NODE_RANK, "Coordinates") ) { //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } @@ -348,8 +344,7 @@ Hex20Fixture::Hex20Fixture(stk::ParallelMachine pm, m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, "Coordinates"); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } @@ -378,8 +373,7 @@ Hex20Fixture::Hex20Fixture(stk::ParallelMachine pm, m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, coordsName); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/Hex27Fixture.cpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/Hex27Fixture.cpp index 837576e41dfd..9412701c7667 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/Hex27Fixture.cpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/Hex27Fixture.cpp @@ -71,8 +71,7 @@ Hex27Fixture::Hex27Fixture(MetaData& meta, m_coord_field( m_meta.declare_field(stk::topology::NODE_RANK, "Coordinates") ) { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } Hex27Fixture::Hex27Fixture(stk::ParallelMachine pm, @@ -97,8 +96,7 @@ Hex27Fixture::Hex27Fixture(stk::ParallelMachine pm, { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } @@ -125,8 +123,7 @@ Hex27Fixture::Hex27Fixture(stk::ParallelMachine pm, { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } @@ -338,8 +335,7 @@ Hex27Fixture::Hex27Fixture(MetaData& meta, m_coord_field( &m_meta.declare_field(stk::topology::NODE_RANK, "Coordinates") ) { //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } @@ -366,8 +362,7 @@ Hex27Fixture::Hex27Fixture(stk::ParallelMachine pm, m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, "Coordinates"); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } @@ -396,8 +391,7 @@ Hex27Fixture::Hex27Fixture(stk::ParallelMachine pm, m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, coordsName); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/HexFixture.cpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/HexFixture.cpp index f219f7760bed..4124c1581756 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/HexFixture.cpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/HexFixture.cpp @@ -74,8 +74,7 @@ HexFixture::HexFixture(MetaData& meta, owns_mesh(false) { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } HexFixture::HexFixture(stk::ParallelMachine pm, @@ -99,8 +98,7 @@ HexFixture::HexFixture(stk::ParallelMachine pm, { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } @@ -125,8 +123,7 @@ HexFixture::HexFixture(stk::ParallelMachine pm, m_coord_field( m_meta.declare_field(stk::topology::NODE_RANK, coordinate_name) ) { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } HexFixture::HexFixture(stk::ParallelMachine pm, @@ -151,8 +148,7 @@ HexFixture::HexFixture(stk::ParallelMachine pm, { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } @@ -377,8 +373,7 @@ HexFixture::HexFixture(MetaData& meta, owns_mesh(false) { //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } HexFixture::HexFixture(stk::ParallelMachine pm, @@ -403,8 +398,7 @@ HexFixture::HexFixture(stk::ParallelMachine pm, m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, "Coordinates"); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } HexFixture::HexFixture(stk::ParallelMachine pm, @@ -430,8 +424,7 @@ HexFixture::HexFixture(stk::ParallelMachine pm, m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, coordinate_name); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } HexFixture::HexFixture(stk::ParallelMachine pm, @@ -457,8 +450,7 @@ HexFixture::HexFixture(stk::ParallelMachine pm, m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, "Coordinates"); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } HexFixture::~HexFixture() diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/PyramidFixture.cpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/PyramidFixture.cpp index e86905a61855..9848c36a038f 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/PyramidFixture.cpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/PyramidFixture.cpp @@ -72,8 +72,7 @@ PyramidFixture::PyramidFixture(MetaData& meta, owns_mesh(false) { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } PyramidFixture::PyramidFixture(stk::ParallelMachine pm, @@ -98,8 +97,7 @@ PyramidFixture::PyramidFixture(stk::ParallelMachine pm, { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } @@ -126,8 +124,7 @@ PyramidFixture::PyramidFixture(stk::ParallelMachine pm, { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } @@ -338,8 +335,7 @@ PyramidFixture::PyramidFixture(MetaData& meta, owns_mesh(false) { //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } @@ -366,8 +362,7 @@ PyramidFixture::PyramidFixture(stk::ParallelMachine pm, m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, "Coordinates"); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } @@ -396,8 +391,7 @@ PyramidFixture::PyramidFixture(stk::ParallelMachine pm, m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, coordinate_name); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/QuadFixture.cpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/QuadFixture.cpp index 3e0c2942dd35..4f10c94edf74 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/QuadFixture.cpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/QuadFixture.cpp @@ -69,8 +69,7 @@ QuadFixture::QuadFixture( MetaData& meta, BulkData& bulk, size_t nx, size_t ny, m_elem_id_start(eid_start) { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } QuadFixture::QuadFixture( stk::ParallelMachine pm , @@ -88,8 +87,7 @@ QuadFixture::QuadFixture( stk::ParallelMachine pm , m_ny( ny ) { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } QuadFixture::QuadFixture( stk::ParallelMachine pm , @@ -108,8 +106,7 @@ QuadFixture::QuadFixture( stk::ParallelMachine pm , m_ny( ny ) { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } QuadFixture::QuadFixture( stk::ParallelMachine pm , @@ -128,8 +125,7 @@ QuadFixture::QuadFixture( stk::ParallelMachine pm , { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } void QuadFixture::node_x_y( EntityId entity_id, unsigned &x , unsigned &y ) const @@ -286,8 +282,7 @@ Quad9Fixture::Quad9Fixture( MetaData& meta, BulkData& bulk, size_t nx, size_t ny m_elem_id_start(eid_start) { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } Quad9Fixture::Quad9Fixture( stk::ParallelMachine pm , @@ -305,8 +300,7 @@ Quad9Fixture::Quad9Fixture( stk::ParallelMachine pm , m_ny( ny ) { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } Quad9Fixture::Quad9Fixture( stk::ParallelMachine pm , @@ -325,8 +319,7 @@ Quad9Fixture::Quad9Fixture( stk::ParallelMachine pm , m_ny( ny ) { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } Quad9Fixture::Quad9Fixture( stk::ParallelMachine pm , @@ -345,8 +338,7 @@ Quad9Fixture::Quad9Fixture( stk::ParallelMachine pm , { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } void Quad9Fixture::elem_x_y( EntityId entity_id, unsigned &x , unsigned &y ) const @@ -536,8 +528,7 @@ QuadFixture::QuadFixture( MetaData& meta, BulkData& bulk, size_t nx, size_t ny, m_elem_id_start(eid_start) { //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } QuadFixture::QuadFixture( stk::ParallelMachine pm , @@ -557,8 +548,7 @@ QuadFixture::QuadFixture( stk::ParallelMachine pm , m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, "Coordinates"); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } QuadFixture::QuadFixture( stk::ParallelMachine pm , @@ -579,8 +569,7 @@ QuadFixture::QuadFixture( stk::ParallelMachine pm , m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, coordsName); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } QuadFixture::QuadFixture( stk::ParallelMachine pm , @@ -600,8 +589,7 @@ QuadFixture::QuadFixture( stk::ParallelMachine pm , m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, "Coordinates"); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } void QuadFixture::node_x_y( EntityId entity_id, unsigned &x , unsigned &y ) const @@ -764,8 +752,7 @@ Quad9Fixture::Quad9Fixture( MetaData& meta, BulkData& bulk, size_t nx, size_t ny m_elem_id_start(eid_start) { //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } Quad9Fixture::Quad9Fixture( stk::ParallelMachine pm , @@ -785,8 +772,7 @@ Quad9Fixture::Quad9Fixture( stk::ParallelMachine pm , m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, "Coordinates"); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } Quad9Fixture::Quad9Fixture( stk::ParallelMachine pm , @@ -807,8 +793,7 @@ Quad9Fixture::Quad9Fixture( stk::ParallelMachine pm , m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, coordsName); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } Quad9Fixture::Quad9Fixture( stk::ParallelMachine pm , @@ -828,8 +813,7 @@ Quad9Fixture::Quad9Fixture( stk::ParallelMachine pm , m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, "Coordinates"); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*)nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } void Quad9Fixture::elem_x_y( EntityId entity_id, unsigned &x , unsigned &y ) const diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/QuadShellFixture.cpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/QuadShellFixture.cpp index 0ff230a6bb2a..8071cb4d551c 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/QuadShellFixture.cpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/QuadShellFixture.cpp @@ -75,8 +75,7 @@ QuadShellFixture::QuadShellFixture(MetaData& meta, m_ny( ny ) { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } QuadShellFixture::QuadShellFixture( stk::ParallelMachine pm , @@ -94,8 +93,7 @@ QuadShellFixture::QuadShellFixture( stk::ParallelMachine pm , m_ny( ny ) { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } QuadShellFixture::QuadShellFixture( stk::ParallelMachine pm , @@ -114,8 +112,7 @@ QuadShellFixture::QuadShellFixture( stk::ParallelMachine pm , m_ny( ny ) { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } QuadShellFixture::QuadShellFixture( stk::ParallelMachine pm , @@ -133,8 +130,7 @@ QuadShellFixture::QuadShellFixture( stk::ParallelMachine pm , m_ny( ny ) { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } QuadShellFixture::~QuadShellFixture() @@ -305,8 +301,7 @@ QuadShellFixture::QuadShellFixture(MetaData& meta, m_ny( ny ) { //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } @@ -327,8 +322,7 @@ QuadShellFixture::QuadShellFixture( stk::ParallelMachine pm , m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, "Coordinates"); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } @@ -350,8 +344,7 @@ QuadShellFixture::QuadShellFixture( stk::ParallelMachine pm , m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, coordsName); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } @@ -371,8 +364,7 @@ QuadShellFixture::QuadShellFixture( stk::ParallelMachine pm , m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, "Coordinates"); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/SelectorFixture.cpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/SelectorFixture.cpp index 63fed1f31975..aced67f1a99c 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/SelectorFixture.cpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/SelectorFixture.cpp @@ -67,15 +67,11 @@ SelectorFixture::SelectorFixture() m_fieldA(m_meta_data.declare_field >(stk::topology::NODE_RANK, "FieldA")), m_fieldABC(m_meta_data.declare_field >(stk::topology::NODE_RANK, "FieldABC")) { - stk::mesh::put_field_on_mesh(m_fieldA, m_partA, - (stk::mesh::FieldTraits >::data_type*) nullptr); - - stk::mesh::put_field_on_mesh(m_fieldABC, m_partA, - (stk::mesh::FieldTraits >::data_type*) nullptr); - stk::mesh::put_field_on_mesh(m_fieldABC, m_partB, - (stk::mesh::FieldTraits >::data_type*) nullptr); - stk::mesh::put_field_on_mesh(m_fieldABC, m_partC, - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(m_fieldA, m_partA, nullptr); + + stk::mesh::put_field_on_mesh(m_fieldABC, m_partA, nullptr); + stk::mesh::put_field_on_mesh(m_fieldABC, m_partB, nullptr); + stk::mesh::put_field_on_mesh(m_fieldABC, m_partC, nullptr); } void SelectorFixture::generate_mesh() @@ -185,15 +181,11 @@ SelectorFixture::SelectorFixture() m_fieldA = &m_meta_data.declare_field(stk::topology::NODE_RANK, "FieldA"); m_fieldABC = &m_meta_data.declare_field(stk::topology::NODE_RANK, "FieldABC"); - stk::mesh::put_field_on_mesh(*m_fieldA, m_partA, - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(*m_fieldA, m_partA, nullptr); - stk::mesh::put_field_on_mesh(*m_fieldABC, m_partA, - (stk::mesh::FieldTraits >::data_type*) nullptr); - stk::mesh::put_field_on_mesh(*m_fieldABC, m_partB, - (stk::mesh::FieldTraits >::data_type*) nullptr); - stk::mesh::put_field_on_mesh(*m_fieldABC, m_partC, - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(*m_fieldABC, m_partA, nullptr); + stk::mesh::put_field_on_mesh(*m_fieldABC, m_partB, nullptr); + stk::mesh::put_field_on_mesh(*m_fieldABC, m_partC, nullptr); } void SelectorFixture::generate_mesh() diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/Tet10Fixture.cpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/Tet10Fixture.cpp index 1b8b197164f1..10e8179982b6 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/Tet10Fixture.cpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/Tet10Fixture.cpp @@ -71,8 +71,7 @@ Tet10Fixture::Tet10Fixture(MetaData& meta, m_coord_field( m_meta.declare_field(stk::topology::NODE_RANK, "Coordinates") ) { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } Tet10Fixture::Tet10Fixture(stk::ParallelMachine pm, @@ -96,8 +95,7 @@ Tet10Fixture::Tet10Fixture(stk::ParallelMachine pm, { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } @@ -123,8 +121,7 @@ Tet10Fixture::Tet10Fixture(stk::ParallelMachine pm, { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } @@ -348,8 +345,7 @@ Tet10Fixture::Tet10Fixture(MetaData& meta, m_coord_field( &m_meta.declare_field(stk::topology::NODE_RANK, "Coordinates") ) { //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } @@ -375,8 +371,7 @@ Tet10Fixture::Tet10Fixture(stk::ParallelMachine pm, m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, "Coordinates"); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } @@ -404,8 +399,7 @@ Tet10Fixture::Tet10Fixture(stk::ParallelMachine pm, m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, coordsName); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/TetFixture.cpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/TetFixture.cpp index 3674e7a6a4ea..86d10c55e040 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/TetFixture.cpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/TetFixture.cpp @@ -72,8 +72,7 @@ TetFixture::TetFixture(MetaData& meta, owns_mesh(false) { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } TetFixture::TetFixture(stk::ParallelMachine pm, @@ -97,8 +96,7 @@ TetFixture::TetFixture(stk::ParallelMachine pm, { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } TetFixture::TetFixture(stk::ParallelMachine pm, @@ -123,8 +121,7 @@ TetFixture::TetFixture(stk::ParallelMachine pm, { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } @@ -323,8 +320,7 @@ TetFixture::TetFixture(MetaData& meta, owns_mesh(false) { //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } @@ -350,8 +346,7 @@ TetFixture::TetFixture(stk::ParallelMachine pm, m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, "Coordinates"); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } @@ -378,8 +373,7 @@ TetFixture::TetFixture(stk::ParallelMachine pm, m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, coordsName); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/TriFixture.cpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/TriFixture.cpp index 288cbf087a01..a329ff0ea0b9 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/TriFixture.cpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/TriFixture.cpp @@ -77,8 +77,7 @@ TriFixtureImpl::TriFixtureImpl(MetaData& meta, m_face_topology( DIM == 2 ? stk::topology::LINE_2 : stk::topology::TRI_3) { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } template @@ -113,8 +112,7 @@ TriFixtureImpl::TriFixtureImpl(stk::ParallelMachine pm, m_face_topology( DIM == 2 ? stk::topology::LINE_2 : stk::topology::TRI_3) { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } @@ -312,8 +310,7 @@ TriFixtureImpl::TriFixtureImpl(MetaData& meta, m_face_topology( DIM == 2 ? stk::topology::LINE_2 : stk::topology::TRI_3) { //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } @@ -351,8 +348,7 @@ TriFixtureImpl::TriFixtureImpl(stk::ParallelMachine pm, m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, coordsName); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } diff --git a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/WedgeFixture.cpp b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/WedgeFixture.cpp index 5a91b72a5179..35a4cd679d82 100644 --- a/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/WedgeFixture.cpp +++ b/packages/stk/stk_unit_test_utils/stk_unit_test_utils/stk_mesh_fixtures/WedgeFixture.cpp @@ -75,8 +75,7 @@ WedgeFixture::WedgeFixture(MetaData& meta, owns_mesh(false) { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } WedgeFixture::WedgeFixture(stk::ParallelMachine pm, @@ -100,8 +99,7 @@ WedgeFixture::WedgeFixture(stk::ParallelMachine pm, { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } @@ -127,8 +125,7 @@ WedgeFixture::WedgeFixture(stk::ParallelMachine pm, { //put coord-field on all nodes: - put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); } @@ -323,8 +320,7 @@ WedgeFixture::WedgeFixture(MetaData& meta, owns_mesh(false) { //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } @@ -350,8 +346,7 @@ WedgeFixture::WedgeFixture(stk::ParallelMachine pm, m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, "Coordinates"); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } @@ -379,8 +374,7 @@ WedgeFixture::WedgeFixture(stk::ParallelMachine pm, m_coord_field = &m_meta.declare_field(stk::topology::NODE_RANK, coordinate_name); //put coord-field on all nodes: - put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(*m_coord_field, m_meta.universal_part(), m_spatial_dimension, nullptr); stk::io::set_field_output_type(*m_coord_field, "Vector_3D"); } diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestColoring.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestColoring.cpp index 2c4775ec2f1c..8945a43b9a89 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestColoring.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestColoring.cpp @@ -104,7 +104,6 @@ class ColorMeshWithColoringFieldsSettings : public stk::balance::BalanceSettings void declare_color_fields(stk::mesh::MetaData& meta) { - const int initValue = 0; const stk::mesh::PartVector& parts = meta.get_parts(); for(stk::mesh::Part* part : parts) { @@ -114,7 +113,7 @@ void declare_color_fields(stk::mesh::MetaData& meta) stk::mesh::Part& rootTopologyPart = meta.get_topology_root_part(topo); stk::mesh::Field& colorField = meta.declare_field(stk::topology::ELEMENT_RANK, rootTopologyPart.topology().name() + "coloring"); - stk::mesh::put_field_on_mesh(colorField, rootTopologyPart, &initValue); + stk::mesh::put_field_on_mesh(colorField, rootTopologyPart, nullptr); } } } @@ -146,8 +145,7 @@ TEST(ColorByTopology, colorHeterogeneousMesh) stk::mesh::MetaData& meta = bulk->mesh_meta_data(); stk::mesh::fixtures::simple_fields::VectorFieldType & node_coord = meta.declare_field(stk::topology::NODE_RANK, "coordinates"); - stk::mesh::put_field_on_mesh(node_coord, meta.universal_part(), 3, - (stk::mesh::FieldTraits::data_type*) nullptr); + stk::mesh::put_field_on_mesh(node_coord, meta.universal_part(), 3, nullptr); stk::mesh::fixtures::simple_fields::heterogeneous_mesh_meta_data( meta , node_coord ); declare_color_fields(meta); @@ -198,8 +196,7 @@ TEST_F(Color2DMesh, colorHeterogeneousMeshWithQuadsSurroundingTriangles) setup_empty_mesh(stk::mesh::BulkData::AUTO_AURA); Vector2dFieldType & node_coord = get_meta().declare_field(stk::topology::NODE_RANK, "coordinates"); - stk::mesh::put_field_on_mesh(node_coord, get_meta().universal_part(), 2, - (stk::mesh::FieldTraits::data_type*) nullptr); + stk::mesh::put_field_on_mesh(node_coord, get_meta().universal_part(), 2, nullptr); quad_tri_mesh_meta_data(get_meta() , node_coord); diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestSettingVertexWeights.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestSettingVertexWeights.cpp index b736557e26ec..f896c722b03c 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestSettingVertexWeights.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestSettingVertexWeights.cpp @@ -22,7 +22,7 @@ class VertexWeightSettings : public stk::unit_test_util::simple_fields::MeshFixt { setup_empty_mesh(stk::mesh::BulkData::AUTO_AURA); vertexWeightField = &get_meta().declare_field(stk::topology::ELEMENT_RANK, "vertex_weights", 1); - stk::mesh::put_field_on_mesh(*vertexWeightField, get_meta().universal_part(), static_cast(nullptr)); + stk::mesh::put_field_on_mesh(*vertexWeightField, get_meta().universal_part(), nullptr); } virtual ~VertexWeightSettings() {} diff --git a/packages/stk/stk_unit_tests/stk_balance/UnitTestTransientFieldTransferById.cpp b/packages/stk/stk_unit_tests/stk_balance/UnitTestTransientFieldTransferById.cpp index 110691156c96..52b53a1d284a 100644 --- a/packages/stk/stk_unit_tests/stk_balance/UnitTestTransientFieldTransferById.cpp +++ b/packages/stk/stk_unit_tests/stk_balance/UnitTestTransientFieldTransferById.cpp @@ -254,11 +254,10 @@ void create_n_hex_mesh_with_transient_field(int numElems, const std::string& fil stk::io::set_field_role(field, Ioss::Field::TRANSIENT); - double initialValue = 0.0; std::ostringstream os; os << "generated:1x1x" << numElems; - stk::mesh::put_field_on_mesh(field, meta.universal_part(), 1, &initialValue); + stk::mesh::put_field_on_mesh(field, meta.universal_part(), 1, nullptr); stk::io::fill_mesh(os.str(), *bulk); stk::io::StkMeshIoBroker ioBroker; @@ -284,11 +283,10 @@ void create_n_hex_mesh_with_transient_field_and_global_data(int numElems, const stk::io::set_field_role(field, Ioss::Field::TRANSIENT); - double initialValue = 0.0; std::ostringstream os; os << "generated:1x1x" << numElems; - stk::mesh::put_field_on_mesh(field, meta.universal_part(), 1, &initialValue); + stk::mesh::put_field_on_mesh(field, meta.universal_part(), 1, nullptr); stk::io::fill_mesh(os.str(), *bulk); stk::io::StkMeshIoBroker ioBroker; diff --git a/packages/stk/stk_unit_tests/stk_io/UnitTestFieldNames.cpp b/packages/stk/stk_unit_tests/stk_io/UnitTestFieldNames.cpp index e599687a3339..8c24f0db78a2 100644 --- a/packages/stk/stk_unit_tests/stk_io/UnitTestFieldNames.cpp +++ b/packages/stk/stk_unit_tests/stk_io/UnitTestFieldNames.cpp @@ -63,8 +63,7 @@ void createNamedFieldOnMesh(stk::mesh::MetaData &stkMeshMetaData, const std::str { const int numberOfStates = 1; stk::mesh::Field &field0 = stkMeshMetaData.declare_field >(stk::topology::NODE_RANK, internalClientFieldName, numberOfStates); - stk::mesh::put_field_on_mesh(field0, stkMeshMetaData.universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(field0, stkMeshMetaData.universal_part(), nullptr); } void testFieldNamedCorrectly(Ioss::Region &ioRegion, MPI_Comm communicator, std::vector goldFieldNames) @@ -216,8 +215,7 @@ void createNamedFieldOnMesh(stk::mesh::MetaData &stkMeshMetaData, const std::str { const int numberOfStates = 1; stk::mesh::Field &field0 = stkMeshMetaData.declare_field(stk::topology::NODE_RANK, internalClientFieldName, numberOfStates); - stk::mesh::put_field_on_mesh(field0, stkMeshMetaData.universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(field0, stkMeshMetaData.universal_part(), nullptr); } void testFieldNamedCorrectly(Ioss::Region &ioRegion, MPI_Comm communicator, std::vector goldFieldNames) diff --git a/packages/stk/stk_unit_tests/stk_io/UnitTestFieldTypes.cpp b/packages/stk/stk_unit_tests/stk_io/UnitTestFieldTypes.cpp index 415e09a558aa..006427b08ee8 100644 --- a/packages/stk/stk_unit_tests/stk_io/UnitTestFieldTypes.cpp +++ b/packages/stk/stk_unit_tests/stk_io/UnitTestFieldTypes.cpp @@ -97,8 +97,7 @@ stk::io::FieldType setup_field_type(stk::mesh::MetaData& meta, const std::string const int numStates = 1; stk::mesh::EntityRank rank = stk::topology::NODE_RANK; stk::mesh::FieldBase& field = meta.declare_field>(rank, fieldName , numStates); - stk::mesh::put_field_on_mesh(field, meta.universal_part(), firstDimension, numCopies, - (typename stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(field, meta.universal_part(), firstDimension, numCopies, nullptr); const stk::mesh::FieldBase::Restriction &res = stk::mesh::find_restriction(field, rank, meta.universal_part()); EXPECT_EQ(int(firstDimension), res.dimension()); @@ -115,8 +114,7 @@ stk::io::FieldType setup_field_type(stk::mesh::MetaData& meta, const std::string const int numStates = 1; stk::mesh::EntityRank rank = stk::topology::NODE_RANK; stk::mesh::FieldBase& field = meta.declare_field>(rank, fieldName , numStates); - stk::mesh::put_field_on_mesh(field, meta.universal_part(), firstDimension, numCopies, - (typename stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(field, meta.universal_part(), firstDimension, numCopies, nullptr); const stk::mesh::FieldBase::Restriction &res = stk::mesh::find_restriction(field, rank, meta.universal_part()); EXPECT_EQ(int(firstDimension), res.dimension()); @@ -861,8 +859,7 @@ stk::mesh::FieldBase & create_stk_field(stk::mesh::MetaData & meta, const FieldC const int numStates = 1; stk::mesh::EntityRank rank = stk::topology::NODE_RANK; stk::mesh::FieldBase& field = meta.declare_field(rank, fieldConfig.fieldName, numStates); - stk::mesh::put_field_on_mesh(field, meta.universal_part(), fieldConfig.firstDimension, fieldConfig.numCopies, - (typename stk::mesh::FieldTraits>::data_type*)nullptr); + stk::mesh::put_field_on_mesh(field, meta.universal_part(), fieldConfig.firstDimension, fieldConfig.numCopies, nullptr); if (fieldConfig.storageName != unspecified) { stk::io::set_field_output_type(field, fieldConfig.storageName); diff --git a/packages/stk/stk_unit_tests/stk_io/UnitTestGlobalVariables.cpp b/packages/stk/stk_unit_tests/stk_io/UnitTestGlobalVariables.cpp index a620c690ba61..a40bfcd4634e 100644 --- a/packages/stk/stk_unit_tests/stk_io/UnitTestGlobalVariables.cpp +++ b/packages/stk/stk_unit_tests/stk_io/UnitTestGlobalVariables.cpp @@ -357,8 +357,7 @@ stk::mesh::Field &createNodalTestField(stk::mesh::MetaData &stkMeshMetaD { const int numberOfStates = 1; stk::mesh::Field &field0 = stkMeshMetaData.declare_field >(stk::topology::NODE_RANK, fieldName, numberOfStates); - stk::mesh::put_field_on_mesh(field0, stkMeshMetaData.universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(field0, stkMeshMetaData.universal_part(), nullptr); return field0; } void putDataOnTestField(stk::mesh::BulkData &stkMeshBulkData, stk::mesh::Field &field0, std::vector &nodalFieldValues) @@ -845,8 +844,7 @@ stk::mesh::Field &createNodalTestField(stk::mesh::MetaData &stkMeshMetaD { const int numberOfStates = 1; stk::mesh::Field &field0 = stkMeshMetaData.declare_field(stk::topology::NODE_RANK, fieldName, numberOfStates); - stk::mesh::put_field_on_mesh(field0, stkMeshMetaData.universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(field0, stkMeshMetaData.universal_part(), nullptr); return field0; } void putDataOnTestField(stk::mesh::BulkData &stkMeshBulkData, stk::mesh::Field &field0, std::vector &nodalFieldValues) diff --git a/packages/stk/stk_unit_tests/stk_io/UnitTestInvalidCallOrdering.cpp b/packages/stk/stk_unit_tests/stk_io/UnitTestInvalidCallOrdering.cpp index bcfef8f061f0..a7743aa72218 100644 --- a/packages/stk/stk_unit_tests/stk_io/UnitTestInvalidCallOrdering.cpp +++ b/packages/stk/stk_unit_tests/stk_io/UnitTestInvalidCallOrdering.cpp @@ -62,8 +62,7 @@ TEST(StkMeshIoBroker, CheckInvalidCallOrdering_legacy) stk::mesh::MetaData &stkMeshMetaData = stkIo.meta_data(); stk::mesh::Field &field0 = stkMeshMetaData.declare_field >(stk::topology::NODE_RANK, "displacement", 1); - stk::mesh::put_field_on_mesh(field0, stkMeshMetaData.universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(field0, stkMeshMetaData.universal_part(), nullptr); stkIo.populate_bulk_data(); { @@ -130,8 +129,7 @@ TEST(StkMeshIoBroker, CheckInvalidCallOrdering) stk::mesh::MetaData &stkMeshMetaData = stkIo.meta_data(); stk::mesh::Field &field0 = stkMeshMetaData.declare_field(stk::topology::NODE_RANK, "displacement", 1); - stk::mesh::put_field_on_mesh(field0, stkMeshMetaData.universal_part(), - (stk::mesh::FieldTraits>::data_type*) nullptr); + stk::mesh::put_field_on_mesh(field0, stkMeshMetaData.universal_part(), nullptr); stkIo.populate_bulk_data(); { diff --git a/packages/stk/stk_unit_tests/stk_io/UnitTestReadNodesets.cpp b/packages/stk/stk_unit_tests/stk_io/UnitTestReadNodesets.cpp index bbde46136492..ecfce7afb2bd 100644 --- a/packages/stk/stk_unit_tests/stk_io/UnitTestReadNodesets.cpp +++ b/packages/stk/stk_unit_tests/stk_io/UnitTestReadNodesets.cpp @@ -77,10 +77,10 @@ void create_one_element_mesh_with_nodeset(stk::mesh::BulkData& bulk, const std:: stk::io::put_io_part_attribute(*nodesetPart); stk::mesh::Field & coordsField = meta.declare_field>(stk::topology::NODE_RANK, "coordinates", 1); - stk::mesh::put_field_on_mesh(coordsField, meta.universal_part(), spatialDim, static_cast(nullptr)); + stk::mesh::put_field_on_mesh(coordsField, meta.universal_part(), spatialDim, nullptr); stk::mesh::Field & nodeSetField = meta.declare_field>(stk::topology::NODE_RANK, "nodeSetField", 1); - stk::mesh::put_field_on_mesh(nodeSetField, *nodesetPart, 1, static_cast(nullptr)); + stk::mesh::put_field_on_mesh(nodeSetField, *nodesetPart, 1, nullptr); meta.commit(); @@ -236,7 +236,7 @@ TEST(StkMeshIoBroker, readSubsetFieldData_legacy) { stk::mesh::FieldBase* nodeSetField = meta.get_field(stk::topology::NODE_RANK, nodeSetString); stk::mesh::Part* nodesetPart = meta.get_part("nodelist_1"); - stk::mesh::put_field_on_mesh(*nodeSetField, *nodesetPart, 1, static_cast(nullptr)); + stk::mesh::put_field_on_mesh(*nodeSetField, *nodesetPart, 1, nullptr); stk::io::MeshField meshField(nodeSetField, nodeSetString); meshField.add_subset(*nodesetPart); @@ -257,7 +257,7 @@ TEST(StkMeshIoBroker, readFieldDataOnUniversalSetButNotDefinedOnSubset_legacy) { setup_field_data(inputFile, nodeSetString, *bulk); stk::mesh::FieldBase* nodeSetField = meta.get_field(stk::topology::NODE_RANK, nodeSetString); - stk::mesh::put_field_on_mesh(*nodeSetField, meta.universal_part(), 1, static_cast(nullptr)); + stk::mesh::put_field_on_mesh(*nodeSetField, meta.universal_part(), 1, nullptr); stk::io::MeshField meshField(nodeSetField, nodeSetString); @@ -278,7 +278,7 @@ TEST(StkMeshIoBroker, readFieldDataOnUniversalSetAndDefinedOnSubset_legacy) { stk::mesh::FieldBase* nodeSetField = meta.get_field(stk::topology::NODE_RANK, nodeSetString); stk::mesh::Part* nodesetPart = meta.get_part("nodelist_1"); - stk::mesh::put_field_on_mesh(*nodeSetField, meta.universal_part(), 1, static_cast(nullptr)); + stk::mesh::put_field_on_mesh(*nodeSetField, meta.universal_part(), 1, nullptr); stk::io::MeshField meshField(nodeSetField, nodeSetString); meshField.add_subset(*nodesetPart); @@ -303,10 +303,10 @@ void create_one_element_mesh_with_nodeset(stk::mesh::BulkData& bulk, const std:: stk::io::put_io_part_attribute(*nodesetPart); stk::mesh::Field & coordsField = meta.declare_field(stk::topology::NODE_RANK, "coordinates", 1); - stk::mesh::put_field_on_mesh(coordsField, meta.universal_part(), spatialDim, static_cast(nullptr)); + stk::mesh::put_field_on_mesh(coordsField, meta.universal_part(), spatialDim, nullptr); stk::mesh::Field & nodeSetField = meta.declare_field(stk::topology::NODE_RANK, "nodeSetField", 1); - stk::mesh::put_field_on_mesh(nodeSetField, *nodesetPart, 1, static_cast(nullptr)); + stk::mesh::put_field_on_mesh(nodeSetField, *nodesetPart, 1, nullptr); meta.commit(); @@ -462,7 +462,7 @@ TEST(StkMeshIoBroker, readSubsetFieldData) { stk::mesh::FieldBase* nodeSetField = meta.get_field(stk::topology::NODE_RANK, nodeSetString); stk::mesh::Part* nodesetPart = meta.get_part("nodelist_1"); - stk::mesh::put_field_on_mesh(*nodeSetField, *nodesetPart, 1, static_cast(nullptr)); + stk::mesh::put_field_on_mesh(*nodeSetField, *nodesetPart, 1, nullptr); stk::io::MeshField meshField(nodeSetField, nodeSetString); meshField.add_subset(*nodesetPart); @@ -483,7 +483,7 @@ TEST(StkMeshIoBroker, readFieldDataOnUniversalSetButNotDefinedOnSubset) { setup_field_data(inputFile, nodeSetString, *bulk); stk::mesh::FieldBase* nodeSetField = meta.get_field(stk::topology::NODE_RANK, nodeSetString); - stk::mesh::put_field_on_mesh(*nodeSetField, meta.universal_part(), 1, static_cast(nullptr)); + stk::mesh::put_field_on_mesh(*nodeSetField, meta.universal_part(), 1, nullptr); stk::io::MeshField meshField(nodeSetField, nodeSetString); @@ -504,7 +504,7 @@ TEST(StkMeshIoBroker, readFieldDataOnUniversalSetAndDefinedOnSubset) { stk::mesh::FieldBase* nodeSetField = meta.get_field(stk::topology::NODE_RANK, nodeSetString); stk::mesh::Part* nodesetPart = meta.get_part("nodelist_1"); - stk::mesh::put_field_on_mesh(*nodeSetField, meta.universal_part(), 1, static_cast(nullptr)); + stk::mesh::put_field_on_mesh(*nodeSetField, meta.universal_part(), 1, nullptr); stk::io::MeshField meshField(nodeSetField, nodeSetString); meshField.add_subset(*nodesetPart); diff --git a/packages/stk/stk_unit_tests/stk_io/UnitTestReadWriteSideSets.cpp b/packages/stk/stk_unit_tests/stk_io/UnitTestReadWriteSideSets.cpp index 5998783207f5..ad0d7f207b29 100644 --- a/packages/stk/stk_unit_tests/stk_io/UnitTestReadWriteSideSets.cpp +++ b/packages/stk/stk_unit_tests/stk_io/UnitTestReadWriteSideSets.cpp @@ -210,9 +210,9 @@ class StkIoSideset_legacy : public IOMeshFixture coordField = &get_meta().declare_field(stk::topology::NODE_RANK, "coordinates"); get_meta().set_coordinate_field(coordField); ssField = &get_meta().declare_field(stk::topology::FACE_RANK, "ssfield"); - stk::mesh::put_field_on_mesh(*coordField, get_meta().universal_part(), 3, static_cast(nullptr)); - stk::mesh::put_field_on_mesh(*ssField, *sideBlock1, 4, static_cast(nullptr)); - stk::mesh::put_field_on_mesh(*ssField, *sideBlock2, 3, static_cast(nullptr)); + stk::mesh::put_field_on_mesh(*coordField, get_meta().universal_part(), 3, nullptr); + stk::mesh::put_field_on_mesh(*ssField, *sideBlock1, 4, nullptr); + stk::mesh::put_field_on_mesh(*ssField, *sideBlock2, 3, nullptr); } void create_hex_with_face() @@ -889,9 +889,9 @@ class StkIoSideset : public stk::io::unit_test::simple_fields::IOMeshFixture coordField = &get_meta().declare_field(stk::topology::NODE_RANK, "coordinates"); get_meta().set_coordinate_field(coordField); ssField = &get_meta().declare_field(stk::topology::FACE_RANK, "ssfield"); - stk::mesh::put_field_on_mesh(*coordField, get_meta().universal_part(), 3, static_cast(nullptr)); - stk::mesh::put_field_on_mesh(*ssField, *sideBlock1, 4, static_cast(nullptr)); - stk::mesh::put_field_on_mesh(*ssField, *sideBlock2, 3, static_cast(nullptr)); + stk::mesh::put_field_on_mesh(*coordField, get_meta().universal_part(), 3, nullptr); + stk::mesh::put_field_on_mesh(*ssField, *sideBlock1, 4, nullptr); + stk::mesh::put_field_on_mesh(*ssField, *sideBlock2, 3, nullptr); } void create_hex_with_face() diff --git a/packages/stk/stk_unit_tests/stk_io/UnitTestWriteSTKMesh.cpp b/packages/stk/stk_unit_tests/stk_io/UnitTestWriteSTKMesh.cpp index f72798df49d4..d0b9b2bc757e 100644 --- a/packages/stk/stk_unit_tests/stk_io/UnitTestWriteSTKMesh.cpp +++ b/packages/stk/stk_unit_tests/stk_io/UnitTestWriteSTKMesh.cpp @@ -227,8 +227,7 @@ class StkIoResultsOutput_legacy : public stk::unit_test_util::MeshFixture setup_empty_mesh(auraOption, bucketCapacity); stk::mesh::Field & field = get_meta().declare_field>(stk::topology::NODE_RANK, "nodal_field"); - const int initValue = 0; - stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), &initValue); + stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), nullptr); stk::io::fill_mesh(meshSpec, get_bulk()); } @@ -241,8 +240,7 @@ class StkIoResultsOutput_legacy : public stk::unit_test_util::MeshFixture stk::io::put_io_part_attribute(surface_part); stk::mesh::Field & field = get_meta().declare_field>(stk::topology::NODE_RANK, "nodal_field"); - const int initValue = 0; - stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), &initValue); + stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), nullptr); stk::io::fill_mesh(meshSpec, get_bulk()); @@ -540,8 +538,7 @@ class StkIoResultsOutput : public stk::unit_test_util::simple_fields::MeshFixtur setup_empty_mesh(auraOption, bucketCapacity); stk::mesh::Field & field = get_meta().declare_field(stk::topology::NODE_RANK, "nodal_field"); - const int initValue = 0; - stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), &initValue); + stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), nullptr); stk::io::fill_mesh(meshSpec, get_bulk()); } @@ -554,8 +551,7 @@ class StkIoResultsOutput : public stk::unit_test_util::simple_fields::MeshFixtur stk::io::put_io_part_attribute(surface_part); stk::mesh::Field & field = get_meta().declare_field(stk::topology::NODE_RANK, "nodal_field"); - const int initValue = 0; - stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), &initValue); + stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), nullptr); stk::io::fill_mesh(meshSpec, get_bulk()); diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestBucket.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestBucket.cpp index 3da34017bc21..46248b801cce 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestBucket.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestBucket.cpp @@ -106,8 +106,8 @@ TEST(UnitTestingOfBucket, testBucket) ScalarFieldType & temperature = meta.declare_field(stk::topology::NODE_RANK, "temperature", number_of_states); ScalarFieldType & volume = meta.declare_field(stk::topology::ELEMENT_RANK, "volume", number_of_states); Part & universal = meta.universal_part (); - put_field_on_mesh ( temperature , universal , (stk::mesh::FieldTraits::data_type*) nullptr); - put_field_on_mesh ( volume , universal , (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh ( temperature , universal , nullptr); + put_field_on_mesh ( volume , universal , nullptr); meta.commit(); // Generate the mesh diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestBulkData.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestBulkData.cpp index 0a2904c9b87c..ca388144ff60 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestBulkData.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestBulkData.cpp @@ -2206,8 +2206,7 @@ TEST(BulkData, testFieldComm) BoxFixture fixture(pm, stk::mesh::BulkData::AUTO_AURA, 100); PressureFieldType& p_field = fixture.fem_meta().declare_field(stk::topology::NODE_RANK, "p"); - stk::mesh::put_field_on_mesh(p_field, fixture.fem_meta().universal_part(), - (stk::mesh::FieldTraits::data_type*) nullptr); + stk::mesh::put_field_on_mesh(p_field, fixture.fem_meta().universal_part(), nullptr); fixture.fem_meta().commit(); BulkData & bulk = fixture.bulk_data(); int local_box[3][2] = { {0, 0}, {0, 0}, {0, 0}}; @@ -2235,8 +2234,7 @@ TEST(BulkData, testFieldComm) { stk::mesh::fixtures::simple_fields::QuadFixture fixture(pm, 2 /*nx*/, 2 /*ny*/); PressureFieldType& p_field = fixture.m_meta.declare_field(stk::topology::NODE_RANK, "p"); - stk::mesh::put_field_on_mesh(p_field, fixture.m_meta.universal_part(), - (stk::mesh::FieldTraits::data_type*) nullptr); + stk::mesh::put_field_on_mesh(p_field, fixture.m_meta.universal_part(), nullptr); fixture.m_meta.commit(); fixture.generate_mesh(); stk::mesh::BulkData & bulk = fixture.m_bulk_data; @@ -4431,8 +4429,7 @@ TEST(BulkData, can_we_create_shared_nodes) stk::mesh::Selector all_nodes = meta.universal_part(); typedef stk::mesh::Field CoordFieldType; CoordFieldType& coordField = meta.declare_field(stk::topology::NODE_RANK, "model_coordinates"); - stk::mesh::put_field_on_mesh(coordField, all_nodes, 3, - (stk::mesh::FieldTraits::data_type*) nullptr); + stk::mesh::put_field_on_mesh(coordField, all_nodes, 3, nullptr); stk::mesh::Part& elem_part = meta.declare_part_with_topology("block_1", stk::topology::BEAM_2); stk::io::put_io_part_attribute(elem_part); @@ -5298,11 +5295,9 @@ void Test_STK_ParallelPartConsistency_ChangeBlock(stk::mesh::BulkData::Automatic //declare a field for coordinates typedef stk::mesh::Field CoordFieldType; CoordFieldType& coordField = meta.declare_field(stk::topology::NODE_RANK, "model_coordinates"); - stk::mesh::put_field_on_mesh(coordField, all_nodes, 2, - (stk::mesh::FieldTraits::data_type*) nullptr); + stk::mesh::put_field_on_mesh(coordField, all_nodes, 2, nullptr); stk::mesh::Field& oneField = meta.declare_field(stk::topology::NODE_RANK, "field_of_one"); - stk::mesh::put_field_on_mesh(oneField, block_1, - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(oneField, block_1, nullptr); meta.commit(); mesh.modification_begin(); diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestCEO4ElemEdge.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestCEO4ElemEdge.cpp index 652e73e2cd51..84c73e6dc9c1 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestCEO4ElemEdge.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestCEO4ElemEdge.cpp @@ -505,8 +505,7 @@ void fillMeshfor4Elem4ProcEdgeAndTest(stk::unit_test_util::BulkDataTester &mesh, Part* elem_block = &meta_data.declare_part("elem_block", stk::topology::ELEMENT_RANK); typedef stk::mesh::Field rank_zero_field; rank_zero_field & f0 = meta_data.declare_field( NODE_RANK, "elem_field" ); - stk::mesh::put_field_on_mesh( f0 , *elem_block , - (stk::mesh::FieldTraits::data_type*) nullptr); + stk::mesh::put_field_on_mesh( f0 , *elem_block , nullptr); meta_data.commit(); // Begin modification cycle so we can create the entities and relations diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestChangeEntityId.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestChangeEntityId.cpp index c366f95b9ce4..f7e5a051e0df 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestChangeEntityId.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestChangeEntityId.cpp @@ -134,7 +134,7 @@ TEST( UnitTestChangeEntityId, change_id_large ) Field & simple_nodal_field = hf.m_meta.declare_field(stk::topology::NODE_RANK, "simple_nodal_field"); - put_field_on_mesh(simple_nodal_field, *hf.m_elem_parts[0], (stk::mesh::FieldTraits >::data_type*) nullptr); + put_field_on_mesh(simple_nodal_field, *hf.m_elem_parts[0], nullptr); //create nodal field on hex topo diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestChangeEntityOwnerCommMaps.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestChangeEntityOwnerCommMaps.cpp index e7e948ed7b71..71c16b5fc291 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestChangeEntityOwnerCommMaps.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestChangeEntityOwnerCommMaps.cpp @@ -116,8 +116,7 @@ class FieldMgr stk::mesh::Field &field = m_stkMeshMetaData.declare_field(stk::topology::NODE_RANK, m_commListNodeFieldName, 1); m_commListNodeField = &field; - stk::mesh::put_field_on_mesh(*m_commListNodeField, m_stkMeshMetaData.universal_part(), - (stk::mesh::FieldTraits>::data_type*) nullptr); + stk::mesh::put_field_on_mesh(*m_commListNodeField, m_stkMeshMetaData.universal_part(), nullptr); } void addSharingCommMapNodeField() @@ -125,8 +124,7 @@ class FieldMgr stk::mesh::Field &field = m_stkMeshMetaData.declare_field(stk::topology::NODE_RANK, m_sharingCommMapNodeFieldName, 1); m_sharingCommMapNodeField = &field; - stk::mesh::put_field_on_mesh(*m_sharingCommMapNodeField, m_stkMeshMetaData.universal_part(), - (stk::mesh::FieldTraits>::data_type*) nullptr); + stk::mesh::put_field_on_mesh(*m_sharingCommMapNodeField, m_stkMeshMetaData.universal_part(), nullptr); } void addAuraCommMapNodeField() @@ -134,8 +132,7 @@ class FieldMgr stk::mesh::Field &field = m_stkMeshMetaData.declare_field(stk::topology::NODE_RANK, m_auraCommMapNodeFieldName, 1); m_auraCommMapNodeField = &field; - stk::mesh::put_field_on_mesh(*m_auraCommMapNodeField, m_stkMeshMetaData.universal_part(), - (stk::mesh::FieldTraits>::data_type*) nullptr); + stk::mesh::put_field_on_mesh(*m_auraCommMapNodeField, m_stkMeshMetaData.universal_part(), nullptr); } void addAuraCommMapElementField() @@ -143,8 +140,7 @@ class FieldMgr stk::mesh::Field &field = m_stkMeshMetaData.declare_field(stk::topology::ELEMENT_RANK, m_auraCommMapElementFieldName, 1); m_auraCommMapElementField = &field; - stk::mesh::put_field_on_mesh(*m_auraCommMapElementField, m_stkMeshMetaData.universal_part(), - (stk::mesh::FieldTraits>::data_type*) nullptr); + stk::mesh::put_field_on_mesh(*m_auraCommMapElementField, m_stkMeshMetaData.universal_part(), nullptr); } stk::mesh::Field * getCommListNodeField() { return m_commListNodeField; } diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestChangeParts.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestChangeParts.cpp index 2daf120f9632..7bf2067b43c0 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestChangeParts.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestChangeParts.cpp @@ -162,7 +162,7 @@ TEST(UnitTestChangeParts, test_superset_and_subset_part_change) metaData.declare_part_subset(supersetPart, subsetPart2); stk::mesh::FieldBase &field = metaData.declare_field(stk::topology::NODE_RANK, "sam"); - stk::mesh::put_field_on_mesh(field, supersetPart, (stk::mesh::FieldTraits>::data_type*) nullptr); + stk::mesh::put_field_on_mesh(field, supersetPart, nullptr); std::string meshDesc = "0,1,HEX_8,1,2,3,4,5,6,7,8"; stk::unit_test_util::simple_fields::setup_text_mesh(bulkData, meshDesc); diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestCommunicateFieldData.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestCommunicateFieldData.cpp index b5b0a779e5a6..3c57b758d93f 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestCommunicateFieldData.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestCommunicateFieldData.cpp @@ -70,9 +70,7 @@ TEST(CommunicateFieldData, communicate) stk::mesh::BulkData& bulk = *bulkPtr; stk::mesh::Field& field = meta.declare_field(stk::topology::NODE_RANK, "field1"); - stk::mesh::put_field_on_mesh(field, meta.universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); - + stk::mesh::put_field_on_mesh(field, meta.universal_part(), nullptr); stk::mesh::unit_test::setupKeyholeMesh2D_case1(bulk); @@ -126,8 +124,7 @@ TEST(CommunicateFieldData, communicateMultipleGhostings) stk::mesh::BulkData& bulk = *bulkPtr; stk::mesh::Field& field = meta.declare_field(stk::topology::NODE_RANK, "field1"); - stk::mesh::put_field_on_mesh(field, meta.universal_part(), - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(field, meta.universal_part(), nullptr); stk::mesh::unit_test::setupKeyholeMesh2D_case2(bulk); diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestCreateFaces.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestCreateFaces.cpp index 9d763b336300..e80bc09ebb34 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestCreateFaces.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestCreateFaces.cpp @@ -526,8 +526,7 @@ void heterogeneous_create_faces_test(stk::mesh::BulkData::AutomaticAuraOption au stk::mesh::BulkData& bulk_data = *bulkPtr; stk::mesh::fixtures::simple_fields::VectorFieldType & node_coord = meta_data.declare_field(stk::topology::NODE_RANK, "coordinates"); - stk::mesh::put_field_on_mesh( node_coord , meta_data.universal_part() , 3, - (stk::mesh::FieldTraits::data_type*) nullptr); + stk::mesh::put_field_on_mesh( node_coord , meta_data.universal_part() , 3, nullptr); stk::mesh::fixtures::simple_fields::heterogeneous_mesh_meta_data( meta_data , node_coord ); meta_data.commit(); @@ -620,8 +619,7 @@ TEST ( UnitTestCreateFaces, Degenerate ) stk::mesh::BulkData& bulk_data = *bulkPtr; stk::mesh::fixtures::simple_fields::VectorFieldType & node_coord = meta_data.declare_field(stk::topology::NODE_RANK, "coordinates"); - stk::mesh::put_field_on_mesh( node_coord , meta_data.universal_part() , 3, - (stk::mesh::FieldTraits::data_type*) nullptr); + stk::mesh::put_field_on_mesh( node_coord , meta_data.universal_part() , 3, nullptr); stk::mesh::fixtures::simple_fields::degenerate_mesh_meta_data( meta_data , node_coord ); meta_data.commit(); diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestField.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestField.cpp index a1db899b252c..3cd90c738ca5 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestField.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestField.cpp @@ -117,12 +117,12 @@ TEST(UnitTestField, testFieldMaxSize) stk::mesh::Part & p4 = meta_data.declare_part("P4", NODE_RANK ); stk::mesh::Part & p5 = meta_data.declare_part("P5", NODE_RANK ); - stk::mesh::put_field_on_mesh( f0, p0, (stk::mesh::FieldTraits::data_type*) nullptr); - stk::mesh::put_field_on_mesh( f1, p1, 10, (stk::mesh::FieldTraits::data_type*) nullptr); - stk::mesh::put_field_on_mesh( f2, p2, 10, 20, (stk::mesh::FieldTraits::data_type*) nullptr); - stk::mesh::put_field_on_mesh( f3, p3, 10, 20, 30, (stk::mesh::FieldTraits::data_type*) nullptr); - stk::mesh::put_field_on_mesh( f4, p4, 10, 20, 30, 40, (stk::mesh::FieldTraits::data_type*) nullptr); - stk::mesh::put_field_on_mesh( f5, p5, 10, 20, 30, 40, 50, (stk::mesh::FieldTraits::data_type*) nullptr); + stk::mesh::put_field_on_mesh( f0, p0, nullptr); + stk::mesh::put_field_on_mesh( f1, p1, 10, nullptr); + stk::mesh::put_field_on_mesh( f2, p2, 10, 20, nullptr); + stk::mesh::put_field_on_mesh( f3, p3, 10, 20, 30, nullptr); + stk::mesh::put_field_on_mesh( f4, p4, 10, 20, 30, 40, nullptr); + stk::mesh::put_field_on_mesh( f5, p5, 10, 20, 30, 40, 50, nullptr); meta_data.commit(); @@ -167,8 +167,7 @@ TEST(UnitTestField, fieldDataAccess_rankMustMatch) using MyField = stk::mesh::Field; MyField& nodalField = meta.declare_field(NODE_RANK, "nodal_field"); - stk::mesh::FieldTraits::data_type* initialValue = nullptr; - stk::mesh::put_field_on_mesh(nodalField, meta.universal_part(), initialValue); + stk::mesh::put_field_on_mesh(nodalField, meta.universal_part(), nullptr); stk::io::fill_mesh("generated:2x2x2|sideset:xXyYzZ", bulk); @@ -209,7 +208,7 @@ TEST(UnitTestField, testFieldWithSelector) stk::mesh::Selector select_p0 = p0; std::cout <<"select_p0: "<< select_p0 << std::endl; - stk::mesh::put_field_on_mesh( f0 , select_p0 , (stk::mesh::FieldTraits::data_type*) nullptr); + stk::mesh::put_field_on_mesh( f0 , select_p0 , nullptr); stk::mesh::print( oss , " " , f0 ); @@ -276,8 +275,8 @@ TEST(UnitTestField, testFieldWithSelectorAnd) std::cout <<"elem_hex_selector: "<< elem_hex_selector << std::endl; std::cout <<"elem_tet_selector: "<< elem_tet_selector << std::endl; - stk::mesh::put_field_on_mesh( f0 , elem_hex_selector, 8u , (stk::mesh::FieldTraits::data_type*) nullptr); - stk::mesh::put_field_on_mesh( f0 , elem_tet_selector, 4u , (stk::mesh::FieldTraits::data_type*) nullptr); + stk::mesh::put_field_on_mesh( f0 , elem_hex_selector, 8u , nullptr); + stk::mesh::put_field_on_mesh( f0 , elem_tet_selector, 4u , nullptr); stk::mesh::print( oss , " " , f0 ); @@ -348,12 +347,12 @@ TEST(UnitTestField, testFieldWithSelectorInvalid) std::cout <<"elem_hexA_selector: "<< elem_hexA_selector << std::endl; std::cout <<"elem_hexB_selector: "<< elem_hexB_selector << std::endl; - stk::mesh::put_field_on_mesh( f0 , elem_hexA_selector, 8u , (stk::mesh::FieldTraits::data_type*) nullptr); + stk::mesh::put_field_on_mesh( f0 , elem_hexA_selector, 8u , nullptr); ASSERT_THROW( - stk::mesh::put_field_on_mesh( f0 , elem_hexA_selector, 4u , (stk::mesh::FieldTraits::data_type*) nullptr), + stk::mesh::put_field_on_mesh( f0 , elem_hexA_selector, 4u , nullptr), std::runtime_error ); - stk::mesh::put_field_on_mesh( f0 , elem_hexB_selector, 4u , (stk::mesh::FieldTraits::data_type*) nullptr); + stk::mesh::put_field_on_mesh( f0 , elem_hexB_selector, 4u , nullptr); stk::mesh::print( oss , " " , f0 ); @@ -774,7 +773,7 @@ class LateFieldFixture : public LateFieldFixtureNoTest, public ::ngp_testing::Te builder.set_field_data_manager(fieldDataManager); bulkData = builder.create(); - metaData = &(bulkData->mesh_meta_data()); + metaData = bulkData->mesh_meta_data_ptr(); } void setup_empty_mesh_with_field_data_manager(stk::mesh::BulkData::AutomaticAuraOption auraOption, stk::mesh::FieldDataManager * fieldDataManager) @@ -1133,7 +1132,7 @@ TEST_F(LateFieldFixture, disable_late_fields) get_meta().disable_late_fields(); stk::mesh::Field& f = declare_field("another_late_field", stk::topology::ELEM_RANK); - EXPECT_ANY_THROW(stk::mesh::put_field_on_mesh(f, get_meta().universal_part(), static_cast(nullptr))); + EXPECT_ANY_THROW(stk::mesh::put_field_on_mesh(f, get_meta().universal_part(), nullptr)); } TEST_F(LateFieldFixture, addLateIntNodalField_multipleBuckets) diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestFieldParallel.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestFieldParallel.cpp index 5b625071ce5b..ec68d28e06dc 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestFieldParallel.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestFieldParallel.cpp @@ -139,20 +139,13 @@ void do_parallel_assemble() Part& center_part = meta.declare_part("center_part", stk::topology::NODE_RANK); - put_field_on_mesh(universal_scalar_node_field, meta.universal_part(), - (stk::mesh::FieldTraits::data_type*) nullptr); - put_field_on_mesh(universal_cartesian_node_field, meta.universal_part(), 3, - (stk::mesh::FieldTraits::data_type*) nullptr); - put_field_on_mesh(universal_scalar_int_node_field, meta.universal_part(), - (stk::mesh::FieldTraits::data_type*) nullptr); - put_field_on_mesh(universal_scalar_edge_field, meta.universal_part(), - (stk::mesh::FieldTraits::data_type*) nullptr); - put_field_on_mesh(non_universal_scalar_node_field, center_part, - (stk::mesh::FieldTraits::data_type*) nullptr); - put_field_on_mesh(universal_scalar_long_double_node_field, meta.universal_part(), - (stk::mesh::FieldTraits::data_type*) nullptr); - put_field_on_mesh(universal_scalar_id_node_field, meta.universal_part(), - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(universal_scalar_node_field, meta.universal_part(), nullptr); + put_field_on_mesh(universal_cartesian_node_field, meta.universal_part(), 3, nullptr); + put_field_on_mesh(universal_scalar_int_node_field, meta.universal_part(), nullptr); + put_field_on_mesh(universal_scalar_edge_field, meta.universal_part(), nullptr); + put_field_on_mesh(non_universal_scalar_node_field, center_part, nullptr); + put_field_on_mesh(universal_scalar_long_double_node_field, meta.universal_part(), nullptr); + put_field_on_mesh(universal_scalar_id_node_field, meta.universal_part(), nullptr); // TODO - Need a field that gets shared between more than 2 procs. @@ -378,16 +371,11 @@ void do_parallel_assemble_including_ghosts() Part& center_part = meta.declare_part("center_part", stk::topology::NODE_RANK); - put_field_on_mesh(universal_scalar_node_field, meta.universal_part(), - (stk::mesh::FieldTraits::data_type*) nullptr); - put_field_on_mesh(universal_cartesian_node_field, meta.universal_part(), 3, - (stk::mesh::FieldTraits::data_type*) nullptr); - put_field_on_mesh(universal_scalar_int_node_field, meta.universal_part(), - (stk::mesh::FieldTraits::data_type*) nullptr); - put_field_on_mesh(non_universal_scalar_node_field, center_part, - (stk::mesh::FieldTraits::data_type*) nullptr); - put_field_on_mesh(universal_scalar_id_node_field, meta.universal_part(), - (stk::mesh::FieldTraits::data_type*) nullptr); + put_field_on_mesh(universal_scalar_node_field, meta.universal_part(), nullptr); + put_field_on_mesh(universal_cartesian_node_field, meta.universal_part(), 3, nullptr); + put_field_on_mesh(universal_scalar_int_node_field, meta.universal_part(), nullptr); + put_field_on_mesh(non_universal_scalar_node_field, center_part, nullptr); + put_field_on_mesh(universal_scalar_id_node_field, meta.universal_part(), nullptr); meta.commit(); diff --git a/packages/stk/stk_unit_tests/stk_mesh/UnitTestSideSet.cpp b/packages/stk/stk_unit_tests/stk_mesh/UnitTestSideSet.cpp index 9d0aaa1d28ff..ebb07b70cd30 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/UnitTestSideSet.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/UnitTestSideSet.cpp @@ -1066,8 +1066,6 @@ TEST_F(InternalSideSet, maintainSingleSidedAfterParallelCreationOnProcessorBound { if(stk::parallel_machine_size(MPI_COMM_WORLD) == 2) { - setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); - stk::mesh::EntityId elemId = 1; stk::mesh::ConnectivityOrdinal ordinal = 5; stk::mesh::EntityId faceId = 16; @@ -1080,8 +1078,6 @@ TEST_F(InternalSideSet, maintainSingleSidedAfterParallelCreationOnProcessorBound { if(stk::parallel_machine_size(MPI_COMM_WORLD) == 2) { - setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); - stk::mesh::EntityId elemId = 2; stk::mesh::ConnectivityOrdinal ordinal = 4; stk::mesh::EntityId faceId = 16; diff --git a/packages/stk/stk_unit_tests/stk_mesh/face_creation/TwoHexesTwoProcs.cpp b/packages/stk/stk_unit_tests/stk_mesh/face_creation/TwoHexesTwoProcs.cpp index 6478f0a7561a..04900ac5ec03 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/face_creation/TwoHexesTwoProcs.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/face_creation/TwoHexesTwoProcs.cpp @@ -17,14 +17,20 @@ class FaceCreatorUsingBulkDataFaceSharingTester : public FaceCreatorFixture ~FaceCreatorUsingBulkDataFaceSharingTester() { bulkData.reset(); - delete metaData; + metaData.reset(); } virtual void allocate_bulk(stk::mesh::BulkData::AutomaticAuraOption auraOption, unsigned bucketCapacity = stk::mesh::impl::BucketRepository::default_bucket_capacity) { ThrowRequireMsg(bucketCapacity == stk::mesh::impl::BucketRepository::default_bucket_capacity, "allocate_bulk: BulkDataFaceSharingTester doesn't recognize non-default bucket-capacity"); - metaData = new stk::mesh::MetaData(m_spatialDim, m_entityRankNames); + + metaData = stk::mesh::MeshBuilder(communicator) + .set_spatial_dimension(m_spatialDim) + .set_entity_rank_names(m_entityRankNames) + .set_aura_option(auraOption) + .set_bucket_capacity(bucketCapacity).create_meta_data(); + set_bulk(std::make_shared(get_meta(), get_comm(), auraOption)); } diff --git a/packages/stk/stk_unit_tests/stk_mesh/face_creation/element_graph/UnitTestElemElemGraph.cpp b/packages/stk/stk_unit_tests/stk_mesh/face_creation/element_graph/UnitTestElemElemGraph.cpp index 9dfd67bcaf52..d43e9c863c50 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/face_creation/element_graph/UnitTestElemElemGraph.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/face_creation/element_graph/UnitTestElemElemGraph.cpp @@ -1532,8 +1532,7 @@ class ElementDeathRestartTest metaData->use_simple_fields(); stk::io::put_io_part_attribute(metaData->universal_part()); deathStatusField = &metaData->declare_field(stk::topology::ELEM_RANK,deathStatusFieldName); - double zeroInitialValue = 0.0; - stk::mesh::put_field_on_mesh(*deathStatusField,metaData->universal_part(),&zeroInitialValue); + stk::mesh::put_field_on_mesh(*deathStatusField,metaData->universal_part(), nullptr); activePart = &metaData->declare_part("active"); deathPart = &metaData->declare_part("death_1", metaData->side_rank()); diff --git a/packages/stk/stk_unit_tests/stk_mesh/ngp/KokkosBulkDataCentroidCalculation.hpp b/packages/stk/stk_unit_tests/stk_mesh/ngp/KokkosBulkDataCentroidCalculation.hpp index efa3598085f6..3838ec545c74 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/ngp/KokkosBulkDataCentroidCalculation.hpp +++ b/packages/stk/stk_unit_tests/stk_mesh/ngp/KokkosBulkDataCentroidCalculation.hpp @@ -207,9 +207,8 @@ struct MyApp { centroid = &meta->declare_field(stk::topology::ELEM_RANK, "centroid"); hostCentroid = &meta->declare_field(stk::topology::ELEM_RANK, "hostCentroid"); - std::vector init_vec = {0,0,0}; - stk::mesh::put_field_on_mesh(*centroid, meta->universal_part(), 3, init_vec.data()); - stk::mesh::put_field_on_mesh(*hostCentroid, meta->universal_part(), 3, init_vec.data()); + stk::mesh::put_field_on_mesh(*centroid, meta->universal_part(), 3, nullptr); + stk::mesh::put_field_on_mesh(*hostCentroid, meta->universal_part(), 3, nullptr); stk::io::fill_mesh(os.str(), *bulk); diff --git a/packages/stk/stk_unit_tests/stk_mesh/ngp/KokkosNodalVolume.cpp b/packages/stk/stk_unit_tests/stk_mesh/ngp/KokkosNodalVolume.cpp index 9b33f39a99ae..69e7efc17734 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/ngp/KokkosNodalVolume.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/ngp/KokkosNodalVolume.cpp @@ -398,14 +398,11 @@ class NodalVolumeCalculator : public stk::unit_test_util::simple_fields::MeshFix void create_mesh_and_fields(const stk::mesh::Part &part) { elemVolumePerNodeField = &get_meta().declare_field(stk::topology::ELEM_RANK, "elemVolumePerNodeField"); - stk::mesh::put_field_on_mesh(*elemVolumePerNodeField, part, - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(*elemVolumePerNodeField, part, nullptr); nodalVolumeField = &get_meta().declare_field(stk::topology::NODE_RANK, "nodal_volume"); - stk::mesh::put_field_on_mesh(*nodalVolumeField, part, - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(*nodalVolumeField, part, nullptr); numElemsPerNodeField = &get_meta().declare_field(stk::topology::NODE_RANK, "numElemsPerNode"); - stk::mesh::put_field_on_mesh(*numElemsPerNodeField, part, - (stk::mesh::FieldTraits >::data_type*) nullptr); + stk::mesh::put_field_on_mesh(*numElemsPerNodeField, part, nullptr); std::string meshName = stk::unit_test_util::simple_fields::get_mesh_spec("-dim"); stk::io::fill_mesh(meshName, get_bulk()); std::cout << "Using mesh: "< & userField = get_meta().declare_field(stk::topology::NODE_RANK, "userField", numStates); stk::mesh::Field & goldValues = get_meta().declare_field(stk::topology::NODE_RANK, "goldValues", numStates); - stk::mesh::put_field_on_mesh(userField, get_meta().universal_part(), &initValue); - stk::mesh::put_field_on_mesh(goldValues, get_meta().universal_part(), &initValue); + stk::mesh::put_field_on_mesh(userField, get_meta().universal_part(), nullptr); + stk::mesh::put_field_on_mesh(goldValues, get_meta().universal_part(), nullptr); stk::io::fill_mesh("generated:1x1x4", get_bulk()); @@ -148,12 +147,11 @@ NGP_TEST_F(NgpParallelSum, simpleVersion) NGP_TEST_F(NgpParallelSum, simpleVersion_noSyncToDeviceAfterwards) { setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); - const double initValue = 0.0; const int numStates = 1; stk::mesh::Field & userField = get_meta().declare_field(stk::topology::NODE_RANK, "userField", numStates); stk::mesh::Field & goldValues = get_meta().declare_field(stk::topology::NODE_RANK, "goldValues", numStates); - stk::mesh::put_field_on_mesh(userField, get_meta().universal_part(), &initValue); - stk::mesh::put_field_on_mesh(goldValues, get_meta().universal_part(), &initValue); + stk::mesh::put_field_on_mesh(userField, get_meta().universal_part(), nullptr); + stk::mesh::put_field_on_mesh(goldValues, get_meta().universal_part(), nullptr); stk::io::fill_mesh("generated:1x1x4", get_bulk()); @@ -174,12 +172,11 @@ NGP_TEST_F(NgpParallelSum, simpleVersion_noSyncToDeviceAfterwards) NGP_TEST_F(NgpCopyOwnedToShared, simpleVersion) { setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); - const double initValue = 0.0; const int numStates = 1; stk::mesh::Field & userField = get_meta().declare_field(stk::topology::NODE_RANK, "userField", numStates); stk::mesh::Field & goldValues = get_meta().declare_field(stk::topology::NODE_RANK, "goldValues", numStates); - stk::mesh::put_field_on_mesh(userField, get_meta().universal_part(), &initValue); - stk::mesh::put_field_on_mesh(goldValues, get_meta().universal_part(), &initValue); + stk::mesh::put_field_on_mesh(userField, get_meta().universal_part(), nullptr); + stk::mesh::put_field_on_mesh(goldValues, get_meta().universal_part(), nullptr); stk::io::fill_mesh("generated:1x1x4", get_bulk()); @@ -198,12 +195,11 @@ NGP_TEST_F(NgpCopyOwnedToShared, simpleVersion) NGP_TEST_F(NgpCopyOwnedToShared, simpleVersion_noSyncToDeviceAfterwards) { setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); - const double initValue = 0.0; const int numStates = 1; stk::mesh::Field & userField = get_meta().declare_field(stk::topology::NODE_RANK, "userField", numStates); stk::mesh::Field & goldValues = get_meta().declare_field(stk::topology::NODE_RANK, "goldValues", numStates); - stk::mesh::put_field_on_mesh(userField, get_meta().universal_part(), &initValue); - stk::mesh::put_field_on_mesh(goldValues, get_meta().universal_part(), &initValue); + stk::mesh::put_field_on_mesh(userField, get_meta().universal_part(), nullptr); + stk::mesh::put_field_on_mesh(goldValues, get_meta().universal_part(), nullptr); stk::io::fill_mesh("generated:1x1x4", get_bulk()); @@ -224,12 +220,11 @@ NGP_TEST_F(NgpCopyOwnedToShared, simpleVersion_noSyncToDeviceAfterwards) NGP_TEST_F(NgpCommunicateFieldData, simpleVersion_takesGhosting) { setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); - const double initValue = 0.0; const int numStates = 1; stk::mesh::Field & userField = get_meta().declare_field(stk::topology::NODE_RANK, "userField", numStates); stk::mesh::Field & goldValues = get_meta().declare_field(stk::topology::NODE_RANK, "goldValues", numStates); - stk::mesh::put_field_on_mesh(userField, get_meta().universal_part(), &initValue); - stk::mesh::put_field_on_mesh(goldValues, get_meta().universal_part(), &initValue); + stk::mesh::put_field_on_mesh(userField, get_meta().universal_part(), nullptr); + stk::mesh::put_field_on_mesh(goldValues, get_meta().universal_part(), nullptr); stk::io::fill_mesh("generated:1x1x4", get_bulk()); @@ -248,12 +243,11 @@ NGP_TEST_F(NgpCommunicateFieldData, simpleVersion_takesGhosting) NGP_TEST_F(NgpCommunicateFieldData, simpleVersion_takesGhosting_noSyncToDeviceAfterwards) { setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); - const double initValue = 0.0; const int numStates = 1; stk::mesh::Field & userField = get_meta().declare_field(stk::topology::NODE_RANK, "userField", numStates); stk::mesh::Field & goldValues = get_meta().declare_field(stk::topology::NODE_RANK, "goldValues", numStates); - stk::mesh::put_field_on_mesh(userField, get_meta().universal_part(), &initValue); - stk::mesh::put_field_on_mesh(goldValues, get_meta().universal_part(), &initValue); + stk::mesh::put_field_on_mesh(userField, get_meta().universal_part(), nullptr); + stk::mesh::put_field_on_mesh(goldValues, get_meta().universal_part(), nullptr); stk::io::fill_mesh("generated:1x1x4", get_bulk()); @@ -274,12 +268,11 @@ NGP_TEST_F(NgpCommunicateFieldData, simpleVersion_takesGhosting_noSyncToDeviceAf NGP_TEST_F(NgpCommunicateFieldData, simpleVersion_takesBulkData) { setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); - const double initValue = 0.0; const int numStates = 1; stk::mesh::Field & userField = get_meta().declare_field(stk::topology::NODE_RANK, "userField", numStates); stk::mesh::Field & goldValues = get_meta().declare_field(stk::topology::NODE_RANK, "goldValues", numStates); - stk::mesh::put_field_on_mesh(userField, get_meta().universal_part(), &initValue); - stk::mesh::put_field_on_mesh(goldValues, get_meta().universal_part(), &initValue); + stk::mesh::put_field_on_mesh(userField, get_meta().universal_part(), nullptr); + stk::mesh::put_field_on_mesh(goldValues, get_meta().universal_part(), nullptr); stk::io::fill_mesh("generated:1x1x4", get_bulk()); @@ -298,12 +291,11 @@ NGP_TEST_F(NgpCommunicateFieldData, simpleVersion_takesBulkData) NGP_TEST_F(NgpCommunicateFieldData, simpleVersion_takesBulkData_noSyncToDeviceAfterwards) { setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); - const double initValue = 0.0; const int numStates = 1; stk::mesh::Field & userField = get_meta().declare_field(stk::topology::NODE_RANK, "userField", numStates); stk::mesh::Field & goldValues = get_meta().declare_field(stk::topology::NODE_RANK, "goldValues", numStates); - stk::mesh::put_field_on_mesh(userField, get_meta().universal_part(), &initValue); - stk::mesh::put_field_on_mesh(goldValues, get_meta().universal_part(), &initValue); + stk::mesh::put_field_on_mesh(userField, get_meta().universal_part(), nullptr); + stk::mesh::put_field_on_mesh(goldValues, get_meta().universal_part(), nullptr); stk::io::fill_mesh("generated:1x1x4", get_bulk()); @@ -325,12 +317,11 @@ NGP_TEST_F(NgpParallelSum, DISABLED_DeviceMPIVersion) if (!stk::have_device_aware_mpi()) { GTEST_SKIP(); } setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); - const double initValue = 0.0; const int numStates = 1; stk::mesh::Field & userField = get_meta().declare_field(stk::topology::NODE_RANK, "userField", numStates); stk::mesh::Field & goldValues = get_meta().declare_field(stk::topology::NODE_RANK, "goldValues", numStates); - stk::mesh::put_field_on_mesh(userField, get_meta().universal_part(), &initValue); - stk::mesh::put_field_on_mesh(goldValues, get_meta().universal_part(), &initValue); + stk::mesh::put_field_on_mesh(userField, get_meta().universal_part(), nullptr); + stk::mesh::put_field_on_mesh(goldValues, get_meta().universal_part(), nullptr); stk::io::fill_mesh("generated:1x1x4", get_bulk()); @@ -364,12 +355,11 @@ NGP_TEST_F(NgpParallelSum, Performance) } setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); - const double initValue = 0.0; const int numStates = 1; stk::mesh::Field & userField = get_meta().declare_field(stk::topology::NODE_RANK, "userField", numStates); stk::mesh::Field & goldValues = get_meta().declare_field(stk::topology::NODE_RANK, "goldValues", numStates); - stk::mesh::put_field_on_mesh(userField, get_meta().universal_part(), &initValue); - stk::mesh::put_field_on_mesh(goldValues, get_meta().universal_part(), &initValue); + stk::mesh::put_field_on_mesh(userField, get_meta().universal_part(), nullptr); + stk::mesh::put_field_on_mesh(goldValues, get_meta().universal_part(), nullptr); stk::io::fill_mesh_with_auto_decomp(serialMeshName, get_bulk()); diff --git a/packages/stk/stk_unit_tests/stk_mesh/ngp/UnitTestNgpDebugFieldSync.cpp b/packages/stk/stk_unit_tests/stk_mesh/ngp/UnitTestNgpDebugFieldSync.cpp index 6b7d985e04a7..35ef6d7166c7 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/ngp/UnitTestNgpDebugFieldSync.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/ngp/UnitTestNgpDebugFieldSync.cpp @@ -2277,9 +2277,8 @@ class NgpDebugFieldSync_SeparateFieldRestrictions : public NgpDebugFieldSyncFixt const unsigned numStates = 1; stk::mesh::Field & field = get_meta().declare_field(stk::topology::ELEM_RANK, fieldName, numStates); - double init = 0.0; - stk::mesh::put_field_on_mesh(field, part1, &init); - stk::mesh::put_field_on_mesh(field, part2, &init); + stk::mesh::put_field_on_mesh(field, part1, nullptr); + stk::mesh::put_field_on_mesh(field, part2, nullptr); const std::vector part1FullPart2Empty = {{"Part1", 2}}; build_mesh(part1FullPart2Empty); diff --git a/packages/stk/stk_unit_tests/stk_mesh/ngp/howToNgp.cpp b/packages/stk/stk_unit_tests/stk_mesh/ngp/howToNgp.cpp index f83a0842af3f..815547ad9b9d 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/ngp/howToNgp.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/ngp/howToNgp.cpp @@ -54,8 +54,7 @@ class NgpHowTo : public stk::unit_test_util::simple_fields::MeshFixture setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); stk::mesh::Part &shellQuadPart = get_meta().get_topology_root_part(stk::topology::SHELL_QUAD_4); auto &shellQuadField = get_meta().declare_field(stk::topology::ELEM_RANK, "myField"); - double init = 0.0; - stk::mesh::put_field_on_mesh(shellQuadField, shellQuadPart, &init); + stk::mesh::put_field_on_mesh(shellQuadField, shellQuadPart, nullptr); std::string meshDesc = "0,1,HEX_8,1,2,3,4,5,6,7,8\n\ 0,2,SHELL_QUAD_4,5,6,7,8"; @@ -68,8 +67,7 @@ TEST_F(NgpHowTo, loopOverSubsetOfMesh) setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); stk::mesh::Part &shellQuadPart = get_meta().get_topology_root_part(stk::topology::SHELL_QUAD_4); auto &shellQuadField = get_meta().declare_field(stk::topology::ELEM_RANK, "myField"); - double init = 0.0; - stk::mesh::put_field_on_mesh(shellQuadField, shellQuadPart, &init); + stk::mesh::put_field_on_mesh(shellQuadField, shellQuadPart, nullptr); std::string meshDesc = "0,1,HEX_8,1,2,3,4,5,6,7,8\n\ 0,2,SHELL_QUAD_4,5,6,7,8"; @@ -146,8 +144,7 @@ TEST_F(NgpHowTo, fieldOnSubsetOfMesh) const stk::mesh::Part &hex8Part = get_meta().get_topology_root_part(stk::topology::HEX_8); auto &shellQuadField = get_meta().declare_field(stk::topology::ELEM_RANK, "myField"); - double init = 0.0; - stk::mesh::put_field_on_mesh(shellQuadField, shellQuadPart, &init); + stk::mesh::put_field_on_mesh(shellQuadField, shellQuadPart, nullptr); std::string meshDesc = "0,1,HEX_8,1,2,3,4,5,6,7,8\n\ 0,2,SHELL_QUAD_4,5,6,7,8"; @@ -166,8 +163,7 @@ TEST_F(NgpHowTo, loopOverAllMeshNodes) { setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); auto &field = get_meta().declare_field(stk::topology::NODE_RANK, "myField"); - double init = 0.0; - stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), &init); + stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), nullptr); std::string meshDesc = "0,1,HEX_8,1,2,3,4,5,6,7,8"; stk::unit_test_util::simple_fields::setup_text_mesh(get_bulk(), meshDesc); double fieldVal = 13.0; @@ -182,8 +178,7 @@ TEST_F(NgpHowTo, loopOverMeshFaces) setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); stk::mesh::Part &facePart = get_meta().declare_part("facePart", stk::topology::FACE_RANK); auto &field = get_meta().declare_field(stk::topology::FACE_RANK, "myField"); - double init = 0.0; - stk::mesh::put_field_on_mesh(field, facePart, &init); + stk::mesh::put_field_on_mesh(field, facePart, nullptr); std::string meshDesc = "0,1,HEX_8,1,2,3,4,5,6,7,8"; stk::unit_test_util::simple_fields::setup_text_mesh(get_bulk(), meshDesc); @@ -247,8 +242,7 @@ TEST_F(NgpHowTo, loopOverElemNodes) } setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); auto &field = get_meta().declare_field(stk::topology::NODE_RANK, "myField"); - double init = 0.0; - stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), &init); + stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), nullptr); std::string meshDesc = "0,1,HEX_8,1,2,3,4,5,6,7,8"; stk::unit_test_util::simple_fields::setup_text_mesh(get_bulk(), meshDesc); @@ -263,8 +257,7 @@ TEST_F(NgpHowTo, loopOverElemNodes_bucketCapacity) const unsigned bucketCapacity = 8; setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA, bucketCapacity); auto &field = get_meta().declare_field(stk::topology::NODE_RANK, "myField"); - double init = 0.0; - stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), &init); + stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), nullptr); std::string meshDesc = "0,1,HEX_8,1,2,3,4,5,6,7,8"; stk::unit_test_util::simple_fields::setup_text_mesh(get_bulk(), meshDesc); @@ -380,8 +373,7 @@ TEST_F(NgpHowTo, loopOverElemFaces) } setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); auto &field = get_meta().declare_field(stk::topology::NODE_RANK, "myField"); - double init = 0.0; - stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), &init); + stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), nullptr); stk::io::fill_mesh("generated:1x1x1|sideset:xXyYzZ", get_bulk()); run_connected_face_test(get_bulk()); @@ -452,8 +444,7 @@ TEST_F(NgpHowToConstraint, checkNodalConnectivity) } setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); auto &field = get_meta().declare_field(stk::topology::NODE_RANK, "myField"); - double init = 0.0; - stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), &init); + stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), nullptr); stk::io::fill_mesh("generated:1x1x1", get_bulk()); stk::mesh::EntityId constraintId = 1; add_constraint_on_nodes_1_thru_4(get_bulk(), constraintId); @@ -523,8 +514,7 @@ TEST_F(NgpHowTo, loopOverElemFaceOrdinals) } setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); auto &field = get_meta().declare_field(stk::topology::NODE_RANK, "myField"); - double init = 0.0; - stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), &init); + stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), nullptr); stk::io::fill_mesh("generated:1x1x1|sideset:xXyYzZ", get_bulk()); run_connected_face_ordinal_test(get_bulk()); @@ -603,8 +593,7 @@ TEST_F(NgpHowTo, loopOverElemFacePermutations) setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); stk::mesh::Part& sidePart = get_meta().declare_part("SidePart"); auto &field = get_meta().declare_field(stk::topology::NODE_RANK, "myField"); - double init = 0.0; - stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), &init); + stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), nullptr); stk::io::fill_mesh("generated:1x1x2|sideset:xXyYzZ", get_bulk()); stk::mesh::create_edges(get_bulk()); bool connectFacesToEdges = true; @@ -677,8 +666,7 @@ TEST_F(NgpHowTo, anotherElemFacesTest) } setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); auto &field = get_meta().declare_field(stk::topology::NODE_RANK, "myField"); - double init = 0.0; - stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), &init); + stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), nullptr); stk::io::fill_mesh("generated:1x1x4|sideset:zZ", get_bulk()); run_another_connected_face_test(get_bulk()); } @@ -724,9 +712,8 @@ TEST_F(NgpHowTo, viewOfFields) setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); auto &field1 = get_meta().declare_field(stk::topology::NODE_RANK, "myField1"); auto &field2 = get_meta().declare_field(stk::topology::NODE_RANK, "myField2"); - double init = 0.0; - stk::mesh::put_field_on_mesh(field1, get_meta().universal_part(), &init); - stk::mesh::put_field_on_mesh(field2, get_meta().universal_part(), &init); + stk::mesh::put_field_on_mesh(field1, get_meta().universal_part(), nullptr); + stk::mesh::put_field_on_mesh(field2, get_meta().universal_part(), nullptr); stk::io::fill_mesh("generated:1x1x4|sideset:zZ", get_bulk()); test_view_of_fields(get_bulk(), field1, field2); @@ -1281,8 +1268,7 @@ TEST_F(NgpHowTo, checkPartMembership) } setup_empty_mesh(stk::mesh::BulkData::NO_AUTO_AURA); auto &field = get_meta().declare_field(stk::topology::NODE_RANK, "myField"); - double init = 0.0; - stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), &init); + stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), nullptr); stk::mesh::Part& testPart = get_meta().declare_part("testPart", stk::topology::NODE_RANK); diff --git a/packages/stk/stk_unit_tests/stk_mesh/ngp/ngpMultiStateFieldTests.cpp b/packages/stk/stk_unit_tests/stk_mesh/ngp/ngpMultiStateFieldTests.cpp index 2e798b88ac0d..71c8a3f3d311 100644 --- a/packages/stk/stk_unit_tests/stk_mesh/ngp/ngpMultiStateFieldTests.cpp +++ b/packages/stk/stk_unit_tests/stk_mesh/ngp/ngpMultiStateFieldTests.cpp @@ -111,9 +111,8 @@ class NgpMultiStateFieldTest : public stk::mesh::fixtures::simple_fields::TestHe template stk::mesh::Field & create_multistate_field(stk::topology::rank_t rank, const std::string & name, unsigned numStates) { - T initialValue = 0; stk::mesh::Field & field = get_meta().declare_field(rank, name, numStates); - stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), &initialValue); + stk::mesh::put_field_on_mesh(field, get_meta().universal_part(), nullptr); return field; } diff --git a/packages/stk/stk_unit_tests/stk_util/parallel/UnitTestMPICommKey.cpp b/packages/stk/stk_unit_tests/stk_util/parallel/UnitTestMPICommKey.cpp index bdd1269b4710..bc72b7928670 100644 --- a/packages/stk/stk_unit_tests/stk_util/parallel/UnitTestMPICommKey.cpp +++ b/packages/stk/stk_unit_tests/stk_util/parallel/UnitTestMPICommKey.cpp @@ -70,7 +70,7 @@ class CallbackChecker } // namespace - +#ifndef MPI_KEY_MANAGER_COMM_DESTRUCTOR_CALLBACK_BROKEN namespace { MPI_Request req; bool is_complete = false; @@ -83,7 +83,6 @@ namespace { } } -#ifndef MPI_KEY_MANAGER_COMM_DESTRUCTOR_CALLBACK_BROKEN TEST(KeyManager, IntelMPIBug) { MPI_Comm comm2; diff --git a/packages/stk/stk_util/stk_util/registry/ProductRegistry.cpp b/packages/stk/stk_util/stk_util/registry/ProductRegistry.cpp index 256d49ed514e..4f77da4accec 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.7.2-179-g3f1355cd" +#define STK_VERSION_STRING "5.7.2-246-g86e6e237" #endif namespace stk { diff --git a/packages/stk/stk_util/stk_util/util/StkNgpVector.hpp b/packages/stk/stk_util/stk_util/util/StkNgpVector.hpp index 4495d886cc42..529eeec21516 100644 --- a/packages/stk/stk_util/stk_util/util/StkNgpVector.hpp +++ b/packages/stk/stk_util/stk_util/util/StkNgpVector.hpp @@ -50,8 +50,15 @@ class NgpVector NgpVector() : NgpVector(get_default_name()) { } - NgpVector(const std::string &n, size_t s) : mSize(s), deviceVals(Kokkos::view_alloc(Kokkos::WithoutInitializing, n), mSize), hostVals(Kokkos::create_mirror_view(HostSpace(), deviceVals, Kokkos::WithoutInitializing)) - { + NgpVector(const std::string &n, size_t s) + : mSize(s), + deviceVals(Kokkos::view_alloc(Kokkos::WithoutInitializing, n), mSize), +#ifndef NEW_TRILINOS_INTEGRATION + hostVals(Kokkos::create_mirror_view(HostSpace(), deviceVals, Kokkos::WithoutInitializing)) +#else + hostVals(Kokkos::create_mirror_view(Kokkos::WithoutInitializing, HostSpace(), deviceVals)) +#endif + { } NgpVector(size_t s) : NgpVector(get_default_name(), s) {