// Update grid momenta and transport rates void UpdateMomentaTask::Execute(void) { CommonException *umErr = NULL; #pragma omp parallel for for(int i=1;i<=nnodes;i++) { NodalPoint *ndptr = nd[i]; ndptr->UpdateMomentaOnNode(timestep); // get grid transport rates (update transport properties when particle state updated) // do first so both material and crack contact will have actual rates TransportTask *nextTransport=transportTasks; while(nextTransport!=NULL) nextTransport=nextTransport->TransportRates(ndptr,timestep); // material contact if(fmobj->multiMaterialMode) { try { ndptr->MaterialContactOnNode(timestep,UPDATE_MOMENTUM_CALL,NULL,NULL); } catch(CommonException err) { if(umErr==NULL) { #pragma omp critical umErr = new CommonException(err); } } } } // throw error now if(umErr!=NULL) throw *umErr; // adjust momenta and forces for crack contact on known nodes CrackNode::CrackContactTask4(timestep); }
// Get mass matrix, find dimensionless particle locations, // and find grid momenta void MassAndMomentumTask::Execute(void) { CommonException *massErr = NULL; double fn[maxShapeNodes],xDeriv[maxShapeNodes],yDeriv[maxShapeNodes],zDeriv[maxShapeNodes]; int nds[maxShapeNodes]; #pragma mark ... UPDATE RIGID CONTACT PARTICLES // Set rigid BC contact material velocities first (so loop can be parallel) // GetVectorSetting() uses globals and therefore can't be parallel if(nmpmsRC>nmpmsNR) { Vector newvel; bool hasDir[3]; for(int p=nmpmsNR;p<nmpmsRC;p++) { MPMBase *mpmptr = mpm[p]; const RigidMaterial *matID = (RigidMaterial *)theMaterials[mpm[p]->MatID()]; if(matID->GetVectorSetting(&newvel,hasDir,mtime,&mpmptr->pos)) { // change velocity if functions being used, otherwise keep velocity constant if(hasDir[0]) mpmptr->vel.x = newvel.x; if(hasDir[1]) mpmptr->vel.y = newvel.y; if(hasDir[2]) mpmptr->vel.z = newvel.z; } } } // loop over non-rigid and rigid contact particles - this parallel part changes only particle p // mass, momenta, etc are stored on ghost nodes, which are sent to real nodes in next non-parallel loop //for(int pn=0;pn<4;pn++) #pragma omp parallel private(fn,xDeriv,yDeriv,zDeriv,nds) { // thread for patch pn int pn = GetPatchNumber(); // in case 2D planar for(int i=0;i<maxShapeNodes;i++) zDeriv[i] = 0.; #pragma mark ... EXTRAPOLATE NONRIGID PARTICLES try { for(int block=FIRST_NONRIGID;block<=FIRST_RIGID_CONTACT;block++) { MPMBase *mpmptr = patches[pn]->GetFirstBlockPointer(block); while(mpmptr!=NULL) { const MaterialBase *matID = theMaterials[mpmptr->MatID()]; // material object for this particle int matfld = matID->GetField(); // material velocity field // get nodes and shape function for material point p int i,numnds; const ElementBase *elref = theElements[mpmptr->ElemID()]; // element containing this particle if(fmobj->multiMaterialMode) elref->GetShapeGradients(&numnds,fn,nds,xDeriv,yDeriv,zDeriv,mpmptr); else elref->GetShapeFunctions(&numnds,fn,nds,mpmptr); // Add particle property to each node in the element short vfld; NodalPoint *ndptr; for(i=1;i<=numnds;i++) { // get node pointer ndptr = GetNodePointer(pn,nds[i]); // momentum vector (and allocate velocity field if needed) vfld = mpmptr->vfld[i]; ndptr->AddMassMomentum(mpmptr,vfld,matfld,fn[i],xDeriv[i],yDeriv[i],zDeriv[i], 1,block==FIRST_NONRIGID); } // next material point mpmptr = (MPMBase *)mpmptr->GetNextObject(); } } } catch(CommonException err) { if(massErr==NULL) { #pragma omp critical massErr = new CommonException(err); } } catch(...) { cout << "Unknown exception in MassAndMomentumTask()" << endl; } } // throw now - only possible error if too many CPDI nodes in 3D if(massErr!=NULL) throw *massErr; // reduction of ghost node forces to real nodes int totalPatches = fmobj->GetTotalNumberOfPatches(); if(totalPatches>1) { for(int pn=0;pn<totalPatches;pn++) patches[pn]->MassAndMomentumReduction(); } #pragma mark ... RIGID BOUNDARY CONDITIONS // undo dynamic velocity, temp, and conc BCs from rigid materials // and get pointer to first empty one in reuseRigid...BC UnsetRigidBCs((BoundaryCondition **)&firstVelocityBC,(BoundaryCondition **)&lastVelocityBC, (BoundaryCondition **)&firstRigidVelocityBC,(BoundaryCondition **)&reuseRigidVelocityBC); UnsetRigidBCs((BoundaryCondition **)&firstTempBC,(BoundaryCondition **)&lastTempBC, (BoundaryCondition **)&firstRigidTempBC,(BoundaryCondition **)&reuseRigidTempBC); UnsetRigidBCs((BoundaryCondition **)&firstConcBC,(BoundaryCondition **)&lastConcBC, (BoundaryCondition **)&firstRigidConcBC,(BoundaryCondition **)&reuseRigidConcBC); // For Rigid BC materials create velocity BC on each node in the element for(int p=nmpmsRC;p<nmpms;p++) { MPMBase *mpmptr = mpm[p]; // pointer int matid0 = mpmptr->MatID(); const MaterialBase *matID = theMaterials[matid0]; // material object for this particle RigidMaterial *rigid=(RigidMaterial *)matID; const ElementBase *elref = theElements[mpmptr->ElemID()]; // element containing this particle int numnds=elref->NumberNodes(); double rvalue; for(int i=1;i<=numnds;i++) { int mi=elref->nodes[i-1]; // 1 based node // look for setting function in one to three directions // GetVectorSetting() returns true if function has set the velocity, otherwise it return FALSE bool hasDir[3]; Vector rvel; if(rigid->GetVectorSetting(&rvel,hasDir,mtime,&mpmptr->pos)) { // velocity set by 1 to 3 functions as determined by hasDir[i] if(hasDir[0]) { mpmptr->vel.x = rvel.x; SetRigidBCs(mi,matid0,X_DIRECTION,rvel.x,0.,rigid->mirrored, (BoundaryCondition **)&firstVelocityBC,(BoundaryCondition **)&lastVelocityBC, (BoundaryCondition **)&firstRigidVelocityBC,(BoundaryCondition **)&reuseRigidVelocityBC); } if(hasDir[1]) { mpmptr->vel.y = rvel.y; SetRigidBCs(mi,matid0,Y_DIRECTION,rvel.y,0.,rigid->mirrored, (BoundaryCondition **)&firstVelocityBC,(BoundaryCondition **)&lastVelocityBC, (BoundaryCondition **)&firstRigidVelocityBC,(BoundaryCondition **)&reuseRigidVelocityBC); } if(hasDir[2]) { mpmptr->vel.z = rvel.z; SetRigidBCs(mi,matid0,Z_DIRECTION,rvel.z,0.,rigid->mirrored, (BoundaryCondition **)&firstVelocityBC,(BoundaryCondition **)&lastVelocityBC, (BoundaryCondition **)&firstRigidVelocityBC,(BoundaryCondition **)&reuseRigidVelocityBC); } } else { // velocity set by particle velocity in selected directions if(rigid->RigidDirection(X_DIRECTION)) { SetRigidBCs(mi,matid0,X_DIRECTION,mpmptr->vel.x,0.,rigid->mirrored, (BoundaryCondition **)&firstVelocityBC,(BoundaryCondition **)&lastVelocityBC, (BoundaryCondition **)&firstRigidVelocityBC,(BoundaryCondition **)&reuseRigidVelocityBC); } if(rigid->RigidDirection(Y_DIRECTION)) { SetRigidBCs(mi,matid0,Y_DIRECTION,mpmptr->vel.y,0.,rigid->mirrored, (BoundaryCondition **)&firstVelocityBC,(BoundaryCondition **)&lastVelocityBC, (BoundaryCondition **)&firstRigidVelocityBC,(BoundaryCondition **)&reuseRigidVelocityBC); } if(rigid->RigidDirection(Z_DIRECTION)) { SetRigidBCs(mi,matid0,Z_DIRECTION,mpmptr->vel.z,0.,rigid->mirrored, (BoundaryCondition **)&firstVelocityBC,(BoundaryCondition **)&lastVelocityBC, (BoundaryCondition **)&firstRigidVelocityBC,(BoundaryCondition **)&reuseRigidVelocityBC); } } // temperature if(rigid->RigidTemperature()) { if(rigid->GetValueSetting(&rvalue,mtime,&mpmptr->pos)) mpmptr->pTemperature=rvalue; SetRigidBCs(mi,matid0,TEMP_DIRECTION,mpmptr->pTemperature,0.,0, (BoundaryCondition **)&firstTempBC,(BoundaryCondition **)&lastTempBC, (BoundaryCondition **)&firstRigidTempBC,(BoundaryCondition **)&reuseRigidTempBC); } // concentration if(rigid->RigidConcentration()) { if(rigid->GetValueSetting(&rvalue,mtime,&mpmptr->pos)) mpmptr->pConcentration=rvalue; SetRigidBCs(mi,matid0,CONC_DIRECTION,mpmptr->pConcentration,0.,0, (BoundaryCondition **)&firstConcBC,(BoundaryCondition **)&lastConcBC, (BoundaryCondition **)&firstRigidConcBC,(BoundaryCondition **)&reuseRigidConcBC); } } } // if any left over rigid BCs, delete them now RemoveRigidBCs((BoundaryCondition **)&firstVelocityBC,(BoundaryCondition **)&lastVelocityBC,(BoundaryCondition **)&firstRigidVelocityBC); RemoveRigidBCs((BoundaryCondition **)&firstTempBC,(BoundaryCondition **)&lastTempBC,(BoundaryCondition **)&firstRigidTempBC); RemoveRigidBCs((BoundaryCondition **)&firstConcBC,(BoundaryCondition **)&lastConcBC,(BoundaryCondition **)&firstRigidConcBC); #ifdef COMBINE_RIGID_MATERIALS bool combineRigid = firstCrack!=NULL && fmobj->multiMaterialMode && fmobj->hasRigidContactParticles; #endif #pragma mark ... POST EXTRAPOLATION TASKS // Post mass and momentum extrapolation calculations on nodes #pragma omp parallel { // variables for each thread CrackNode *firstCrackNode=NULL,*lastCrackNode=NULL; MaterialInterfaceNode *firstInterfaceNode=NULL,*lastInterfaceNode=NULL; // Each pass in this loop should be independent #pragma omp for nowait for(int i=1;i<=nnodes;i++) { // node reference NodalPoint *ndptr = nd[i]; try { #ifdef COMBINE_RIGID_MATERIALS // combine rigid fields if necessary if(combineRigid) ndptr->CopyRigidParticleField(); #endif // Get total nodal masses and count materials if multimaterial mode ndptr->CalcTotalMassAndCount(); // multimaterial contact if(fmobj->multiMaterialMode) ndptr->MaterialContactOnNode(timestep,MASS_MOMENTUM_CALL,&firstInterfaceNode,&lastInterfaceNode); // crack contact if(firstCrack!=NULL) ndptr->CrackContact(FALSE,0.,&firstCrackNode,&lastCrackNode); // get transport values on nodes TransportTask *nextTransport=transportTasks; while(nextTransport!=NULL) nextTransport = nextTransport->GetNodalValue(ndptr); } catch(CommonException err) { if(massErr==NULL) { #pragma omp critical massErr = new CommonException(err); } } } #pragma omp critical { // link up crack nodes if(lastCrackNode != NULL) { if(CrackNode::currentCNode != NULL) firstCrackNode->SetPrevBC(CrackNode::currentCNode); CrackNode::currentCNode = lastCrackNode; } // link up interface nodes if(lastInterfaceNode != NULL) { if(MaterialInterfaceNode::currentIntNode != NULL) firstInterfaceNode->SetPrevBC(MaterialInterfaceNode::currentIntNode); MaterialInterfaceNode::currentIntNode = lastInterfaceNode; } } } // throw any errors if(massErr!=NULL) throw *massErr; #pragma mark ... IMPOSE BOUNDARY CONDITIONS // Impose transport BCs and extrapolate gradients to the particles TransportTask *nextTransport=transportTasks; while(nextTransport!=NULL) { nextTransport->ImposeValueBCs(mtime); nextTransport = nextTransport->GetGradients(mtime); } // locate BCs with reflected nodes if(firstRigidVelocityBC!=NULL) { NodalVelBC *nextBC=firstRigidVelocityBC; double mstime=1000.*mtime; //cout << "# Find Reflected Nodes" << endl; while(nextBC!=NULL) nextBC = nextBC->SetMirroredVelBC(mstime); } // used to call class methods for material contact and crack contact here // Impose velocity BCs NodalVelBC::GridMomentumConditions(TRUE); }
// Get mass matrix, find dimensionless particle locations, // and find grid momenta // throws CommonException() void PostExtrapolationTask::Execute(void) { CommonException *massErr = NULL; bool combineRigid = firstCrack!=NULL && fmobj->multiMaterialMode && fmobj->hasRigidContactParticles; // Post mass and momentum extrapolation calculations on nodes #pragma omp parallel { // variables for each thread CrackNode *firstCrackNode=NULL,*lastCrackNode=NULL; MaterialInterfaceNode *firstInterfaceNode=NULL,*lastInterfaceNode=NULL; // Each pass in this loop should be independent #pragma omp for nowait for(int i=1;i<=nnodes;i++) { // node reference NodalPoint *ndptr = nd[i]; try { // combine rigid fields if necessary if(combineRigid) ndptr->CopyRigidParticleField(); // Get total nodal masses and count materials if multimaterial mode ndptr->CalcTotalMassAndCount(); // multimaterial contact if(fmobj->multiMaterialMode) ndptr->MaterialContactOnNode(timestep,MASS_MOMENTUM_CALL,&firstInterfaceNode,&lastInterfaceNode); // crack contact if(firstCrack!=NULL) ndptr->CrackContact(FALSE,0.,&firstCrackNode,&lastCrackNode); // get transport values on nodes TransportTask *nextTransport=transportTasks; while(nextTransport!=NULL) nextTransport = nextTransport->GetNodalValue(ndptr); } catch(std::bad_alloc&) { if(massErr==NULL) { #pragma omp critical (error) massErr = new CommonException("Memory error","PostExtrapolationTask::Execute"); } } catch(...) { if(massErr==NULL) { #pragma omp critical (error) massErr = new CommonException("Unexpected error","PostExtrapolationTask::Execute"); } } } #pragma omp critical (linknodes) { // link up crack nodes if(lastCrackNode != NULL) { if(CrackNode::currentCNode != NULL) firstCrackNode->SetPrevBC(CrackNode::currentCNode); CrackNode::currentCNode = lastCrackNode; } // link up interface nodes if(lastInterfaceNode != NULL) { if(MaterialInterfaceNode::currentIntNode != NULL) firstInterfaceNode->SetPrevBC(MaterialInterfaceNode::currentIntNode); MaterialInterfaceNode::currentIntNode = lastInterfaceNode; } } } // throw any errors if(massErr!=NULL) throw *massErr; #pragma mark ... IMPOSE BOUNDARY CONDITIONS // Impose transport BCs and extrapolate gradients to the particles TransportTask *nextTransport=transportTasks; while(nextTransport!=NULL) { nextTransport->ImposeValueBCs(mtime); nextTransport = nextTransport->GetGradients(mtime); } // locate BCs with reflected nodes if(firstRigidVelocityBC!=NULL) { NodalVelBC *nextBC=firstRigidVelocityBC; //cout << "# Find Reflected Nodes" << endl; while(nextBC!=NULL) nextBC = nextBC->SetMirroredVelBC(mtime); } // used to call class methods for material contact and crack contact here // Impose velocity BCs NodalVelBC::GridMomentumConditions(TRUE); }