int XmlGspInterface::readFile(const QString &fileName) { if(XMLQtInterface::readFile(fileName) == 0) return 0; QFileInfo fi(fileName); QString path = (fi.path().length() > 3) ? QString(fi.path() + "/") : fi.path(); QDomDocument doc("OGS-PROJECT-DOM"); doc.setContent(_fileData); QDomElement docElement = doc.documentElement(); //OpenGeoSysProject if (docElement.nodeName().compare("OpenGeoSysProject")) { ERR("XmlGspInterface::readFile(): Unexpected XML root."); return 0; } QDomNodeList fileList = docElement.childNodes(); for(int i = 0; i < fileList.count(); i++) { const QString file_node(fileList.at(i).nodeName()); if (file_node.compare("geo") == 0) { XmlGmlInterface gml(*(_project.getGEOObjects())); const QDomNodeList childList = fileList.at(i).childNodes(); for(int j = 0; j < childList.count(); j++) { const QDomNode child_node (childList.at(j)); if (child_node.nodeName().compare("file") == 0) { DBUG("XmlGspInterface::readFile(): path: \"%s\".", path.data()); DBUG("XmlGspInterface::readFile(): file name: \"%s\".", (child_node.toElement().text()).data()); gml.readFile(QString(path + child_node.toElement().text())); } } } else if (file_node.compare("stn") == 0) { XmlStnInterface stn(*(_project.getGEOObjects())); const QDomNodeList childList = fileList.at(i).childNodes(); for(int j = 0; j < childList.count(); j++) if (childList.at(j).nodeName().compare("file") == 0) stn.readFile(QString(path + childList.at(j).toElement().text())); } else if (file_node.compare("msh") == 0) { const std::string msh_name = path.toStdString() + fileList.at(i).toElement().text().toStdString(); MeshLib::Mesh* msh = FileIO::readMeshFromFile(msh_name); if (msh) _project.addMesh(msh); } } return 1; }
bool XmlGspInterface::write() { GeoLib::GEOObjects* geoObjects = _project.getGEOObjects(); QFileInfo fi(QString::fromStdString(_filename)); std::string path((fi.absolutePath()).toStdString() + "/"); _out << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"; // xml definition _out << "<?xml-stylesheet type=\"text/xsl\" href=\"OpenGeoSysProject.xsl\"?>\n\n"; // stylefile definition QDomDocument doc("OGS-PROJECT-DOM"); QDomElement root = doc.createElement("OpenGeoSysProject"); root.setAttribute( "xmlns:ogs", "http://www.opengeosys.org" ); root.setAttribute( "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance" ); root.setAttribute( "xsi:noNamespaceSchemaLocation", "http://www.opengeosys.org/images/xsd/OpenGeoSysProject.xsd" ); doc.appendChild(root); // GML std::vector<std::string> geoNames; geoObjects->getGeometryNames(geoNames); for (std::vector<std::string>::const_iterator it(geoNames.begin()); it != geoNames.end(); ++it) { // write GLI file XmlGmlInterface gml(*geoObjects); std::string name(*it); gml.setNameForExport(name); if (gml.writeToFile(std::string(path + name + ".gml"))) { // write entry in project file QDomElement geoTag = doc.createElement("geo"); root.appendChild(geoTag); QDomElement fileNameTag = doc.createElement("file"); geoTag.appendChild(fileNameTag); QDomText fileNameText = doc.createTextNode(QString::fromStdString(name + ".gml")); fileNameTag.appendChild(fileNameText); } } // MSH const std::vector<MeshLib::Mesh*> msh_vec = _project.getMeshObjects(); for (std::vector<MeshLib::Mesh*>::const_iterator it(msh_vec.begin()); it != msh_vec.end(); ++it) { // write mesh file Legacy::MeshIO meshIO; meshIO.setMesh(*it); std::string fileName(path + (*it)->getName()); meshIO.writeToFile(fileName); // write entry in project file QDomElement mshTag = doc.createElement("msh"); root.appendChild(mshTag); QDomElement fileNameTag = doc.createElement("file"); mshTag.appendChild(fileNameTag); QDomText fileNameText = doc.createTextNode(QString::fromStdString((*it)->getName())); fileNameTag.appendChild(fileNameText); } // STN std::vector<std::string> stnNames; geoObjects->getStationVectorNames(stnNames); for (std::vector<std::string>::const_iterator it(stnNames.begin()); it != stnNames.end(); ++it) { // write STN file XmlStnInterface stn(*geoObjects); std::string name(*it); stn.setNameForExport(name); if (stn.writeToFile(path + name + ".stn")) { // write entry in project file QDomElement geoTag = doc.createElement("stn"); root.appendChild(geoTag); QDomElement fileNameTag = doc.createElement("file"); geoTag.appendChild(fileNameTag); QDomText fileNameText = doc.createTextNode(QString::fromStdString(name + ".stn")); fileNameTag.appendChild(fileNameText); } else ERR("XmlGspInterface::writeFile(): Error writing stn-file \"%s\".", name.c_str()); } std::string xml = doc.toString().toStdString(); _out << xml; return true; }
int XmlGspInterface::readFile(const QString &fileName) { QFile* file = new QFile(fileName); QFileInfo fi(fileName); QString path = (fi.path().length() > 3) ? QString(fi.path() + "/") : fi.path(); QFileInfo si(QString::fromStdString(_schemaName)); QString schemaPath(si.absolutePath() + "/"); if (!file->open(QIODevice::ReadOnly | QIODevice::Text)) { std::cout << "XmlGspInterface::readFile() - Can't open xml-file " << fileName.toStdString() << "." << std::endl; delete file; return 0; } if (!checkHash(fileName)) { delete file; return 0; } QDomDocument doc("OGS-PROJECT-DOM"); doc.setContent(file); QDomElement docElement = doc.documentElement(); //OpenGeoSysProject if (docElement.nodeName().compare("OpenGeoSysProject")) { std::cout << "XmlGspInterface::readFile() - Unexpected XML root." << std::endl; delete file; return 0; } QDomNodeList fileList = docElement.childNodes(); for(int i = 0; i < fileList.count(); i++) { const QString file_node(fileList.at(i).nodeName()); if (file_node.compare("geo") == 0) { XmlGmlInterface gml(_project, schemaPath.toStdString() + "OpenGeoSysGLI.xsd"); const QDomNodeList childList = fileList.at(i).childNodes(); for(int j = 0; j < childList.count(); j++) { const QDomNode child_node (childList.at(j)); if (child_node.nodeName().compare("file") == 0) { std::cout << "path: " << path.toStdString() << "#" << std::endl; std::cout << "file name: " << (child_node.toElement().text()).toStdString() << "#" << std::endl; gml.readFile(QString(path + child_node.toElement().text())); } } } else if (file_node.compare("stn") == 0) { XmlStnInterface stn(_project, schemaPath.toStdString() + "OpenGeoSysSTN.xsd"); const QDomNodeList childList = fileList.at(i).childNodes(); for(int j = 0; j < childList.count(); j++) if (childList.at(j).nodeName().compare("file") == 0) stn.readFile(QString(path + childList.at(j).toElement().text())); } else if (file_node.compare("msh") == 0) { const std::string msh_name = path.toStdString() + fileList.at(i).toElement().text().toStdString(); FileIO::MeshIO meshIO; MeshLib::Mesh* msh = meshIO.loadMeshFromFile(msh_name); _project->addMesh(msh); } } return 1; }
/* Take increments in strain and calculate new Particle: strains, rotation strain, stresses, strain energy, du are (gradient rates X time increment) to give deformation gradient change For Axisymmetry: x->R, y->Z, z->theta, np==AXISYMMETRIC_MPM, otherwise dvzz=0 This material tracks pressure and stores deviatoric stress only in particle stress tensor */ void Viscoelastic::MPMConstitutiveLaw(MPMBase *mptr,Matrix3 du,double delTime,int np,void *properties,ResidualStrains *res,int historyOffset) const { // current previous deformation gradient and stretch Matrix3 pFnm1 = mptr->GetDeformationGradientMatrix(); // get incremental deformation gradient and decompose it const Matrix3 dF = du.Exponential(incrementalDefGradTerms); Matrix3 dR; Matrix3 dVstretch = dF.LeftDecompose(&dR,NULL); // decompose to get previous stretch Matrix3 Vnm1 = pFnm1.LeftDecompose(NULL,NULL); // get strain increments de = (dV-I) dR Vnma dRT dVstretch(0,0) -= 1.; dVstretch(1,1) -= 1.; dVstretch(2,2) -= 1.; Matrix3 Vrot = Vnm1.RMRT(dR); Matrix3 detot = dVstretch*Vrot; // Update total deformation gradient Matrix3 pF = dF*pFnm1; mptr->SetDeformationGradientMatrix(pF); // Effective strain by deducting thermal strain (no shear thermal strain because isotropic) double eres=CTE*res->dT; if(DiffusionTask::active) eres+=CME*res->dC; // update pressure double dTq0 = 0.,dispEnergy = 0.; double traceDe = detot.trace(); double delV = traceDe - 3.*eres; #ifdef USE_KIRCHOFF_STRESS // tracking J double detdF = dF.determinant(); double **h =(double **)(mptr->GetHistoryPtr(0)); double J = detdF*h[mptrHistory][MGJ_HISTORY]; h[mptrHistory][MGJ_HISTORY] = J; UpdatePressure(mptr,delV,res,eres,detdF,J,delTime,dTq0,dispEnergy); #else UpdatePressure(mptr,delV,res,eres,&dF,delTime,dTq0,dispEnergy); #endif // deviatoric strains increment in de // Actually de is finding 2*(dev e) to avoid many multiplies by two Tensor de; double dV = traceDe/3.; de.xx = 2.*(detot(0,0) - dV); de.yy = 2.*(detot(1,1) - dV); de.zz = 2.*(detot(2,2) - dV); de.xy = 2.*detot(0,1); if(np==THREED_MPM) { de.xz = 2.*detot(0,2); de.yz = 2.*detot(1,2); } // Find initial 2*e(t) (deviatoric strain) in ed Tensor ed; double thirdV = Vrot.trace()/3.; ed.xx = 2.*(Vrot(0,0)-thirdV); ed.yy = 2.*(Vrot(1,1)-thirdV); ed.zz = 2.*(Vrot(2,2)-thirdV); ed.xy = 2.*Vrot(0,1); if(np==THREED_MPM) { ed.xz = 2.*Vrot(0,2); ed.yz = 2.*Vrot(1,2); } // increment particle deviatoric stresses - elastic part double dsig[6]; dsig[XX] = Gered*de.xx; dsig[YY] = Gered*de.yy; dsig[ZZ] = Gered*de.zz; dsig[XY] = Gered*de.xy; if(np==THREED_MPM) { dsig[XZ] = Gered*de.xz; dsig[YZ] = Gered*de.yz; } // get internal variable increments, update them, add to incremental stress, and get dissipated energy6 Tensor dak; double **ak =(double **)(mptr->GetHistoryPtr(0)); int k; for(k=0;k<ntaus;k++) { double tmp = exp(-delTime/tauk[k]); double tmpm1 = tmp-1.; double tmpp1 = tmp+1.; double arg = 0.25*delTime/tauk[k]; // 0.25 because e's have factor of 2 dak.xx = tmpm1*ak[XX_HISTORY][k] + arg*(tmpp1*ed.xx + de.xx); dak.yy = tmpm1*ak[YY_HISTORY][k] + arg*(tmpp1*ed.yy + de.yy); dak.xy = tmpm1*ak[XY_HISTORY][k] + arg*(tmpp1*ed.xy + de.xy); dak.zz = tmpm1*ak[ZZ_HISTORY][k] + arg*(tmpp1*ed.zz + de.zz); ak[XX_HISTORY][k] += dak.xx; ak[YY_HISTORY][k] += dak.yy; ak[ZZ_HISTORY][k] += dak.zz; ak[XY_HISTORY][k] += dak.xy; // add to stress increments dsig[XX] -= TwoGkred[k]*dak.xx; dsig[YY] -= TwoGkred[k]*dak.yy; dsig[ZZ] -= TwoGkred[k]*dak.zz; dsig[XY] -= TwoGkred[k]*dak.xy; // dissipation dispEnergy += TwoGkred[k]*(dak.xx*(0.5*(ed.xx+0.5*de.xx)-ak[XX_HISTORY][k]+0.5*dak.xx) + dak.yy*(0.5*(ed.yy+0.5*de.yy)-ak[YY_HISTORY][k]+0.5*dak.yy) + dak.zz*(0.5*(ed.zz+0.5*de.zz)-ak[ZZ_HISTORY][k]+0.5*dak.zz) + dak.xy*(0.5*(ed.xy+0.5*de.xy)-ak[XY_HISTORY][k]+0.5*dak.xy)); // extra terms for 3D if(np==THREED_MPM) { // internal variables dak.xz = tmpm1*ak[XZ_HISTORY][k] + arg*(tmpp1*ed.xz + de.xz); dak.yz = tmpm1*ak[YZ_HISTORY][k] + arg*(tmpp1*ed.yz + de.yz); ak[XZ_HISTORY][k] += dak.xz; ak[YZ_HISTORY][k] += dak.yz; // stresses dsig[XZ] -= TwoGkred[k]*dak.xz; dsig[YZ] -= TwoGkred[k]*dak.yz; // dissipation dispEnergy += TwoGkred[k]*(dak.xz*(0.5*(ed.xz+0.5*de.xz)-ak[XZ_HISTORY][k]+0.5*dak.xz) + dak.yz*(0.5*(ed.yz+0.5*de.yz)-ak[YZ_HISTORY][k]+0.5*dak.yz)); } } // Update particle deviatoric stresses Tensor *sp=mptr->GetStressTensor(); //Tensor st0 = *sp; if(np==THREED_MPM) { // incremental rotate of prior stress Matrix3 stn(sp->xx,sp->xy,sp->xz,sp->xy,sp->yy,sp->yz,sp->xz,sp->yz,sp->zz); Matrix3 str = stn.RMRT(dR); #ifdef USE_KIRCHOFF_STRESS // convert sigma(n)/rho(n) to sigma(n)/rho(n+1) and add dsigma/rho(n+1) sp->xx = detdF*str(0,0)+J*dsig[XX]; sp->yy = detdF*str(1,1)+J*dsig[YY]; sp->xy = detdF*str(0,1)+J*dsig[XY]; sp->zz = detdF*str(2,2)+J*dsig[ZZ]; sp->yz = detdF*str(1,2)+J*dsig[YZ]; sp->xz = detdF*str(0,2)+J*dsig[XZ]; #else sp->xx = str(0,0)+dsig[XX]; sp->yy = str(1,1)+dsig[YY]; sp->xy = str(0,1)+dsig[XY]; sp->zz = str(2,2)+dsig[ZZ]; sp->yz = str(1,2)+dsig[YZ]; sp->xz = str(0,2)+dsig[XZ]; #endif } else { // incremental rotate of prior stress Matrix3 stn(sp->xx,sp->xy,sp->xy,sp->yy,sp->zz); Matrix3 str = stn.RMRT(dR); #ifdef USE_KIRCHOFF_STRESS // convert sigma(n)/rho(n) to sigma(n)/rho(n+1) and add dsigma/rho(n+1) sp->xx = detdF*str(0,0)+J*dsig[XX]; sp->yy = detdF*str(1,1)+J*dsig[YY]; sp->xy = detdF*str(0,1)+J*dsig[XY]; sp->zz = detdF*sp->zz+J*dsig[ZZ]; #else sp->xx = str(0,0)+dsig[XX]; sp->yy = str(1,1)+dsig[YY]; sp->xy = str(0,1)+dsig[XY]; sp->zz += dsig[ZZ]; #endif } // incremental work energy = shear energy (dilation and residual energy done in update pressure) double shearEnergy = sp->xx*detot(0,0) + sp->yy*detot(1,1) + sp->zz*detot(2,2) + sp->xy*de.xy; if(np==THREED_MPM) { shearEnergy += sp->xz*de.xz + sp->yz*de.yz; } mptr->AddWorkEnergyAndResidualEnergy(shearEnergy,0.); // disispated energy per unit mass (dPhi/(rho0 V0)) (nJ/g) mptr->AddPlastEnergy(dispEnergy); // heat energy is Cv dT - dPhi // The dPhi is subtracted here because it will show up in next // time step within Cv dT (if adibatic heating occurs) // The Cv dT was done in update pressure IncrementHeatEnergy(mptr,res->dT,dTq0,dispEnergy); }
// To allow some subclasses to support large deformations, the initial calculation for incremental // deformation gradient (the dvij), volume change (delV) can be // handled first by the subclass. This mtehod then finishes the constitutive law void IsoPlasticity::LRPlasticityConstLaw(MPMBase *mptr,double dexx,double deyy,double dezz,double dgxy, double dgxz,double dgyz,double delTime,int np,double delV,double eres, PlasticProperties *p,ResidualStrains *res,Matrix3 *dR) const { // here dvij is total strain increment, dexxr is relative strain by subtracting off eres double dexxr=dexx-eres; double deyyr=deyy-eres; double dezzr=dezz-eres; // allow arbitrary equation of state for pressure double dTq0 = 0.,dispEnergy = 0.; UpdatePressure(mptr,delV,np,p,res,eres,dTq0,dispEnergy); // Elastic deviatoric stress increment Tensor *sp=mptr->GetStressTensor(); Tensor stk; //Tensor st0=*sp; double dsig[6]; double thirdDelV = delV/3.; dsig[XX] = 2.*p->Gred*(dexxr-thirdDelV); dsig[YY] = 2.*p->Gred*(deyyr-thirdDelV); dsig[ZZ] = 2.*p->Gred*(dezzr-thirdDelV); dsig[YZ] = p->Gred*dgyz; dsig[XZ] = p->Gred*dgxz; dsig[XY] = p->Gred*dgxy; // incremental rotate of prior strain Tensor *eplast=mptr->GetAltStrainTensor(); Matrix3 etn(eplast->xx,0.5*eplast->xy,0.5*eplast->xz,0.5*eplast->xy,eplast->yy,0.5*eplast->yz, 0.5*eplast->xz,0.5*eplast->yz,eplast->zz); Matrix3 etr = etn.RMRT(*dR); Matrix3 stn(sp->xx,sp->xy,sp->xz,sp->xy,sp->yy,sp->yz,sp->xz,sp->yz,sp->zz); Matrix3 str = stn.RMRT(*dR); // trial deviatoric stress stk.xx = str(0,0) + dsig[XX]; stk.yy = str(1,1) + dsig[YY]; stk.zz = str(2,2) + dsig[ZZ]; stk.yz = str(1,2) + dsig[YZ]; stk.xz = str(0,2) + dsig[XZ]; stk.xy = str(0,1) + dsig[XY]; // Calculate plastic potential f = ||s|| - sqrt(2/3)*sy(alpha,rate,...) HardeningAlpha alpha; plasticLaw->UpdateTrialAlpha(mptr,np,&alpha,0); // initialize to last value double strial = GetMagnitudeSFromDev(&stk,np); double ftrial = strial - SQRT_TWOTHIRDS*plasticLaw->GetYield(mptr,np,delTime,&alpha,p->hardProps); if(ftrial<0.) { // elastic, update stress and strain energy as usual // set in-plane deviatoric stress *sp = stk; // rotate plastic strain eplast->xx = etr(0,0); eplast->yy = etr(1,1); eplast->zz = etr(2,2); eplast->xy = 2.*etr(0,1); eplast->xz = 2.*etr(0,2); eplast->yz = 2.*etr(1,2); // work energy increment per unit mass (dU/(rho0 V0)) (nJ/g) mptr->AddWorkEnergy(sp->xx*dexx + sp->yy*deyy + sp->zz*dezz + sp->yz*dgyz + sp->xz*dgxz + sp->xy*dgxy); //mptr->AddWorkEnergy(0.5*((st0.xx+sp->xx)*dexx + (st0.yy+sp->yy)*deyy + (st0.zz+sp->zz)*dezz // + (st0.yz+sp->yz)*dgyz + (st0.xz+sp->xz)*dgxz + (st0.xy+sp->xy)*dgxy)); // give material chance to update history variables that change in elastic updates plasticLaw->ElasticUpdateFinished(mptr,np,delTime,0); // heat energy from pressure and any pressure method items IncrementHeatEnergy(mptr,res->dT,dTq0,dispEnergy); return; } // Find direction of plastic strain and lambda for this plastic state // Base class finds it numerically, subclass can override if solvable by more efficient meethods Tensor dfds; GetDfDsigma(strial,&stk,np,&dfds); double lambdak = plasticLaw->SolveForLambdaBracketed(mptr,np,strial,&stk,p->Gred,1.,1.,delTime,&alpha,p->hardProps,0); // Now have lambda, finish update on this particle // Plastic strain increments on particle double dexxp = lambdak*dfds.xx; double deyyp = lambdak*dfds.yy; double dezzp = lambdak*dfds.zz; double dgxyp = 2.*lambdak*dfds.xy; // 2 for engineering plastic shear strain double dgxzp = 2.*lambdak*dfds.xz; // 2 for engineering plastic shear strain double dgyzp = 2.*lambdak*dfds.yz; // 2 for engineering plastic shear strain // incremental plastic strain eplast->xx = etr(0,0) + dexxp; eplast->yy = etr(1,1) + deyyp; eplast->zz = etr(2,2) + dezzp; eplast->xy = 2.*etr(0,1) + dgxyp; eplast->xz = 2.*etr(0,2) + dgxzp; eplast->yz = 2.*etr(1,2) + dgyzp; // increment particle deviatoric stresses sp->xx = stk.xx - 2.*p->Gred*dexxp; sp->yy = stk.yy - 2.*p->Gred*deyyp; sp->zz = stk.zz - 2.*p->Gred*dezzp; sp->yz = stk.yz - p->Gred*dgyzp; sp->xz = stk.xz - p->Gred*dgxzp; sp->xy = stk.xy - p->Gred*dgxyp; // work energy increment per unit mass (dU/(rho0 V0)) (nJ/g) double workEnergy = sp->xx*dexx + sp->yy*dezz + sp->zz*dezz + sp->yz*dgyz + sp->xz*dgxz + sp->xy*dgxy; //double workEnergy = 0.5*((st0.xx+sp->xx)*dexx + (st0.yy+sp->yy)*dezz + (st0.zz+sp->zz)*dezz // + (st0.yz+sp->yz)*dgyz + (st0.xz+sp->xz)*dgxz + (st0.xy+sp->xy)*dgxy); // total work mptr->AddWorkEnergy(workEnergy); // plastic strain work double plastEnergy = lambdak*(sp->xx*dfds.xx + sp->yy*dfds.yy + sp->zz*dfds.zz + 2.*sp->xy*dfds.xy + 2.*sp->xz*dfds.xz + 2.*sp->yz*dfds.yz); // and subtrace q dalpa disispated energy per unit mass (dPhi/(rho0 V0)) (nJ/g) double qdalphaTerm = lambdak*SQRT_TWOTHIRDS*plasticLaw->GetYieldIncrement(mptr,np,delTime,&alpha,p->hardProps); dispEnergy += plastEnergy - qdalphaTerm; // The cumulative dissipated energy is tracked in plastic energy // Setting the disp energy allows heating if mechanical energy is on mptr->AddPlastEnergy(dispEnergy); // heat energy is Cv(dT-dTq0) - dPhi // The dPhi is subtracted here because it will show up in next // time step within Cv dT (if adiabatic heating occurs) // The Cv(dT-dTq0) was done already in update pressure IncrementHeatEnergy(mptr,res->dT,dTq0,dispEnergy); // update internal variables plasticLaw->UpdatePlasticInternal(mptr,np,&alpha,0); }
// To allow some subclasses to support large deformations, the initial calculation for incremental // deformation gradient (the dvij), volume change (delV) // handled first by the subclass. This method then finishes the constitutive law void IsoPlasticity::LRPlasticityConstLaw(MPMBase *mptr,double dexx,double deyy,double dgxy, double dezz,double delTime,int np,double delV,double eres, PlasticProperties *p,ResidualStrains *res,Matrix3 *dR) const { // here deij is total strain increment, dexxr is relative strain by subtracting off eres double dexxr = dexx-eres; double deyyr = deyy-eres; double dezzr = dezz-eres; // In plane strain trial dezz=0, but not in axisymmetric // allow arbitrary equation of state for pressure double P0 = mptr->GetPressure(); double dTq0 = 0.,dispEnergy = 0.; UpdatePressure(mptr,delV,np,p,res,eres,dTq0,dispEnergy); double Pfinal = mptr->GetPressure(); // Deviatoric stress increment Tensor *sp=mptr->GetStressTensor(); Tensor dels,stk; //Tensor st0=*sp; double thirdDelV = delV/3.; dels.xx = 2.*p->Gred*(dexxr-thirdDelV); dels.yy = 2.*p->Gred*(deyyr-thirdDelV); if(np==PLANE_STRESS_MPM) dels.zz = Pfinal-P0; else dels.zz = 2.*p->Gred*(dezzr-thirdDelV); dels.xy = p->Gred*dgxy; // incremental rotate of plastic strain Tensor *eplast=mptr->GetAltStrainTensor(); Matrix3 etn(eplast->xx,0.5*eplast->xy,0.5*eplast->xy,eplast->yy,eplast->zz); Matrix3 etr = etn.RMRT(*dR); eplast->xx = etr(0,0); eplast->yy = etr(1,1); eplast->xy = 2.*etr(0,1); // incremental rotation of stress Matrix3 stn(sp->xx,sp->xy,sp->xy,sp->yy,sp->zz); Matrix3 str = stn.RMRT(*dR); // trial deviatoric stress stk.xx = str(0,0) + dels.xx; stk.yy = str(1,1) + dels.yy; stk.zz = str(2,2) + dels.zz; stk.xy = str(0,1) + dels.xy; // Calculate plastic potential f = ||s|| - sqrt(2/3)*sy(alpha,rate,...) HardeningAlpha alpha; plasticLaw->UpdateTrialAlpha(mptr,np,&alpha,0); // initialize to last value and zero plastic strain rate double strial = GetMagnitudeSFromDev(&stk,np); double ftrial = strial - SQRT_TWOTHIRDS*plasticLaw->GetYield(mptr,np,delTime,&alpha,p->hardProps); if(ftrial<0.) { // elastic, update stress and strain energy as usual // set in plane deviatoric stress sp->xx = stk.xx; sp->xy = stk.xy; sp->yy = stk.yy; sp->zz = stk.zz; // work energy increment per unit mass (dU/(rho0 V0)) (by midpoint rule) (nJ/g) // energy units are also Pa mm^3/g, i.e., same as stress units if(np==AXISYMMETRIC_MPM) { mptr->AddWorkEnergy(sp->xx*dexx + sp->yy*deyy + sp->xy*dgxy + sp->zz*dezz); //mptr->AddWorkEnergy(0.5*((st0.xx+sp->xx)*dexx + (st0.yy+sp->yy)*deyy + (st0.xy+sp->xy)*dgxy + (st0.zz+sp->zz)*dezz)); } else if(np==PLANE_STRESS_MPM) { // zz deformation mptr->IncrementDeformationGradientZZ(-p->psLr2G*(dexxr+deyyr) + eres); mptr->AddWorkEnergy(sp->xx*dexx + sp->yy*deyy + sp->xy*dgxy); //mptr->AddWorkEnergy(0.5*((st0.xx+sp->xx)*dexx + (st0.yy+sp->yy)*deyy + (st0.xy+sp->xy)*dgxy)); } else { mptr->AddWorkEnergy(sp->xx*dexx + sp->yy*deyy + sp->xy*dgxy); //mptr->AddWorkEnergy(0.5*((st0.xx+sp->xx)*dexx + (st0.yy+sp->yy)*deyy + (st0.xy+sp->xy)*dgxy)); } // give subclass material chance to update history variables that change in elastic updates plasticLaw->ElasticUpdateFinished(mptr,np,delTime,0); // heat energy from pressure and any pressure method items IncrementHeatEnergy(mptr,res->dT,dTq0,dispEnergy); return; } // Find lambda for this plastic state // Base class finds it numerically, subclass can override if solvable by more efficient methods double lambdak = plasticLaw->SolveForLambdaBracketed(mptr,np,strial,&stk,p->Gred,p->psKred,Pfinal,delTime,&alpha,p->hardProps,0); // Now have lambda, finish update on this particle Tensor dfds; if(np==PLANE_STRESS_MPM) { // get final stress state double d1 = (1 + p->psKred*lambdak); double d2 = (1.+2.*p->Gred*lambdak); double n1 = (stk.xx+stk.yy-2.*Pfinal)/d1; double n2 = (-stk.xx+stk.yy)/d2; double sxx = (n1-n2)/2.; double syy = (n1+n2)/2.; double txy = stk.xy/d2; // find increment in deviatoric stress dels.xx = sxx+Pfinal-sp->xx; dels.yy = syy+Pfinal-sp->yy; dels.xy = txy-sp->xy; // get final direction dfds.xx = (2.*sxx-syy)/3.; dfds.yy = (2.*syy-sxx)/3.; dfds.zz = -(dfds.xx+dfds.yy); dfds.xy = txy; // tensorial shear strain // zz deformation mptr->IncrementDeformationGradientZZ(-p->psLr2G*(dexxr+deyyr - lambdak*(dfds.xx+dfds.yy)) + eres + lambdak*dfds.zz); // If fully plastic, the increment in deviatoric stress should be zero // sxx = sigmaxx+Pfinal = st0.xx, syy = sigmayy+Pfinal = st0.yy, szz = Pfinal // But first two must be wrong because trace is no longer zero? // // This is probably wrong // i.e.: n1 + 2*Pfinal = st0.xx+st0.yy // (stk.xx+stk.yy)/d1 - 2*Pfinal*(1/d1-1) = st0.xx+st0.yy // But (stk.xx+stk.yy) = (st0.xx+st0.yy) + 2.*Gred*(dexxr+deyyr-2*thirdDelV) // (st0.xx+st0.yy)(1/d1-1) - 2*Pfinal*(1/d1-1) = -2.*Gred*(dexxr+deyyr-2*thirdDelV)/d1 // (st0.xx+st0.yy-2*Pfinal)*(1-d1) = -2.*Gred*(dexxr+deyyr-2*thirdDelV) // B*Kred*lam = 2.*Gred*A or lam = 2.*Gred*A/(B*Kred) // where B = st0.xx+st0.yy-2*Pfinal, and A = (dexxr+deyyr-2*thirdDelV) // Then d1 = 1+2*Gred*A/B, n1 = ((st0.xx+st0.yy) + 2*Gred*A - 2*Pfinal)/d1 = (B+2*Gred*A)*B/(B+2*Gred*A) = B // // Also expect syy-sxx = sigmayy-sigmaxx = st0.yy-st0.xx = n2 // (stk.yy-stk.xx)/d2 = st0.yy-st0.xx // (st0.yy-st0.xx)/d2 + 2*Gred*(deyyr-dexxr)/d2 = (st0.yy-st0.xx) // (st0.yy-st0.xx)(d2-1) = - 2*Gred*(deyyr-dexxr) // lam = (deyyr-dexxr)/(st0.yy-st0.xx) // Then n2 = (st0.yy-st0.xx + 2*Gred*(deyyr-dexxr))/(1+2*Gred*(deyyr-dexxr)/(st0.yy-st0.xx)) = st0.yy-st0.xx // // But these two lam's seem to differ? // We can write } else { // get final direction GetDfDsigma(strial,&stk,np,&dfds); } // Plastic strain increments on particle double dexxp = lambdak*dfds.xx; double deyyp = lambdak*dfds.yy; double dezzp = lambdak*dfds.zz; double dgxyp = 2.*lambdak*dfds.xy; // 2 for engineering plastic shear strain eplast->xx += dexxp; eplast->yy += deyyp; eplast->zz += dezzp; eplast->xy += dgxyp; // increment particle deviatoric stresses (plane stress increments found above) if(np!=PLANE_STRESS_MPM) { dels.xx -= 2.*p->Gred*dexxp; dels.yy -= 2.*p->Gred*deyyp; dels.xy -= p->Gred*dgxyp; dels.zz -= 2.*p->Gred*dezzp; sp->zz += dels.zz; } else sp->zz = Pfinal; // now equal to Pfinal // update in-plane stressees sp->xx = str(0,0) + dels.xx; sp->yy = str(1,1) + dels.yy; sp->xy = str(0,1) + dels.xy; // Elastic work increment per unit mass (dU/(rho0 V0)) (nJ/g) double workEnergy = sp->xx*dexx + sp->yy*deyy + sp->xy*dgxy; //double workEnergy = 0.5*((st0.xx+sp->xx)*dexx + (st0.yy+sp->yy)*deyy + (st0.xy+sp->xy)*dgxy); if(np==AXISYMMETRIC_MPM) { workEnergy += sp->zz*dezz; //workEnergy += 0.5*(st0.zz+sp->zz)*dezz; } // total work mptr->AddWorkEnergy(workEnergy); // plastic strain work double plastEnergy = lambdak*(sp->xx*dfds.xx + sp->yy*dfds.yy + sp->zz*dfds.zz + 2.*sp->xy*dfds.xy); // dand subtract q dalpha to get isispated energy per unit mass (dPhi/(rho0 V0)) (nJ/g) double qdalphaTerm = lambdak*SQRT_TWOTHIRDS*plasticLaw->GetYieldIncrement(mptr,np,delTime,&alpha,p->hardProps); dispEnergy += plastEnergy - qdalphaTerm; // The cumulative dissipated energy is tracked in plastic energy mptr->AddPlastEnergy(dispEnergy); // heat energy is Cv(dT-dTq0) - dPhi // The dPhi is subtracted here because it will show up in next // time step within Cv dT (if adibatic heating occurs) IncrementHeatEnergy(mptr,res->dT,dTq0,dispEnergy); // update internal variables plasticLaw->UpdatePlasticInternal(mptr,np,&alpha,0); }
// Once stress deformation has been decomposed, finish calculations in the material axis system // When stress are found, they are rotated back to the global axes (using Rtot and dR) // Similar, strain increments are rotated back to find work energy (done in global system) void Elastic::LRElasticConstitutiveLaw(MPMBase *mptr,Matrix3 de,Matrix3 er,Matrix3 Rtot,Matrix3 dR, Matrix3 *Rnmatot,int np,void *properties,ResidualStrains *res) const { // effective strains double dvxxeff = de(0,0)-er(0,0); double dvyyeff = de(1,1)-er(1,1); double dvzzeff = de(2,2)-er(2,2); double dgamxy = 2.*de(0,1); // save initial stresses Tensor *sp=mptr->GetStressTensor(); //Tensor st0=*sp; // stress increments // cast pointer to material-specific data ElasticProperties *p = GetElasticPropertiesPointer(properties); if(np==THREED_MPM) { double dgamyz = 2.*de(1,2); double dgamxz = 2.*de(0,2); // update sigma = dR signm1 dRT + Rtot dsigma RtotT double dsigyz = p->C[3][3]*dgamyz; double dsigxz = p->C[4][4]*dgamxz; double dsigxy = p->C[5][5]*dgamxy; Matrix3 dsig(p->C[0][0]*dvxxeff + p->C[0][1]*dvyyeff + p->C[0][2]*dvzzeff, dsigxy, dsigxz, dsigxy, p->C[1][0]*dvxxeff + p->C[1][1]*dvyyeff + p->C[1][2]*dvzzeff, dsigyz, dsigxz, dsigyz, p->C[2][0]*dvxxeff + p->C[2][1]*dvyyeff + p->C[2][2]*dvzzeff); Matrix3 dsigrot = dsig.RMRT(Rtot); Matrix3 stn(sp->xx,sp->xy,sp->xz,sp->xy,sp->yy,sp->yz,sp->xz,sp->yz,sp->zz); Matrix3 str = stn.RMRT(dR); sp->xx = str(0,0) + dsigrot(0,0); sp->yy = str(1,1) + dsigrot(1,1); sp->zz = str(2,2) + dsigrot(2,2); sp->xy = str(0,1) + dsigrot(0,1); sp->xz = str(0,2) + dsigrot(0,2); sp->yz = str(1,2) + dsigrot(1,2); // stresses are in global coordinates so need to rotate strain and residual // strain to get work energy increment per unit mass (dU/(rho0 V0)) Matrix3 derot = de.RMRT(Rtot); Matrix3 errot = er.RMRT(Rtot); mptr->AddWorkEnergyAndResidualEnergy(sp->xx*derot(0,0) + sp->yy*derot(1,1) + sp->zz*derot(2,2) + 2.*(sp->yz*derot(1,2) + sp->xz*derot(0,2) + sp->xy*derot(0,1)), sp->xx*errot(0,0) + sp->yy*errot(1,1) + sp->zz*errot(2,2) + 2.*(sp->yz*errot(1,2) + sp->xz*errot(0,2) + sp->xy*errot(0,1)) ); //mptr->AddWorkEnergyAndResidualEnergy(0.5*((st0.xx+sp->xx)*derot(0,0) + (st0.yy+sp->yy)*derot(1,1) // + (st0.zz+sp->zz)*derot(2,2)) + (st0.yz+sp->yz)*derot(1,2) // + (st0.xz+sp->xz)*derot(0,2) + (st0.xy+sp->xy)*derot(0,1), // 0.5*((st0.xx+sp->xx)*errot(0,0) + (st0.yy+sp->yy)*errot(1,1) // + (st0.zz+sp->zz)*errot(2,2)) + (st0.yz+sp->yz)*errot(1,2) // + (st0.xz+sp->xz)*errot(0,2) + (st0.xy+sp->xy)*errot(0,1)); } else { // find stress increment // this does xx, yy, and xy only. zz done later if needed double dsxx,dsyy; if(np==AXISYMMETRIC_MPM) { dsxx = p->C[1][1]*dvxxeff + p->C[1][2]*dvyyeff + p->C[4][1]*dvzzeff ; dsyy = p->C[1][2]*dvxxeff + p->C[2][2]*dvyyeff + p->C[4][2]*dvzzeff; } else { dsxx = p->C[1][1]*dvxxeff + p->C[1][2]*dvyyeff; dsyy = p->C[1][2]*dvxxeff + p->C[2][2]*dvyyeff; } double dsxy = p->C[3][3]*dgamxy; // update sigma = dR signm1 dRT + Rtot dsigma RtotT Matrix3 dsig(dsxx,dsxy,dsxy,dsyy,0.); Matrix3 dsigrot = dsig.RMRT(Rtot); Matrix3 stn(sp->xx,sp->xy,sp->xy,sp->yy,sp->zz); Matrix3 str = stn.RMRT(dR); sp->xx = str(0,0) + dsigrot(0,0); sp->yy = str(1,1) + dsigrot(1,1); sp->xy = str(0,1) + dsigrot(0,1); // stresses are in global coordinate so need to rotate strain and residual // strain to get work energy increment per unit mass (dU/(rho0 V0)) double ezzr = er(2,2); Matrix3 derot = de.RMRT(Rtot); Matrix3 errot = er.RMRT(Rtot); // work and residual strain energy increments and sigma or F in z direction double workEnergy = sp->xx*derot(0,0) + sp->yy*derot(1,1) + 2.0*sp->xy*derot(0,1); double resEnergy = sp->xx*errot(0,0) + sp->yy*errot(1,1) + 2.*sp->xy*errot(0,1); //double workEnergy = 0.5*((st0.xx+sp->xx)*derot(0,0) + (st0.yy+sp->yy)*derot(1,1)) + (st0.xy+sp->xy)*derot(0,1); //double resEnergy = 0.5*((st0.xx+sp->xx)*errot(0,0) + (st0.yy+sp->yy)*errot(1,1)) + (st0.xy+sp->xy)*errot(0,1); if(np==PLANE_STRAIN_MPM) { // need to add back terms to get from reduced cte to actual cte sp->zz += p->C[4][1]*(dvxxeff+p->alpha[5]*ezzr) + p->C[4][2]*(dvyyeff+p->alpha[6]*ezzr) - p->C[4][4]*ezzr; // extra residual energy increment per unit mass (dU/(rho0 V0)) (by midpoint rule) (nJ/g) resEnergy += sp->zz*ezzr; //resEnergy += 0.5*(st0.zz+sp->zz)*ezzr; } else if(np==PLANE_STRESS_MPM) { // zz deformation mptr->IncrementDeformationGradientZZ(p->C[4][1]*dvxxeff + p->C[4][2]*dvyyeff + ezzr); } else { // axisymmetric hoop stress sp->zz += p->C[4][1]*dvxxeff + p->C[4][2]*dvyyeff + p->C[4][4]*dvzzeff; // extra work and residual energy increment per unit mass (dU/(rho0 V0)) (by midpoint rule) (nJ/g) workEnergy += sp->zz*de(2,2); resEnergy += sp->zz*ezzr; //workEnergy += 0.5*(st0.zz+sp->zz)*de(2,2); //resEnergy += 0.5*(st0.zz+sp->zz)*ezzr; } mptr->AddWorkEnergyAndResidualEnergy(workEnergy, resEnergy); } // track heat energy IncrementHeatEnergy(mptr,res->dT,0.,0.); }