// Update particle position, velocity, temp, and conc // throws CommonException() void UpdateParticlesTask::Execute(void) { CommonException *upErr = NULL; #ifdef CONST_ARRAYS int ndsArray[MAX_SHAPE_NODES]; double fn[MAX_SHAPE_NODES]; #else int ndsArray[maxShapeNodes]; double fn[maxShapeNodes]; #endif // Damping terms on the grid or on the particles // particleAlpha = (1-beta)/dt + pdamping(t) // gridAlpha = -m*(1-beta)/dt + damping(t) double particleAlpha = bodyFrc.GetParticleDamping(mtime); double gridAlpha = bodyFrc.GetDamping(mtime); // nonPICGridAlpha = damping(t) // globalPIC = (1-beta)/dt double nonPICGridAlpha = bodyFrc.GetNonPICDamping(mtime); double globalPIC = bodyFrc.GetPICDamping(); // Update particle position, velocity, temp, and conc #pragma omp parallel for private(ndsArray,fn) for(int p=0;p<nmpmsNR;p++) { MPMBase *mpmptr = mpm[p]; try { // get shape functions const ElementBase *elemRef = theElements[mpmptr->ElemID()]; int *nds = ndsArray; elemRef->GetShapeFunctions(fn,&nds,mpmptr); int numnds = nds[0]; // Update particle position and velocity const MaterialBase *matRef=theMaterials[mpmptr->MatID()]; int matfld=matRef->GetField(); // Allow material to override global settings double localParticleAlpha = particleAlpha; double localGridAlpha = gridAlpha; matRef->GetMaterialDamping(localParticleAlpha,localGridAlpha,nonPICGridAlpha,globalPIC); // data structure for extrapolations GridToParticleExtrap *gp = new GridToParticleExtrap; // acceleration on the particle gp->acc = mpmptr->GetAcc(); ZeroVector(gp->acc); // extrapolate nodal velocity from grid to particle ZeroVector(&gp->vgpnp1); // only two possible transport tasks double rate[2]; rate[0] = rate[1] = 0.; int task; TransportTask *nextTransport; // Loop over nodes for(int i=1;i<=numnds;i++) { // increment velocity and acceleraton const NodalPoint *ndptr = nd[nds[i]]; short vfld = (short)mpmptr->vfld[i]; // increment ndptr->IncrementDelvaTask5(vfld,matfld,fn[i],gp); #ifdef CHECK_NAN // conditionally compiled check for nan velocities if(gp->vgpnp1.x!=gp->vgpnp1.x || gp->vgpnp1.y!=gp->vgpnp1.y || gp->vgpnp1.z!=gp->vgpnp1.z) { #pragma omp critical (output) { cout << "\n# UpdateParticlesTask::Execute: bad material velocity field for vfld=" << vfld << "matfld=" << matfld << " fn[i]=" << fn[i] << endl;; PrintVector("# Particle velocity vgpn1 = ",&gp->vgpnp1); cout << endl; ndptr->Describe(); } } #endif // increment transport rates nextTransport=transportTasks; task=0; while(nextTransport!=NULL) nextTransport=nextTransport->IncrementTransportRate(ndptr,fn[i],rate[task++]); } // Find grid damping acceleration parts = ag*Vgp(n) = ag*(Vgp(n+1) - Agp(n)*dt) Vector accExtra = gp->vgpnp1; AddScaledVector(&accExtra, gp->acc, -timestep); ScaleVector(&accExtra,localGridAlpha); // update position, and must be before velocity update because updates need initial velocity // This section does second order update mpmptr->MovePosition(timestep,&gp->vgpnp1,&accExtra,localParticleAlpha); // update velocity in mm/sec mpmptr->MoveVelocity(timestep,&accExtra); // update transport values nextTransport=transportTasks; task=0; while(nextTransport!=NULL) nextTransport=nextTransport->MoveTransportValue(mpmptr,timestep,rate[task++]); // energy coupling here adds adiabtic temperature rise if(ConductionTask::adiabatic) { double dTad = mpmptr->GetBufferClear_dTad(); // in K mpmptr->pTemperature += dTad; // in K } // delete grid to particle extrap data delete gp; } catch(CommonException& err) { if(upErr==NULL) { #pragma omp critical (error) upErr = new CommonException(err); } } catch(std::bad_alloc&) { if(upErr==NULL) { #pragma omp critical (error) upErr = new CommonException("Memory error","UpdateParticlesTask::Execute"); } } catch(...) { if(upErr==NULL) { #pragma omp critical (error) upErr = new CommonException("Unexpected error","UpdateParticlesTask::Execute"); } } } // throw any errors if(upErr!=NULL) throw *upErr; // rigid materials move at their current velocity for(int p=nmpmsNR;p<nmpms;p++) { mpm[p]->MovePosition(timestep); } }
// Update particle position, velocity, temp, and conc void UpdateParticlesTask::Execute(void) { CommonException *upErr = NULL; int numnds,nds[maxShapeNodes]; double fn[maxShapeNodes]; Vector vgpnp1; // Damping terms on the grid or on the particles // particleAlpha = alpha(PIC)/dt + pdamping(t) // gridAlpha = -alpha(PIC)/dt + damping(t) double particleAlpha = bodyFrc.GetParticleDamping(mtime); double gridAlpha = bodyFrc.GetDamping(mtime); // copy to local values (OSParticulas uses to implement material damping) double localParticleAlpha = particleAlpha; double localGridAlpha = gridAlpha; // Update particle position, velocity, temp, and conc #pragma omp parallel for private(numnds,nds,fn,vgpnp1) for(int p=0;p<nmpmsNR;p++) { MPMBase *mpmptr = mpm[p]; try { // get shape functions const ElementBase *elemRef = theElements[mpmptr->ElemID()]; elemRef->GetShapeFunctions(&numnds,fn,nds,mpmptr); // Update particle position and velocity const MaterialBase *matRef=theMaterials[mpmptr->MatID()]; int matfld=matRef->GetField(); Vector *acc=mpmptr->GetAcc(); ZeroVector(acc); ZeroVector(&vgpnp1); double rate[2]; // only two possible transport tasks rate[0] = rate[1] = 0.; int task; TransportTask *nextTransport; short vfld; // Loop over nodes for(int i=1;i<=numnds;i++) { // increment velocity and acceleraton const NodalPoint *ndptr = nd[nds[i]]; vfld = (short)mpmptr->vfld[i]; ndptr->IncrementDelvaTask5(vfld,matfld,fn[i],&vgpnp1,acc); #ifdef CHECK_NAN if(vgpnp1.x!=vgpnp1.x || vgpnp1.y!=vgpnp1.y || vgpnp1.z!=vgpnp1.z) { cout << "\n# UpdateParticlesTask::Execute: bad material velocity field for vfld = " << vfld << endl; ndptr->Describe(); } #endif // increment transport rates nextTransport=transportTasks; task=0; while(nextTransport!=NULL) nextTransport=nextTransport->IncrementTransportRate(ndptr,fn[i],rate[task++]); } // Find vgpn Vector vgpn = vgpnp1; AddScaledVector(&vgpn,acc,-timestep); // find effective grid acceleration and velocity AddScaledVector(acc,&vgpn,-localGridAlpha); AddScaledVector(&vgpnp1,&vgpn,-timestep*localGridAlpha); // update position, and must be before velocity update because updates need initial velocity // This section does second order update mpmptr->MovePosition(timestep,&vgpnp1,0.5*timestep,localParticleAlpha); // update velocity in mm/sec mpmptr->MoveVelocity(timestep,localParticleAlpha); // update transport values nextTransport=transportTasks; task=0; while(nextTransport!=NULL) nextTransport=nextTransport->MoveTransportValue(mpmptr,timestep,rate[task++]); // thermal ramp thermal.UpdateParticleTemperature(&mpmptr->pTemperature,timestep); // energy coupling here if conduction not doing it if(!ConductionTask::active) { if(ConductionTask::adiabatic) { double energy = mpmptr->GetDispEnergy(); // in nJ/g double Cv = matRef->GetHeatCapacity(mpmptr); // in nJ/(g-K) mpmptr->pTemperature += energy/Cv; // in K } mpmptr->SetDispEnergy(0.); } } catch(CommonException err) { if(upErr==NULL) { #pragma omp critical upErr = new CommonException(err); } } } // throw any errors if(upErr!=NULL) throw *upErr; // rigid materials move at their current velocity for(int p=nmpmsNR;p<nmpms;p++) { mpm[p]->MovePosition(timestep,&mpm[p]->vel,0.,0.); } }