bool PLMaterialForce :: propagateInterface(Domain &iDomain, EnrichmentFront &iEnrFront, TipPropagation &oTipProp) { // printf("Entering PLMaterialForce :: propagateInterface().\n"); if ( !iEnrFront.propagationIsAllowed() ) { return false; } // Fetch crack tip data const TipInfo &tipInfo = iEnrFront.giveTipInfo(); // Check if the tip is located in the domain SpatialLocalizer *localizer = iDomain.giveSpatialLocalizer(); FloatArray lCoords, closest; // printf("tipInfo.mGlobalCoord: \n"); tipInfo.mGlobalCoord.printYourself(); if( tipInfo.mGlobalCoord.giveSize() == 0 ) { return false; } localizer->giveElementClosestToPoint(lCoords, closest, tipInfo.mGlobalCoord); if(closest.distance(tipInfo.mGlobalCoord) > 1.0e-9) { // printf("Tip is outside all elements.\n"); return false; } FloatArray matForce; TimeStep *tStep = iDomain.giveEngngModel()->giveCurrentStep(); mpMaterialForceEvaluator->computeMaterialForce(matForce, iDomain, tipInfo, tStep, mRadius); // printf("matForce: "); matForce.printYourself(); if(matForce.giveSize() == 0) { return false; } double forceNorm = matForce.computeNorm(); // printf("forceNorm: %e mCrackPropThreshold: %e\n", forceNorm, mCrackPropThreshold); if(forceNorm < mCrackPropThreshold || forceNorm < 1.0e-20) { return false; } printf("forceNorm: %e mCrackPropThreshold: %e\n", forceNorm, mCrackPropThreshold); printf("Propagating crack in PLMaterialForce :: propagateInterface.\n"); // printf("Tip coord: "); tipInfo.mGlobalCoord.printYourself(); FloatArray dir(matForce); dir.times(1.0/forceNorm); // printf("dir: "); dir.printYourself(); const double cosAngTol = 1.0/sqrt(2.0); if(tipInfo.mTangDir.dotProduct(dir) < cosAngTol) { // Do not allow sharper turns than 45 degrees if( tipInfo.mNormalDir.dotProduct(dir) > 0.0 ) { dir = tipInfo.mTangDir; dir.add(tipInfo.mNormalDir); dir.normalize(); } else { // dir = tipInfo.mNormalDir; // dir.times(-1.0); dir = tipInfo.mTangDir; dir.add(-1.0,tipInfo.mNormalDir); dir.normalize(); } printf("//////////////////////////////////////////// Resticting crack propagation direction.\n"); // printf("tipInfo.mTangDir: "); tipInfo.mTangDir.printYourself(); // printf("dir: "); dir.printYourself(); } // Fill up struct oTipProp.mTipIndex = tipInfo.mTipIndex; oTipProp.mPropagationDir = dir; oTipProp.mPropagationLength = mIncrementLength; return true; }
int PatchIntegrationRule :: SetUpPointsOnTriangle(int nPoints, MaterialMode mode) { int pointsPassed = 0; // TODO: set properly firstLocalStrainIndx = 1; lastLocalStrainIndx = 3; //////////////////////////////////////////// // Allocate Gauss point array // It may happen that the patch contains triangles with // zero area. This does no harm, since their weights in // the quadrature will be zero. However, they invoke additional // computational cost and therefore we want to avoid them. // Thus, count the number of triangles with finite area // and keep only those triangles. double totArea = 0.0; for(size_t i = 0; i < mTriangles.size(); i++) { totArea += mTriangles[i].getArea(); } std::vector<int> triToKeep; const double triTol = ( 1.0e-6 )*totArea; for(size_t i = 0; i < mTriangles.size(); i++) { if( mTriangles[i].getArea() > triTol ) { triToKeep.push_back(i); } } int nPointsTot = nPoints * triToKeep.size(); FloatArray coords_xi1, coords_xi2, weights; this->giveTriCoordsAndWeights(nPoints, coords_xi1, coords_xi2, weights); this->gaussPointArray = new GaussPoint * [ nPointsTot ]; //////////////////////////////////////////// std :: vector< FloatArray >newGPCoord; double parentArea = this->elem->computeArea(); // Loop over triangles for ( int i = 0; i < int( triToKeep.size() ); i++ ) { // TODO: Probably unnecessary to allocate here const FloatArray **coords = new const FloatArray * [ mTriangles [ triToKeep[i] ].giveNrVertices() ]; // this we should put into the function before for ( int k = 0; k < mTriangles [ triToKeep[i] ].giveNrVertices(); k++ ) { coords [ k ] = new FloatArray( ( mTriangles [ triToKeep[i] ].giveVertex(k + 1) ) ); } // Can not be used because it writes to the start of the array instead of appending. // int nPointsTri = GaussIntegrationRule :: SetUpPointsOnTriangle(nPoints, mode); for ( int j = 0; j < nPoints; j++ ) { FloatArray global; GaussPoint * &gp = this->gaussPointArray [ pointsPassed ]; FloatArray *coord = new FloatArray(2); coord->at(1) = coords_xi1.at(j + 1); coord->at(2) = coords_xi2.at(j + 1); gp = new GaussPoint(this, pointsPassed + 1, coord, weights.at(j + 1), mode); mTriInterp.local2global( global, * gp->giveCoordinates(), FEIVertexListGeometryWrapper(mTriangles [ triToKeep[i] ].giveNrVertices(), coords) ); newGPCoord.push_back(global); FloatArray local; this->elem->computeLocalCoordinates(local, global); gp->setCoordinates(local); double refElArea = this->elem->giveParentElSize(); gp->setWeight(2.0 * refElArea * gp->giveWeight() * mTriangles [ triToKeep[i] ].getArea() / parentArea); // update integration weight pointsPassed++; } for ( int k = 0; k < mTriangles [ triToKeep[i] ].giveNrVertices(); k++ ) { delete coords [ k ]; } delete [] coords; } #if PATCH_INT_DEBUG > 0 double time = 0.0; Element *el = this->elem; if(el != NULL) { Domain *dom = el->giveDomain(); if(dom != NULL) { EngngModel *em = dom->giveEngngModel(); if(em != NULL) { TimeStep *ts = em->giveCurrentStep(); if(ts != NULL) { time = ts->giveTargetTime(); } } } } int elIndex = this->elem->giveGlobalNumber(); std :: stringstream str; str << "GaussPointsTime" << time << "El" << elIndex << ".vtk"; std :: string name = str.str(); XFEMDebugTools :: WritePointsToVTK(name, newGPCoord); #endif numberOfIntegrationPoints = pointsPassed; return numberOfIntegrationPoints; }
void LSPrimaryVariableMapper :: mapPrimaryVariables(FloatArray &oU, Domain &iOldDom, Domain &iNewDom, ValueModeType iMode, TimeStep &iTStep) { EngngModel *engngMod = iNewDom.giveEngngModel(); EModelDefaultEquationNumbering num; const int dim = iNewDom.giveNumberOfSpatialDimensions(); int numElNew = iNewDom.giveNumberOfElements(); // Count dofs int numDofsNew = engngMod->giveNumberOfDomainEquations( 1, num ); oU.resize(numDofsNew); oU.zero(); FloatArray du(numDofsNew); du.zero(); FloatArray res(numDofsNew); std :: unique_ptr< SparseMtrx > K; std :: unique_ptr< SparseLinearSystemNM > solver; solver.reset( classFactory.createSparseLinSolver(ST_Petsc, & iOldDom, engngMod) ); if (!solver) { solver.reset( classFactory.createSparseLinSolver(ST_Direct, & iOldDom, engngMod) ); } K.reset( classFactory.createSparseMtrx(solver->giveRecommendedMatrix(true)) ); K->buildInternalStructure( engngMod, iNewDom.giveNumber(), num ); int maxIter = 1; for ( int iter = 0; iter < maxIter; iter++ ) { K->zero(); res.zero(); // Contribution from elements for ( int elIndex = 1; elIndex <= numElNew; elIndex++ ) { StructuralElement *elNew = dynamic_cast< StructuralElement * >( iNewDom.giveElement(elIndex) ); if ( elNew == NULL ) { OOFEM_ERROR("Failed to cast Element new to StructuralElement."); } /////////////////////////////////// // Compute residual // Count element dofs int numElNodes = elNew->giveNumberOfDofManagers(); int numElDofs = 0; for ( int i = 1; i <= numElNodes; i++ ) { numElDofs += elNew->giveDofManager(i)->giveNumberOfDofs(); } FloatArray elRes(numElDofs); elRes.zero(); IntArray elDofsGlob; elNew->giveLocationArray( elDofsGlob, num ); // Loop over Gauss points for ( int intRuleInd = 0; intRuleInd < elNew->giveNumberOfIntegrationRules(); intRuleInd++ ) { for ( GaussPoint *gp: *elNew->giveIntegrationRule(intRuleInd) ) { // New N-matrix FloatMatrix NNew; elNew->computeNmatrixAt(gp->giveNaturalCoordinates(), NNew); ////////////// // Global coordinates of GP const FloatArray &localCoord = gp->giveNaturalCoordinates(); FloatArray globalCoord; elNew->computeGlobalCoordinates(globalCoord, localCoord); ////////////// // Localize element and point in the old domain FloatArray localCoordOld(dim), pointCoordOld(dim); StructuralElement *elOld = dynamic_cast< StructuralElement * >( iOldDom.giveSpatialLocalizer()->giveElementClosestToPoint(localCoordOld, pointCoordOld, globalCoord, 0) ); if ( elOld == NULL ) { OOFEM_ERROR("Failed to cast Element old to StructuralElement."); } // Compute N-Matrix for the old element FloatMatrix NOld; elOld->computeNmatrixAt(localCoordOld, NOld); // Fetch nodal displacements for the new element FloatArray nodeDispNew( elDofsGlob.giveSize() ); int dofsPassed = 1; for ( int elNode: elNew->giveDofManArray() ) { // DofManager *dMan = iNewDom.giveNode(elNode); DofManager *dMan = iNewDom.giveDofManager(elNode); for ( Dof *dof: *dMan ) { if ( elDofsGlob.at(dofsPassed) != 0 ) { nodeDispNew.at(dofsPassed) = oU.at( elDofsGlob.at(dofsPassed) ); } else { if ( dof->hasBc(& iTStep) ) { nodeDispNew.at(dofsPassed) = dof->giveBcValue(iMode, & iTStep); } } dofsPassed++; } } FloatArray newDisp; newDisp.beProductOf(NNew, nodeDispNew); // Fetch nodal displacements for the old element FloatArray nodeDispOld; dofsPassed = 1; IntArray elDofsGlobOld; elOld->giveLocationArray( elDofsGlobOld, num ); // elOld->computeVectorOf(iMode, &(iTStep), nodeDisp); int numElNodesOld = elOld->giveNumberOfDofManagers(); for(int nodeIndOld = 1; nodeIndOld <= numElNodesOld; nodeIndOld++) { DofManager *dManOld = elOld->giveDofManager(nodeIndOld); for ( Dof *dof: *dManOld ) { if ( elDofsGlobOld.at(dofsPassed) != 0 ) { FloatArray dofUnknowns; if(dof->giveEqn() > 0) { dof->giveUnknowns(dofUnknowns, iMode, &iTStep); #ifdef DEBUG if(!dofUnknowns.isFinite()) { OOFEM_ERROR("!dofUnknowns.isFinite()") } if(dofUnknowns.giveSize() < 1) { OOFEM_ERROR("dofUnknowns.giveSize() < 1") } #endif nodeDispOld.push_back(dofUnknowns.at(1)); } else { // TODO: Why does this case occur? nodeDispOld.push_back(0.0); } } else { if ( dof->hasBc(& iTStep) ) { // printf("hasBC.\n"); #ifdef DEBUG if(!std::isfinite(dof->giveBcValue(iMode, & iTStep))) { OOFEM_ERROR("!std::isfinite(dof->giveBcValue(iMode, & iTStep))") } #endif nodeDispOld.push_back( dof->giveBcValue(iMode, & iTStep) ); } else { // printf("Unhandled case in LSPrimaryVariableMapper :: mapPrimaryVariables().\n"); nodeDispOld.push_back( 0.0 ); } } dofsPassed++; } }
int PatchIntegrationRule :: SetUpPointsOnWedge(int nPointsTri, int nPointsDepth, MaterialMode mode) { //int pointsPassed = 0; // TODO: set properly firstLocalStrainIndx = 1; lastLocalStrainIndx = 3; double totArea = 0.0; for ( size_t i = 0; i < mTriangles.size(); i++ ) { totArea += mTriangles [ i ].getArea(); } std :: vector< int >triToKeep; const double triTol = ( 1.0e-6 ) * totArea; for ( size_t i = 0; i < mTriangles.size(); i++ ) { if ( mTriangles [ i ].getArea() > triTol ) { triToKeep.push_back(i); } } int nPointsTot = nPointsTri * nPointsDepth * triToKeep.size(); FloatArray coords_xi1, coords_xi2, coords_xi3, weightsTri, weightsDepth; this->giveTriCoordsAndWeights(nPointsTri, coords_xi1, coords_xi2, weightsTri); this->giveLineCoordsAndWeights(nPointsDepth, coords_xi3, weightsDepth); this->gaussPoints.resize(nPointsTot); std :: vector< FloatArray >newGPCoord; double parentArea = this->elem->computeArea(); int count = 0; // Loop over triangles for ( int i = 0; i < int( triToKeep.size() ); i++ ) { Triangle triangle = mTriangles [ triToKeep [ i ] ]; // global coords of the the triangle verticies std::vector< FloatArray > gCoords( triangle.giveNrVertices() ); for ( int j = 0; j < triangle.giveNrVertices(); j++ ) { gCoords[j] = (triangle.giveVertex(j + 1)); } for ( int k = 1; k <= nPointsTri; k++ ) { for ( int m = 1; m <= nPointsDepth; m++ ) { // local coords in the parent triangle FloatArray *lCoords = new FloatArray(3); lCoords->at(1) = coords_xi1.at(k); lCoords->at(2) = coords_xi2.at(k); lCoords->at(3) = coords_xi3.at(m); double refElArea = 0.5; double oldWeight = weightsTri.at(k) * weightsDepth.at(m); double newWeight = 2.0 * refElArea * oldWeight * triangle.getArea() / parentArea; GaussPoint *gp = new GaussPoint(this, count + 1, lCoords, newWeight, mode); this->gaussPoints[count] = gp; count++; // Compute global gp coordinate in the element from local gp coord in the sub triangle FloatArray global; mTriInterp.local2global( global, * gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(gCoords) ); // Compute local gp coordinate in the element from global gp coord in the element FloatArray local; this->elem->computeLocalCoordinates(local, global); local.at(3) = coords_xi3.at(m); // manually set third coordinate // compute global coords again, since interpolator dosn't give the z-coord this->elem->computeGlobalCoordinates(global, local); gp->setGlobalCoordinates(global); gp->setNaturalCoordinates(local); gp->setSubPatchCoordinates(local); // Store new global gp coord for vtk output newGPCoord.push_back(global); } } //for ( int k = 0; k < mTriangles [ triToKeep [ i ] ].giveNrVertices(); k++ ) { // delete gCoords [ k ]; //} //delete [] gCoords; } XfemManager *xMan = elem->giveDomain()->giveXfemManager(); if ( xMan != NULL ) { if ( xMan->giveVtkDebug() ) { double time = 0.0; Element *el = this->elem; if ( el != NULL ) { Domain *dom = el->giveDomain(); if ( dom != NULL ) { EngngModel *em = dom->giveEngngModel(); if ( em != NULL ) { TimeStep *ts = em->giveCurrentStep(); if ( ts != NULL ) { time = ts->giveTargetTime(); } } } } int elIndex = this->elem->giveGlobalNumber(); std :: stringstream str; str << "GaussPointsTime" << time << "El" << elIndex << ".vtk"; std :: string name = str.str(); XFEMDebugTools :: WritePointsToVTK(name, newGPCoord); } } return this->giveNumberOfIntegrationPoints(); }
void LSPrimaryVariableMapper :: mapPrimaryVariables(FloatArray &oU, Domain &iOldDom, Domain &iNewDom, ValueModeType iMode, TimeStep &iTStep) { EngngModel *engngMod = iNewDom.giveEngngModel(); EModelDefaultEquationNumbering num; const int dim = iNewDom.giveNumberOfSpatialDimensions(); int numElNew = iNewDom.giveNumberOfElements(); // Count dofs int numDofsNew = engngMod->giveNumberOfDomainEquations( 1, num ); oU.resize(numDofsNew); oU.zero(); FloatArray du(numDofsNew); du.zero(); FloatArray res(numDofsNew); #ifdef __PETSC_MODULE PetscSparseMtrx *K = dynamic_cast<PetscSparseMtrx*>( classFactory.createSparseMtrx(SMT_PetscMtrx) ); SparseLinearSystemNM *solver = classFactory.createSparseLinSolver(ST_Petsc, & iOldDom, engngMod); #else SparseMtrx *K = classFactory.createSparseMtrx(SMT_Skyline); SparseLinearSystemNM *solver = classFactory.createSparseLinSolver(ST_Direct, & iOldDom, engngMod); #endif K->buildInternalStructure( engngMod, 1, num ); int maxIter = 1; for ( int iter = 0; iter < maxIter; iter++ ) { K->zero(); res.zero(); // Contribution from elements for ( int elIndex = 1; elIndex <= numElNew; elIndex++ ) { StructuralElement *elNew = dynamic_cast< StructuralElement * >( iNewDom.giveElement(elIndex) ); if ( elNew == NULL ) { OOFEM_ERROR("Failed to cast Element new to StructuralElement."); } /////////////////////////////////// // Compute residual // Count element dofs int numElNodes = elNew->giveNumberOfDofManagers(); int numElDofs = 0; for ( int i = 1; i <= numElNodes; i++ ) { numElDofs += elNew->giveDofManager(i)->giveNumberOfDofs(); } FloatArray elRes(numElDofs); elRes.zero(); IntArray elDofsGlob; elNew->giveLocationArray( elDofsGlob, num ); // Loop over Gauss points for ( int intRuleInd = 0; intRuleInd < elNew->giveNumberOfIntegrationRules(); intRuleInd++ ) { IntegrationRule *iRule = elNew->giveIntegrationRule(intRuleInd); for ( GaussPoint *gp: *iRule ) { // New N-matrix FloatMatrix NNew; elNew->computeNmatrixAt(* ( gp->giveNaturalCoordinates() ), NNew); ////////////// // Global coordinates of GP const int nDofMan = elNew->giveNumberOfDofManagers(); FloatArray Nc; FEInterpolation *interp = elNew->giveInterpolation(); const FloatArray &localCoord = * ( gp->giveNaturalCoordinates() ); interp->evalN( Nc, localCoord, FEIElementGeometryWrapper(elNew) ); const IntArray &elNodes = elNew->giveDofManArray(); FloatArray globalCoord(dim); globalCoord.zero(); for ( int i = 1; i <= nDofMan; i++ ) { DofManager *dMan = elNew->giveDofManager(i); for ( int j = 1; j <= dim; j++ ) { globalCoord.at(j) += Nc.at(i) * dMan->giveCoordinate(j); } } ////////////// // Localize element and point in the old domain FloatArray localCoordOld(dim), pointCoordOld(dim); StructuralElement *elOld = dynamic_cast< StructuralElement * >( iOldDom.giveSpatialLocalizer()->giveElementClosestToPoint(localCoordOld, pointCoordOld, globalCoord, 0) ); if ( elOld == NULL ) { OOFEM_ERROR("Failed to cast Element old to StructuralElement."); } // Compute N-Matrix for the old element FloatMatrix NOld; elOld->computeNmatrixAt(localCoordOld, NOld); // Fetch nodal displacements for the new element FloatArray nodeDispNew( elDofsGlob.giveSize() ); int dofsPassed = 1; for ( int i = 1; i <= elNodes.giveSize(); i++ ) { DofManager *dMan = elNew->giveDofManager(i); for ( Dof *dof: *dMan ) { if ( elDofsGlob.at(dofsPassed) != 0 ) { nodeDispNew.at(dofsPassed) = oU.at( elDofsGlob.at(dofsPassed) ); } else { if ( dof->hasBc(& iTStep) ) { nodeDispNew.at(dofsPassed) = dof->giveBcValue(iMode, & iTStep); } } dofsPassed++; } } FloatArray newDisp; newDisp.beProductOf(NNew, nodeDispNew); // Fetch nodal displacements for the old element FloatArray nodeDispOld; dofsPassed = 1; IntArray elDofsGlobOld; elOld->giveLocationArray( elDofsGlobOld, num ); // elOld->computeVectorOf(iMode, &(iTStep), nodeDisp); int numElNodesOld = elOld->giveNumberOfDofManagers(); for(int nodeIndOld = 1; nodeIndOld <= numElNodesOld; nodeIndOld++) { DofManager *dManOld = elOld->giveDofManager(nodeIndOld); for ( Dof *dof: *dManOld ) { if ( elDofsGlobOld.at(dofsPassed) != 0 ) { FloatArray dofUnknowns; dof->giveUnknowns(dofUnknowns, iMode, &iTStep); #ifdef DEBUG if(!dofUnknowns.isFinite()) { OOFEM_ERROR("!dofUnknowns.isFinite()") } if(dofUnknowns.giveSize() < 1) { OOFEM_ERROR("dofUnknowns.giveSize() < 1") } #endif nodeDispOld.push_back(dofUnknowns.at(1)); } else { if ( dof->hasBc(& iTStep) ) { // printf("hasBC.\n"); #ifdef DEBUG if(!std::isfinite(dof->giveBcValue(iMode, & iTStep))) { OOFEM_ERROR("!std::isfinite(dof->giveBcValue(iMode, & iTStep))") } #endif nodeDispOld.push_back( dof->giveBcValue(iMode, & iTStep) ); } else { // printf("Unhandled case in LSPrimaryVariableMapper :: mapPrimaryVariables().\n"); nodeDispOld.push_back( 0.0 ); } } dofsPassed++; } } FloatArray oldDisp; oldDisp.beProductOf(NOld, nodeDispOld); FloatArray temp, du; #ifdef DEBUG if(!oldDisp.isFinite()) { OOFEM_ERROR("!oldDisp.isFinite()") } if(!newDisp.isFinite()) { OOFEM_ERROR("!newDisp.isFinite()") } #endif du.beDifferenceOf(oldDisp, newDisp); temp.beTProductOf(NNew, du); double dV = elNew->computeVolumeAround(gp); elRes.add(dV, temp); } }
/* * should be called after basic local migration is finalized, * when all local elements are already available */ void NonlocalMaterialWTP :: migrate() { Domain *domain = this->lb->giveDomain(); EngngModel *emodel = domain->giveEngngModel(); int nproc = emodel->giveNumberOfProcesses(); int myrank = emodel->giveRank(); CommunicatorBuff cb(nproc, CBT_dynamic); Communicator com(emodel, &cb, myrank, nproc, CommMode_Dynamic); StaticCommunicationBuffer commBuff(MPI_COMM_WORLD); /* * build domain nonlocal element dependency list. Then exclude local elements - what remains are unsatisfied * remote dependencies that have to be broadcasted and received from partitions owning relevant elements */ int _locsize, i, _i, ie, _size, _globnum, result, nelems = domain->giveNumberOfElements(); int _globsize, _val; Element *elem; std :: set< int >domainElementDepSet; // loop over each element dep list to assemble domain list for ( ie = 1; ie <= nelems; ie++ ) { elem = domain->giveElement(ie); if ( ( elem->giveParallelMode() == Element_local ) ) { _globnum = elem->giveGlobalNumber(); IntArray &iedep = nonlocElementDependencyMap [ _globnum ]; _size = iedep.giveSize(); for ( _i = 1; _i <= _size; _i++ ) { domainElementDepSet.insert( iedep.at(_i) ); } #if NonlocalMaterialWTP_DEBUG_PRINT fprintf(stderr, "[%d] element %d dependency:", myrank, _globnum); for ( _i = 1; _i <= _size; _i++ ) { fprintf( stderr, "%d ", iedep.at(_i) ); } fprintf(stderr, "\n"); #endif } } #if NonlocalMaterialWTP_DEBUG_PRINT fprintf(stderr, "[%d] nonlocal domain dependency:", myrank); for ( int eldep: domainElementDepSet ) { fprintf(stderr, "%d ", eldep); } fprintf(stderr, "\n"); #endif // now exclude local elements (local dependency is always satisfied) for ( _i = 1; _i <= nelems; _i++ ) { elem = domain->giveElement(_i); if ( elem->giveParallelMode() == Element_local ) { domainElementDepSet.erase( elem->giveGlobalNumber() ); } } #if NonlocalMaterialWTP_DEBUG_PRINT fprintf(stderr, "[%d] remote elem wish list:", myrank); for ( int eldep: domainElementDepSet ) { fprintf(stderr, "%d ", eldep); } fprintf(stderr, "\n"); #endif // broadcast remaining elements (unsatisfied domain nonlocal dependency) to remaining partitions _locsize = domainElementDepSet.size() + 1; result = MPI_Allreduce(& _locsize, & _globsize, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD); if ( result != MPI_SUCCESS ) { OOFEM_ERROR("MPI_Allreduce to determine broadcast buffer size failed"); } commBuff.resize( commBuff.givePackSize(MPI_INT, _globsize) ); // remote domain wish list std :: set< int >remoteWishSet; toSendList.resize(nproc); for ( i = 0; i < nproc; i++ ) { // loop over partitions commBuff.init(); toSendList [ i ].clear(); if ( i == myrank ) { // current domain has to send its receive wish list to all domains commBuff.packInt(_locsize); for ( int eldep: domainElementDepSet ) { commBuff.packInt(eldep); } result = commBuff.bcast(i); } else { // unpack remote domain wish list remoteWishSet.clear(); result = commBuff.bcast(i); // unpack size commBuff.unpackInt(_size); for ( _i = 1; _i < _size; _i++ ) { commBuff.unpackInt(_val); remoteWishSet.insert(_val); } // determine which local elements are to be sent to remotepartition for ( _i = 1; _i <= nelems; _i++ ) { elem = domain->giveElement(_i); if ( elem->giveParallelMode() == Element_local ) { if ( remoteWishSet.find( elem->giveGlobalNumber() ) != remoteWishSet.end() ) { // store local element number toSendList [ i ].push_back(_i); } } } } } // end loop over partitions broadcast #if NonlocalMaterialWTP_DEBUG_PRINT for ( i = 0; i < nproc; i++ ) { // loop over partitions // print some info fprintf(stderr, "[%d] elements scheduled for mirroring at [%d]:", myrank, i); for ( int elnum: toSendList [ i ] ) { fprintf( stderr, "%d[%d] ", elnum, domain->giveElement(elnum)->giveGlobalNumber() ); } fprintf(stderr, "\n"); } #endif com.packAllData(this, domain, & NonlocalMaterialWTP :: packRemoteElements); com.initExchange(MIGRATE_REMOTE_ELEMENTS_TAG); com.unpackAllData(this, domain, & NonlocalMaterialWTP :: unpackRemoteElements); com.finishExchange(); domain->commitTransactions( domain->giveTransactionManager() ); #ifdef __VERBOSE_PARALLEL VERBOSEPARALLEL_PRINT("NonlocalMaterialWTP::migrate", "Finished migrating remote elements", myrank); #endif }