Teuchos::RCP<PeridigmNS::NeighborhoodData> PeridigmNS::Block::createNeighborhoodDataFromGlobalNeighborhoodData(Teuchos::RCP<const Epetra_BlockMap> globalOverlapScalarPointMap, Teuchos::RCP<const PeridigmNS::NeighborhoodData> globalNeighborhoodData) { int numOwnedPoints = ownedScalarPointMap->NumMyElements(); int* ownedPointGlobalIDs = ownedScalarPointMap->MyGlobalElements(); vector<int> ownedIDs(numOwnedPoints); vector<int> neighborhoodList; vector<int> neighborhoodPtr(numOwnedPoints); int* const globalNeighborhoodList = globalNeighborhoodData->NeighborhoodList(); int* const globalNeighborhoodPtr = globalNeighborhoodData->NeighborhoodPtr(); // Create the neighborhoodList and neighborhoodPtr for this block. // All the IDs in the neighborhoodList and neighborhoodPtr are local IDs into // the block-specific overlap map. for(int i=0 ; i<numOwnedPoints ; ++i){ neighborhoodPtr[i] = (int)(neighborhoodList.size()); int globalID = ownedPointGlobalIDs[i]; ownedIDs[i] = overlapScalarPointMap->LID(globalID); int globalNeighborhoodListIndex = globalNeighborhoodPtr[globalOverlapScalarPointMap->LID(globalID)]; int numNeighbors = globalNeighborhoodList[globalNeighborhoodListIndex++]; neighborhoodList.push_back(numNeighbors); for(int j=0 ; j<numNeighbors ; ++j){ int globalNeighborID = globalOverlapScalarPointMap->GID(globalNeighborhoodList[globalNeighborhoodListIndex++]); neighborhoodList.push_back( overlapScalarPointMap->LID(globalNeighborID) ); } } // create the NeighborhoodData for this block Teuchos::RCP<PeridigmNS::NeighborhoodData> blockNeighborhoodData = Teuchos::rcp(new PeridigmNS::NeighborhoodData); blockNeighborhoodData->SetNumOwned(ownedIDs.size()); if(ownedIDs.size() > 0){ memcpy(blockNeighborhoodData->OwnedIDs(), &ownedIDs.at(0), ownedIDs.size()*sizeof(int)); } if(neighborhoodPtr.size() > 0){ memcpy(blockNeighborhoodData->NeighborhoodPtr(), &neighborhoodPtr.at(0), neighborhoodPtr.size()*sizeof(int)); } blockNeighborhoodData->SetNeighborhoodListSize(neighborhoodList.size()); if(neighborhoodList.size() > 0){ memcpy(blockNeighborhoodData->NeighborhoodList(), &neighborhoodList.at(0), neighborhoodList.size()*sizeof(int)); } return blockNeighborhoodData; }
void PeridigmNS::ModelEvaluator::evalJacobian(Teuchos::RCP<Workset> workset) const { const double dt = workset->timeStep; std::vector<PeridigmNS::Block>::iterator blockIt; PeridigmNS::Material::JacobianType jacobianType = *(workset->jacobianType); PeridigmNS::SerialMatrix& jacobian = *(workset->jacobian); // ---- Compute the Tangent Stiffness Matrix ---- for(blockIt = workset->blocks->begin() ; blockIt != workset->blocks->end() ; blockIt++){ Teuchos::RCP<PeridigmNS::NeighborhoodData> neighborhoodData = blockIt->getNeighborhoodData(); const int numOwnedPoints = neighborhoodData->NumOwnedPoints(); const int* ownedIDs = neighborhoodData->OwnedIDs(); const int* neighborhoodList = neighborhoodData->NeighborhoodList(); Teuchos::RCP<PeridigmNS::DataManager> dataManager = blockIt->getDataManager(); Teuchos::RCP<const PeridigmNS::Material> materialModel = blockIt->getMaterialModel(); materialModel->computeJacobian(dt, numOwnedPoints, ownedIDs, neighborhoodList, *dataManager, jacobian, jacobianType); } }
void PeridigmNS::ModelEvaluator::evalModel(Teuchos::RCP<Workset> workset) const { const double dt = workset->timeStep; std::vector<PeridigmNS::Block>::iterator blockIt; // ---- Evaluate Damage --- for(blockIt = workset->blocks->begin() ; blockIt != workset->blocks->end() ; blockIt++){ Teuchos::RCP<const PeridigmNS::DamageModel> damageModel = blockIt->getDamageModel(); if(!damageModel.is_null()){ Teuchos::RCP<PeridigmNS::NeighborhoodData> neighborhoodData = blockIt->getNeighborhoodData(); const int numOwnedPoints = neighborhoodData->NumOwnedPoints(); const int* ownedIDs = neighborhoodData->OwnedIDs(); const int* neighborhoodList = neighborhoodData->NeighborhoodList(); Teuchos::RCP<PeridigmNS::DataManager> dataManager = blockIt->getDataManager(); damageModel->computeDamage(dt, numOwnedPoints, ownedIDs, neighborhoodList, *dataManager); } } // ---- Evaluate Internal Force ---- for(blockIt = workset->blocks->begin() ; blockIt != workset->blocks->end() ; blockIt++){ Teuchos::RCP<PeridigmNS::NeighborhoodData> neighborhoodData = blockIt->getNeighborhoodData(); const int numOwnedPoints = neighborhoodData->NumOwnedPoints(); const int* ownedIDs = neighborhoodData->OwnedIDs(); const int* neighborhoodList = neighborhoodData->NeighborhoodList(); Teuchos::RCP<PeridigmNS::DataManager> dataManager = blockIt->getDataManager(); Teuchos::RCP<const PeridigmNS::Material> materialModel = blockIt->getMaterialModel(); materialModel->computeForce(dt, numOwnedPoints, ownedIDs, neighborhoodList, *dataManager); } // ---- Evaluate Contact ---- if(!workset->contactManager.is_null()) workset->contactManager->evaluateContactForce(dt); }
void PeridigmNS::Compute_Number_Of_Neighbors::initialize( Teuchos::RCP< std::vector<PeridigmNS::Block> > blocks ) { std::vector<PeridigmNS::Block>::iterator blockIt; for(blockIt = blocks->begin() ; blockIt != blocks->end() ; blockIt++){ Teuchos::RCP<PeridigmNS::NeighborhoodData> neighborhoodData = blockIt->getNeighborhoodData(); const int numOwnedPoints = neighborhoodData->NumOwnedPoints(); const int* neighborhoodList = neighborhoodData->NeighborhoodList(); double *numberOfNeighbors; blockIt->getData(m_numberOfNeighborsFieldId, PeridigmField::STEP_NONE)->ExtractView(&numberOfNeighbors); int neighborhoodListIndex = 0; for(int iID=0 ; iID<numOwnedPoints ; ++iID){ int numNeighbors = neighborhoodList[neighborhoodListIndex++]; numberOfNeighbors[iID] = numNeighbors; neighborhoodListIndex += numNeighbors; } } }
void EvaluateForce<EvalT, Traits>::evaluateFields(typename Traits::EvalData cellData) { const double dt = *cellData.timeStep; std::vector<PeridigmNS::Block>::iterator blockIt; for(blockIt = cellData.blocks->begin() ; blockIt != cellData.blocks->end() ; blockIt++){ Teuchos::RCP<PeridigmNS::NeighborhoodData> neighborhoodData = blockIt->getNeighborhoodData(); const int numOwnedPoints = neighborhoodData->NumOwnedPoints(); const int* ownedIDs = neighborhoodData->OwnedIDs(); const int* neighborhoodList = neighborhoodData->NeighborhoodList(); Teuchos::RCP<PeridigmNS::DataManager> dataManager = blockIt->getDataManager(); Teuchos::RCP<const PeridigmNS::Material> materialModel = blockIt->getMaterialModel(); materialModel->computeForce(dt, numOwnedPoints, ownedIDs, neighborhoodList, *dataManager); } }
Teuchos::RCP<PeridigmNS::NeighborhoodData> PeridigmNS::TextFileDiscretization::filterBonds(Teuchos::RCP<PeridigmNS::NeighborhoodData> unfilteredNeighborhoodData) { // Set up a block bonding matrix, which defines whether or not bonds should be formed across blocks int numBlocks = getNumBlocks(); std::vector< std::vector<bool> > blockBondingMatrix(numBlocks); for(int i=0 ; i<numBlocks ; ++i){ blockBondingMatrix[i].resize(numBlocks, true); } if(bondFilterCommand == "None"){ // All blocks are bonded, the blockBondingMatrix is unchanged return unfilteredNeighborhoodData; } else if(bondFilterCommand == "All"){ // No blocks are bonded, the blockBondingMatrix is the identity matrix for(int i=0 ; i<numBlocks ; ++i){ for(int j=0 ; j<numBlocks ; ++j){ if(i != j) blockBondingMatrix[i][j] = false; } } } else{ string msg = "**** Error, unrecognized value for \"Omit Bonds Between Blocks\": "; msg += bondFilterCommand + "\n"; msg += "**** Valid options are: All, None\n"; TEUCHOS_TEST_FOR_EXCEPT_MSG(true, msg); } // Create an overlap vector containing the block IDs of each cell Teuchos::RCP<const Epetra_BlockMap> ownedMap = getGlobalOwnedMap(1); Teuchos::RCP<const Epetra_BlockMap> overlapMap = getGlobalOverlapMap(1); Epetra_Vector blockIDs(*overlapMap); Epetra_Import importer(*overlapMap, *ownedMap); Teuchos::RCP<Epetra_Vector> ownedBlockIDs = getBlockID(); blockIDs.Import(*ownedBlockIDs, importer, Insert); // Apply the block bonding matrix and create a new NeighborhoodData Teuchos::RCP<PeridigmNS::NeighborhoodData> neighborhoodData = Teuchos::rcp(new PeridigmNS::NeighborhoodData); neighborhoodData->SetNumOwned(unfilteredNeighborhoodData->NumOwnedPoints()); memcpy(neighborhoodData->OwnedIDs(), unfilteredNeighborhoodData->OwnedIDs(), neighborhoodData->NumOwnedPoints()*sizeof(int)); vector<int> neighborhoodListVec; neighborhoodListVec.reserve(unfilteredNeighborhoodData->NeighborhoodListSize()); int* const neighborhoodPtr = neighborhoodData->NeighborhoodPtr(); int numOwnedPoints = neighborhoodData->NumOwnedPoints(); int* const unfilteredNeighborhoodList = unfilteredNeighborhoodData->NeighborhoodList(); int unfilteredNeighborhoodListIndex(0); for(int iID=0 ; iID<numOwnedPoints ; ++iID){ int blockID = static_cast<int>(blockIDs[iID]); int numUnfilteredNeighbors = unfilteredNeighborhoodList[unfilteredNeighborhoodListIndex++]; unsigned int numNeighborsIndex = neighborhoodListVec.size(); neighborhoodListVec.push_back(-1); // placeholder for number of neighbors int numNeighbors = 0; for(int iNID=0 ; iNID<numUnfilteredNeighbors ; ++iNID){ int unfilteredNeighborID = unfilteredNeighborhoodList[unfilteredNeighborhoodListIndex++]; int unfilteredNeighborBlockID = static_cast<int>(blockIDs[unfilteredNeighborID]); if(blockBondingMatrix[blockID-1][unfilteredNeighborBlockID-1] == true){ neighborhoodListVec.push_back(unfilteredNeighborID); numNeighbors += 1; } } neighborhoodListVec[numNeighborsIndex] = numNeighbors; neighborhoodPtr[iID] = numNeighborsIndex; } neighborhoodData->SetNeighborhoodListSize(neighborhoodListVec.size()); memcpy(neighborhoodData->NeighborhoodList(), &neighborhoodListVec[0], neighborhoodListVec.size()*sizeof(int)); return neighborhoodData; }
TEUCHOS_UNIT_TEST(PdQuickGridDiscretization_MPI_np2, SimpleTensorProductMeshTest) { Teuchos::RCP<Epetra_Comm> comm; comm = rcp(new Epetra_MpiComm(MPI_COMM_WORLD)); int numProcs = comm->NumProc(); int rank = comm->MyPID(); TEST_COMPARE(numProcs, ==, 2); if(numProcs != 2){ std::cerr << "Unit test runtime ERROR: utPeridigm_PdQuickGridDiscretization_MPI_np2 only makes sense on 2 processors" << std::endl; return; } RCP<ParameterList> discParams = rcp(new ParameterList); // create a 2x2x2 discretization // specify a spherical neighbor search with the horizon a tad longer than the mesh spacing discParams->set("Type", "PdQuickGrid"); discParams->set("NeighborhoodType", "Spherical"); ParameterList& quickGridParams = discParams->sublist("TensorProduct3DMeshGenerator"); quickGridParams.set("Type", "PdQuickGrid"); quickGridParams.set("X Origin", 0.0); quickGridParams.set("Y Origin", 0.0); quickGridParams.set("Z Origin", 0.0); quickGridParams.set("X Length", 1.0); quickGridParams.set("Y Length", 1.0); quickGridParams.set("Z Length", 1.0); quickGridParams.set("Number Points X", 2); quickGridParams.set("Number Points Y", 2); quickGridParams.set("Number Points Z", 2); // initialize the horizon manager and set the horizon to 0.501 ParameterList blockParameterList; ParameterList& blockParams = blockParameterList.sublist("My Block"); blockParams.set("Block Names", "block_1"); blockParams.set("Horizon", 0.501); PeridigmNS::HorizonManager::self().loadHorizonInformationFromBlockParameters(blockParameterList); // create the discretization RCP<PdQuickGridDiscretization> discretization = rcp(new PdQuickGridDiscretization(comm, discParams)); // sanity check, calling with a dimension other than 1 or 3 should throw an exception TEST_THROW(discretization->getGlobalOwnedMap(0), Teuchos::Exceptions::InvalidParameter); TEST_THROW(discretization->getGlobalOwnedMap(2), Teuchos::Exceptions::InvalidParameter); TEST_THROW(discretization->getGlobalOwnedMap(4), Teuchos::Exceptions::InvalidParameter); // basic checks on the 1d map Teuchos::RCP<const Epetra_BlockMap> map = discretization->getGlobalOwnedMap(1); TEST_ASSERT(map->NumGlobalElements() == 8); TEST_ASSERT(map->NumMyElements() == 4); TEST_ASSERT(map->ElementSize() == 1); TEST_ASSERT(map->IndexBase() == 0); TEST_ASSERT(map->UniqueGIDs() == true); int* myGlobalElements = map->MyGlobalElements(); if(rank == 0){ TEST_ASSERT(myGlobalElements[0] == 0); TEST_ASSERT(myGlobalElements[1] == 2); TEST_ASSERT(myGlobalElements[2] == 4); TEST_ASSERT(myGlobalElements[3] == 6); } if(rank == 1){ TEST_ASSERT(myGlobalElements[0] == 5); TEST_ASSERT(myGlobalElements[1] == 7); TEST_ASSERT(myGlobalElements[2] == 1); TEST_ASSERT(myGlobalElements[3] == 3); } // check the 1d overlap map // for this simple discretization, everything should be ghosted on both processors Teuchos::RCP<const Epetra_BlockMap> overlapMap = discretization->getGlobalOverlapMap(1); TEST_ASSERT(overlapMap->NumGlobalElements() == 16); TEST_ASSERT(overlapMap->NumMyElements() == 8); TEST_ASSERT(overlapMap->ElementSize() == 1); TEST_ASSERT(overlapMap->IndexBase() == 0); TEST_ASSERT(overlapMap->UniqueGIDs() == false); myGlobalElements = overlapMap->MyGlobalElements(); if(rank == 0){ TEST_ASSERT(myGlobalElements[0] == 0); TEST_ASSERT(myGlobalElements[1] == 2); TEST_ASSERT(myGlobalElements[2] == 4); TEST_ASSERT(myGlobalElements[3] == 6); TEST_ASSERT(myGlobalElements[4] == 1); TEST_ASSERT(myGlobalElements[5] == 3); TEST_ASSERT(myGlobalElements[6] == 5); TEST_ASSERT(myGlobalElements[7] == 7); } if(rank == 1){ TEST_ASSERT(myGlobalElements[0] == 5); TEST_ASSERT(myGlobalElements[1] == 7); TEST_ASSERT(myGlobalElements[2] == 1); TEST_ASSERT(myGlobalElements[3] == 3); TEST_ASSERT(myGlobalElements[4] == 0); TEST_ASSERT(myGlobalElements[5] == 2); TEST_ASSERT(myGlobalElements[6] == 4); TEST_ASSERT(myGlobalElements[7] == 6); } // same checks for 3d map map = discretization->getGlobalOwnedMap(3); TEST_ASSERT(map->NumGlobalElements() == 8); TEST_ASSERT(map->NumMyElements() == 4); TEST_ASSERT(map->ElementSize() == 3); TEST_ASSERT(map->IndexBase() == 0); TEST_ASSERT(map->UniqueGIDs() == true); myGlobalElements = map->MyGlobalElements(); if(rank == 0){ TEST_ASSERT(myGlobalElements[0] == 0); TEST_ASSERT(myGlobalElements[1] == 2); TEST_ASSERT(myGlobalElements[2] == 4); TEST_ASSERT(myGlobalElements[3] == 6); } if(rank == 1){ TEST_ASSERT(myGlobalElements[0] == 5); TEST_ASSERT(myGlobalElements[1] == 7); TEST_ASSERT(myGlobalElements[2] == 1); TEST_ASSERT(myGlobalElements[3] == 3); } // check the 3d overlap map // for this simple discretization, everything should be ghosted on both processors overlapMap = discretization->getGlobalOverlapMap(3); TEST_ASSERT(overlapMap->NumGlobalElements() == 16); TEST_ASSERT(overlapMap->NumMyElements() == 8); TEST_ASSERT(overlapMap->ElementSize() == 3); TEST_ASSERT(overlapMap->IndexBase() == 0); TEST_ASSERT(overlapMap->UniqueGIDs() == false); myGlobalElements = overlapMap->MyGlobalElements(); if(rank == 0){ TEST_ASSERT(myGlobalElements[0] == 0); TEST_ASSERT(myGlobalElements[1] == 2); TEST_ASSERT(myGlobalElements[2] == 4); TEST_ASSERT(myGlobalElements[3] == 6); TEST_ASSERT(myGlobalElements[4] == 1); TEST_ASSERT(myGlobalElements[5] == 3); TEST_ASSERT(myGlobalElements[6] == 5); TEST_ASSERT(myGlobalElements[7] == 7); } if(rank == 1){ TEST_ASSERT(myGlobalElements[0] == 5); TEST_ASSERT(myGlobalElements[1] == 7); TEST_ASSERT(myGlobalElements[2] == 1); TEST_ASSERT(myGlobalElements[3] == 3); TEST_ASSERT(myGlobalElements[4] == 0); TEST_ASSERT(myGlobalElements[5] == 2); TEST_ASSERT(myGlobalElements[6] == 4); TEST_ASSERT(myGlobalElements[7] == 6); } // check the bond map // the horizon was chosen such that each point should have three neighbors // note that if the NeighborhoodType parameter is not set to Spherical, this will fail Teuchos::RCP<const Epetra_BlockMap> bondMap = discretization->getGlobalBondMap(); TEST_ASSERT(bondMap->NumGlobalElements() == 8); TEST_ASSERT(bondMap->NumMyElements() == 4); TEST_ASSERT(bondMap->IndexBase() == 0); TEST_ASSERT(bondMap->UniqueGIDs() == true); myGlobalElements = bondMap->MyGlobalElements(); if(rank == 0){ TEST_ASSERT(myGlobalElements[0] == 0); TEST_ASSERT(myGlobalElements[1] == 2); TEST_ASSERT(myGlobalElements[2] == 4); TEST_ASSERT(myGlobalElements[3] == 6); } if(rank == 1){ TEST_ASSERT(myGlobalElements[0] == 5); TEST_ASSERT(myGlobalElements[1] == 7); TEST_ASSERT(myGlobalElements[2] == 1); TEST_ASSERT(myGlobalElements[3] == 3); } TEST_ASSERT(discretization->getNumBonds() == 4*3); // check the initial positions // all three coordinates are contained in a single vector Teuchos::RCP<Epetra_Vector> initialX = discretization->getInitialX(); TEST_ASSERT(initialX->MyLength() == 4*3); TEST_ASSERT(initialX->GlobalLength() == 8*3); if(rank == 0){ TEST_FLOATING_EQUALITY((*initialX)[0], 0.25, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[1], 0.25, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[2], 0.25, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[3], 0.25, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[4], 0.75, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[5], 0.25, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[6], 0.25, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[7], 0.25, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[8], 0.75, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[9], 0.25, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[10], 0.75, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[11], 0.75, 1.0e-16); } if(rank == 1){ TEST_FLOATING_EQUALITY((*initialX)[0], 0.75, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[1], 0.25, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[2], 0.75, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[3], 0.75, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[4], 0.75, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[5], 0.75, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[6], 0.75, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[7], 0.25, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[8], 0.25, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[9], 0.75, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[10], 0.75, 1.0e-16); TEST_FLOATING_EQUALITY((*initialX)[11], 0.25, 1.0e-16); } // check cell volumes Teuchos::RCP<Epetra_Vector> volume = discretization->getCellVolume(); TEST_ASSERT(volume->MyLength() == 4); TEST_ASSERT(volume->GlobalLength() == 8); for(int i=0 ; i<volume->MyLength() ; ++i) TEST_FLOATING_EQUALITY((*volume)[i], 0.125, 1.0e-16); // check the neighbor lists Teuchos::RCP<PeridigmNS::NeighborhoodData> neighborhoodData = discretization->getNeighborhoodData(); TEST_ASSERT(neighborhoodData->NumOwnedPoints() == 4); int* ownedIds = neighborhoodData->OwnedIDs(); TEST_ASSERT(ownedIds[0] == 0); TEST_ASSERT(ownedIds[1] == 1); TEST_ASSERT(ownedIds[2] == 2); TEST_ASSERT(ownedIds[3] == 3); TEST_ASSERT(neighborhoodData->NeighborhoodListSize() == 16); int* neighborhood = neighborhoodData->NeighborhoodList(); int* neighborhoodPtr = neighborhoodData->NeighborhoodPtr(); // remember, these are local IDs on each processor, // which includes both owned and ghost nodes (confusing!) if(rank == 0){ TEST_ASSERT(neighborhoodPtr[0] == 0); TEST_ASSERT(neighborhood[0] == 3); TEST_ASSERT(neighborhood[1] == 4); TEST_ASSERT(neighborhood[2] == 1); TEST_ASSERT(neighborhood[3] == 2); TEST_ASSERT(neighborhoodPtr[1] == 4); TEST_ASSERT(neighborhood[4] == 3); TEST_ASSERT(neighborhood[5] == 0); TEST_ASSERT(neighborhood[6] == 5); TEST_ASSERT(neighborhood[7] == 3); TEST_ASSERT(neighborhoodPtr[2] == 8); TEST_ASSERT(neighborhood[8] == 3); TEST_ASSERT(neighborhood[9] == 0); TEST_ASSERT(neighborhood[10] == 6); TEST_ASSERT(neighborhood[11] == 3); TEST_ASSERT(neighborhoodPtr[3] == 12); TEST_ASSERT(neighborhood[12] == 3); TEST_ASSERT(neighborhood[13] == 1); TEST_ASSERT(neighborhood[14] == 2); TEST_ASSERT(neighborhood[15] == 7); } if(rank == 1){ TEST_ASSERT(neighborhoodPtr[0] == 0); TEST_ASSERT(neighborhood[0] == 3); TEST_ASSERT(neighborhood[1] == 2); TEST_ASSERT(neighborhood[2] == 6); TEST_ASSERT(neighborhood[3] == 1); TEST_ASSERT(neighborhoodPtr[1] == 4); TEST_ASSERT(neighborhood[4] == 3); TEST_ASSERT(neighborhood[5] == 3); TEST_ASSERT(neighborhood[6] == 0); TEST_ASSERT(neighborhood[7] == 7); TEST_ASSERT(neighborhoodPtr[2] == 8); TEST_ASSERT(neighborhood[8] == 3); TEST_ASSERT(neighborhood[9] == 4); TEST_ASSERT(neighborhood[10] == 3); TEST_ASSERT(neighborhood[11] == 0); TEST_ASSERT(neighborhoodPtr[3] == 12); TEST_ASSERT(neighborhood[12] == 3); TEST_ASSERT(neighborhood[13] == 2); TEST_ASSERT(neighborhood[14] == 5); TEST_ASSERT(neighborhood[15] == 1); } }
double PeridigmNS::ComputeCriticalTimeStep(const Epetra_Comm& comm, PeridigmNS::Block& block){ Teuchos::RCP<PeridigmNS::NeighborhoodData> neighborhoodData = block.getNeighborhoodData(); const int numOwnedPoints = neighborhoodData->NumOwnedPoints(); const int* ownedIDs = neighborhoodData->OwnedIDs(); const int* neighborhoodList = neighborhoodData->NeighborhoodList(); Teuchos::RCP<const PeridigmNS::Material> materialModel = block.getMaterialModel(); double density = materialModel()->Density(); double bulkModulus = materialModel()->BulkModulus(); double horizon(0.0); string blockName = block.getName(); PeridigmNS::HorizonManager& horizonManager = PeridigmNS::HorizonManager::self(); bool blockHasConstantHorizon = horizonManager.blockHasConstantHorizon(blockName); if(blockHasConstantHorizon) horizon = horizonManager.getBlockConstantHorizonValue(blockName); double *cellVolume, *x; PeridigmNS::FieldManager& fieldManager = PeridigmNS::FieldManager::self(); block.getData(fieldManager.getFieldId("Volume"), PeridigmField::STEP_NONE)->ExtractView(&cellVolume); block.getData(fieldManager.getFieldId("Model_Coordinates"), PeridigmField::STEP_NONE)->ExtractView(&x); const double pi = boost::math::constants::pi<double>(); double springConstant(0.0); if(blockHasConstantHorizon) springConstant = 18.0*bulkModulus/(pi*horizon*horizon*horizon*horizon); double minCriticalTimeStep = 1.0e50; int neighborhoodListIndex = 0; for(int iID=0 ; iID<numOwnedPoints ; ++iID){ double timestepDenominator = 0.0; int nodeID = ownedIDs[iID]; double X[3] = { x[nodeID*3], x[nodeID*3+1], x[nodeID*3+2] }; int numNeighbors = neighborhoodList[neighborhoodListIndex++]; if(!blockHasConstantHorizon){ double delta = horizonManager.evaluateHorizon(blockName, X[0], X[1], X[2]); springConstant = 18.0*bulkModulus/(pi*delta*delta*delta*delta); } for(int iNID=0 ; iNID<numNeighbors ; ++iNID){ int neighborID = neighborhoodList[neighborhoodListIndex++]; double neighborVolume = cellVolume[neighborID]; double initialDistance = sqrt( (X[0] - x[neighborID*3 ])*(X[0] - x[neighborID*3 ]) + (X[1] - x[neighborID*3+1])*(X[1] - x[neighborID*3+1]) + (X[2] - x[neighborID*3+2])*(X[2] - x[neighborID*3+2]) ); // Issue a warning if the bond length is very very small (as in zero) static bool warningGiven = false; if(!warningGiven && initialDistance < 1.0e-50){ cout << "\nWarning: Possible zero length bond detected (length = " << initialDistance << ")." << endl; cout << " Bonds of length zero are not valid, the input mesh may contain coincident nodes.\n" << endl; warningGiven = true; } timestepDenominator += neighborVolume*springConstant/initialDistance; } double criticalTimeStep = 1.0e50; if(numNeighbors > 0) criticalTimeStep = sqrt(2.0*density/timestepDenominator); if(criticalTimeStep < minCriticalTimeStep) minCriticalTimeStep = criticalTimeStep; } // Find the minimum time step for this block across all processors double globalMinCriticalTimeStep; comm.MinAll(&minCriticalTimeStep, &globalMinCriticalTimeStep, 1); return globalMinCriticalTimeStep; }
void PeridigmNS::Block::createMapsFromGlobalMaps(Teuchos::RCP<const Epetra_BlockMap> globalOwnedScalarPointMap, Teuchos::RCP<const Epetra_BlockMap> globalOverlapScalarPointMap, Teuchos::RCP<const Epetra_BlockMap> globalOwnedVectorPointMap, Teuchos::RCP<const Epetra_BlockMap> globalOverlapVectorPointMap, Teuchos::RCP<const Epetra_BlockMap> globalOwnedScalarBondMap, Teuchos::RCP<const Epetra_Vector> globalBlockIds, Teuchos::RCP<const PeridigmNS::NeighborhoodData> globalNeighborhoodData, Teuchos::RCP<const PeridigmNS::NeighborhoodData> globalContactNeighborhoodData) { double* globalBlockIdsPtr; globalBlockIds->ExtractView(&globalBlockIdsPtr); // Create a list of all the on-processor elements that are part of this block vector<int> IDs; IDs.reserve(globalOverlapScalarPointMap->NumMyElements()); // upper bound vector<int> bondIDs; bondIDs.reserve(globalOverlapScalarPointMap->NumMyElements()); vector<int> bondElementSize; bondElementSize.reserve(globalOwnedScalarPointMap->NumMyElements()); for(int iLID=0 ; iLID<globalOwnedScalarPointMap->NumMyElements() ; ++iLID){ if(globalBlockIdsPtr[iLID] == blockID) { int globalID = globalOwnedScalarPointMap->GID(iLID); IDs.push_back(globalID); } } // Record the size of these elements in the bond map // Note that if an element has no bonds, it has no entry in the bondMap // So, the bond map and the scalar map can have a different number of entries (different local IDs) for(int iLID=0 ; iLID<globalOwnedScalarBondMap->NumMyElements() ; ++iLID){ int globalID = globalOwnedScalarBondMap->GID(iLID); int localID = globalOwnedScalarPointMap->LID(globalID); if(globalBlockIdsPtr[localID] == blockID){ bondIDs.push_back(globalID); bondElementSize.push_back(globalOwnedScalarBondMap->ElementSize(iLID)); } } // Create the owned scalar point map, the owned vector point map, and the owned scalar bond map int numGlobalElements = -1; int numMyElements = IDs.size(); int* myGlobalElements = 0; if(numMyElements > 0) myGlobalElements = &IDs.at(0); int elementSize = 1; int indexBase = 0; ownedScalarPointMap = Teuchos::rcp(new Epetra_BlockMap(numGlobalElements, numMyElements, myGlobalElements, elementSize, indexBase, globalOwnedScalarPointMap->Comm())); elementSize = 3; ownedVectorPointMap = Teuchos::rcp(new Epetra_BlockMap(numGlobalElements, numMyElements, myGlobalElements, elementSize, indexBase, globalOwnedScalarPointMap->Comm())); numMyElements = bondElementSize.size(); myGlobalElements = 0; int* elementSizeList = 0; if(numMyElements > 0){ myGlobalElements = &bondIDs.at(0); elementSizeList = &bondElementSize.at(0); } ownedScalarBondMap = Teuchos::rcp(new Epetra_BlockMap(numGlobalElements, numMyElements, myGlobalElements, elementSizeList, indexBase, globalOwnedScalarPointMap->Comm())); // Create a list of nodes that need to be ghosted (both across material boundaries and across processor boundaries) set<int> ghosts; // Check the neighborhood list for things that need to be ghosted int* const globalNeighborhoodList = globalNeighborhoodData->NeighborhoodList(); int globalNeighborhoodListIndex = 0; for(int iLID=0 ; iLID<globalNeighborhoodData->NumOwnedPoints() ; ++iLID){ int numNeighbors = globalNeighborhoodList[globalNeighborhoodListIndex++]; if(globalBlockIdsPtr[iLID] == blockID) { for(int i=0 ; i<numNeighbors ; ++i){ int neighborGlobalID = globalOverlapScalarPointMap->GID( globalNeighborhoodList[globalNeighborhoodListIndex + i] ); ghosts.insert(neighborGlobalID); } } globalNeighborhoodListIndex += numNeighbors; } // Check the contact neighborhood list for things that need to be ghosted if(!globalContactNeighborhoodData.is_null()){ int* const globalContactNeighborhoodList = globalContactNeighborhoodData->NeighborhoodList(); int globalContactNeighborhoodListIndex = 0; for(int iLID=0 ; iLID<globalContactNeighborhoodData->NumOwnedPoints() ; ++iLID){ int numNeighbors = globalContactNeighborhoodList[globalContactNeighborhoodListIndex++]; if(globalBlockIdsPtr[iLID] == blockID) { for(int i=0 ; i<numNeighbors ; ++i){ int neighborGlobalID = globalOverlapScalarPointMap->GID( globalContactNeighborhoodList[globalContactNeighborhoodListIndex + i] ); ghosts.insert(neighborGlobalID); } } globalContactNeighborhoodListIndex += numNeighbors; } } // Remove entries from ghosts that are already in IDs for(unsigned int i=0 ; i<IDs.size() ; ++i) ghosts.erase(IDs[i]); // Copy IDs, this is the owned global ID list vector<int> ownedIDs(IDs.begin(), IDs.end()); // Append ghosts to IDs // This creates the overlap global ID list for(set<int>::iterator it=ghosts.begin() ; it!=ghosts.end() ; ++it) IDs.push_back(*it); // Create the overlap scalar point map and the overlap vector point map numMyElements = IDs.size(); myGlobalElements = 0; if(numMyElements > 0) myGlobalElements = &IDs.at(0); elementSize = 1; overlapScalarPointMap = Teuchos::rcp(new Epetra_BlockMap(numGlobalElements, numMyElements, myGlobalElements, elementSize, indexBase, globalOwnedScalarPointMap->Comm())); elementSize = 3; overlapVectorPointMap = Teuchos::rcp(new Epetra_BlockMap(numGlobalElements, numMyElements, myGlobalElements, elementSize, indexBase, globalOwnedScalarPointMap->Comm())); // Invalidate the importers oneDimensionalImporter = Teuchos::RCP<Epetra_Import>(); threeDimensionalImporter = Teuchos::RCP<Epetra_Import>(); }