void Nonlinear3D::computeIncrementalDeformationGradient(std::vector<ColumnMajorMatrix> & Fhat) { // A = grad(u(k+1) - u(k)) // Fbar = 1 + grad(u(k)) // Fhat = 1 + A*(Fbar^-1) ColumnMajorMatrix A; ColumnMajorMatrix Fbar; ColumnMajorMatrix Fbar_inverse; ColumnMajorMatrix Fhat_average; Real volume(0); _Fbar.resize(_solid_model.qrule()->n_points()); for (unsigned qp = 0; qp < _solid_model.qrule()->n_points(); ++qp) { fillMatrix(qp, _grad_disp_x, _grad_disp_y, _grad_disp_z, A); fillMatrix(qp, _grad_disp_x_old, _grad_disp_y_old, _grad_disp_z_old, Fbar); A -= Fbar; Fbar.addDiag(1); _Fbar[qp] = Fbar; // Get Fbar^(-1) // Computing the inverse is generally a bad idea. // It's better to compute LU factors. For now at least, we'll take // a direct route. invertMatrix(Fbar, Fbar_inverse); Fhat[qp] = A * Fbar_inverse; Fhat[qp].addDiag(1); if (_volumetric_locking_correction) { // Now include the contribution for the integration of Fhat over the element Fhat_average += Fhat[qp] * _solid_model.JxW(qp); volume += _solid_model.JxW(qp); // Accumulate original configuration volume } } if (_volumetric_locking_correction) { Fhat_average /= volume; const Real det_Fhat_average(detMatrix(Fhat_average)); // Finalize volumetric locking correction for (unsigned qp = 0; qp < _solid_model.qrule()->n_points(); ++qp) { const Real det_Fhat(detMatrix(Fhat[qp])); const Real factor(std::cbrt(det_Fhat_average / det_Fhat)); Fhat[qp] *= factor; } } // Moose::out << "Fhat(0,0)" << Fhat[0](0,0) << std::endl; }
void AbaqusUmatMaterial::computeStress() { //Calculate deformation gradient - modeled from "solid_mechanics/src/materials/Nonlinear3D.C" // Fbar = 1 + grad(u(k)) ColumnMajorMatrix Fbar; Fbar(0,0) = _grad_disp_x[_qp](0); Fbar(0,1) = _grad_disp_x[_qp](1); Fbar(0,2) = _grad_disp_x[_qp](2); Fbar(1,0) = _grad_disp_y[_qp](0); Fbar(1,1) = _grad_disp_y[_qp](1); Fbar(1,2) = _grad_disp_y[_qp](2); Fbar(2,0) = _grad_disp_z[_qp](0); Fbar(2,1) = _grad_disp_z[_qp](1); Fbar(2,2) = _grad_disp_z[_qp](2); Fbar.addDiag(1); _Fbar[_qp] = Fbar; Real myDFGRD0[9] = {_Fbar_old[_qp](0,0), _Fbar_old[_qp](1,0), _Fbar_old[_qp](2,0), _Fbar_old[_qp](0,1), _Fbar_old[_qp](1,1), _Fbar_old[_qp](2,1), _Fbar_old[_qp](0,2), _Fbar_old[_qp](1,2), _Fbar_old[_qp](2,2)}; Real myDFGRD1[9] = {_Fbar[_qp](0,0), _Fbar[_qp](1,0), _Fbar[_qp](2,0), _Fbar[_qp](0,1), _Fbar[_qp](1,1), _Fbar[_qp](2,1), _Fbar[_qp](0,2), _Fbar[_qp](1,2), _Fbar[_qp](2,2)}; for (unsigned int i=0; i<9; ++i) { _DFGRD0[i] = myDFGRD0[i]; _DFGRD1[i] = myDFGRD1[i]; } //Recover "old" state variables for (unsigned int i=0; i<_num_state_vars; ++i) _STATEV[i]=_state_var_old[_qp][i]; //Pass through updated stress, total strain, and strain increment arrays for (int i=0; i<_NTENS; ++i) { _STRESS[i] = _stress_old.component(i); _STRAN[i] = _total_strain[_qp].component(i); _DSTRAN[i] = _strain_increment.component(i); } //Pass through step , time, and coordinate system information _KSTEP = _t_step; //Step number _TIME[0] = _t; //Value of step time at the beginning of the current increment - Check _TIME[1] = _t-_dt; //Value of total time at the beginning of the current increment - Check _DTIME = _dt; //Time increment for (unsigned int i=0; i<3; ++i) //Loop current coordinates in UMAT COORDS _COORDS[i] = _coord[i]; //Connection to extern statement _umat(_STRESS, _STATEV, _DDSDDE, &_SSE, &_SPD, &_SCD, &_RPL, _DDSDDT, _DRPLDE, &_DRPLDT, _STRAN, _DSTRAN, _TIME, &_DTIME, &_TEMP, &_DTEMP, _PREDEF, _DPRED, &_CMNAME, &_NDI, &_NSHR, &_NTENS, &_NSTATV, _PROPS, &_NPROPS, _COORDS, _DROT, &_PNEWDT, &_CELENT, _DFGRD0, _DFGRD1, &_NOEL, &_NPT, &_LAYER, &_KSPT, &_KSTEP, &_KINC); //Energy outputs _elastic_strain_energy[_qp] = _SSE; _plastic_dissipation[_qp] = _SPD; _creep_dissipation[_qp] = _SCD; //Update state variables for (unsigned int i=0; i<_num_state_vars; ++i) _state_var[_qp][i]=_STATEV[i]; //Get new stress tensor - UMAT should update stress SymmTensor stressnew(_STRESS[0], _STRESS[1], _STRESS[2], _STRESS[3], _STRESS[4], _STRESS[5]); _stress[_qp] = stressnew; }