Real GapHeatTransfer::computeQpOffDiagJacobian( unsigned jvar ) { computeGapValues(); if (!_has_info) return 0; unsigned coupled_component(0); bool active(false); if ( _xdisp_coupled && jvar == _xdisp_var ) { coupled_component = 0; active = true; } else if ( _ydisp_coupled && jvar == _ydisp_var ) { coupled_component = 1; active = true; } else if ( _zdisp_coupled && jvar == _zdisp_var ) { coupled_component = 2; active = true; } Real dRdx(0); if ( active ) { // Compute dR/du_[xyz] // Residual is based on // h_gap = h_conduction() + h_contact() + h_radiation(); // grad_t = (_u[_qp] - _gap_temp) * h_gap; // So we need // (_u[_qp] - _gap_temp) * (dh_gap/du_[xyz]); // Assuming dh_contact/du_[xyz] = dh_radiation/du_[xyz] = 0, // we need dh_conduction/du_[xyz] // Given // h_conduction = gapK / gapLength, then // dh_conduction/du_[xyz] = -gapK/gapLength^2 * dgapLength/du_[xyz] // Given // gapLength = ((u_x-m_x)^2+(u_y-m_y)^2+(u_z-m_z)^2)^1/2 // where m_[xyz] is the master coordinate, then // dGapLength/du_[xyz] = 1/2*((u_x-m_x)^2+(u_y-m_y)^2+(u_z-m_z)^2)^(-1/2)*2*(u_[xyz]-m_[xyz]) // = (u_[xyz]-m_[xyz])/gapLength // This is the normal vector. const Real gapL = gapLength(); // THIS IS NOT THE NORMAL WE NEED. // WE NEED THE NORMAL FROM THE CONSTRAINT, THE NORMAL FROM THE // MASTER SURFACE. HOWEVER, THIS IS TRICKY SINCE THE NORMAL // FROM THE MASTER SURFACE WAS COMPUTED FOR A POINT ASSOCIATED // WITH A SLAVE NODE. NOW WE ARE AT A SLAVE INTEGRATION POINT. // // HOW DO WE GET THE NORMAL WE NEED? // // Until we have the normal we need, // we'll hope that the one we have is close to the negative of the one we need. const Point & normal( _normals[_qp] ); const Real dgap = dgapLength( -normal(coupled_component) ); dRdx = -(_u[_qp]-_gap_temp)*_edge_multiplier*_gap_conductance[_qp]/gapL * dgap; } return _test[_i][_qp] * dRdx * _phi[_j][_qp]; }
// // sets angle derivatives dR'/dth // void Node2d::setDr() { dRdx(0,0) = dRdx(1,1) = w2n(1,0); // -sin(th) dRdx(0,1) = w2n(0,0); // cos(th) dRdx(1,0) = -w2n(0,0); // -cos(th) }
// // sets angle derivatives // void Node::setDr(bool local) { // for dS'*R', with dS the incremental change if (local) { #if 0 dRdx = w2n.block<3,3>(0,0) * dRidx; dRdy = w2n.block<3,3>(0,0) * dRidy; dRdz = w2n.block<3,3>(0,0) * dRidz; #endif dRdx = dRidx * w2n.block<3,3>(0,0); dRdy = dRidy * w2n.block<3,3>(0,0); dRdz = dRidz * w2n.block<3,3>(0,0); } else { double x2 = qrot.x() * 2.0; double y2 = qrot.y() * 2.0; double z2 = qrot.z() * 2.0; double w2 = qrot.w() * 2.0; double xw = qrot.x()/qrot.w(); // these are problematic for w near zero double yw = qrot.y()/qrot.w(); double zw = qrot.z()/qrot.w(); // dR/dx dRdx(0,0) = 0.0; dRdx(0,1) = y2-zw*x2; dRdx(0,2) = z2+yw*x2; dRdx(1,0) = y2+zw*x2; dRdx(1,1) = -2.0*x2; dRdx(1,2) = w2-xw*x2; dRdx(2,0) = z2-yw*x2; dRdx(2,1) = -dRdx(1,2); dRdx(2,2) = dRdx(1,1); // dR/dy dRdy(0,0) = -2.0*y2; dRdy(0,1) = x2-zw*y2; dRdy(0,2) = (-w2)+yw*y2; dRdy(1,0) = x2+zw*y2; dRdy(1,1) = 0.0; dRdy(1,2) = dRdx(2,0); dRdy(2,0) = -dRdy(0,2); dRdy(2,1) = dRdx(0,2); dRdy(2,2) = dRdy(0,0); // dR/dz dRdz(0,0) = -2.0*z2; dRdz(0,1) = w2-zw*z2; dRdz(0,2) = dRdy(1,0); dRdz(1,0) = -dRdz(0,1); dRdz(1,1) = dRdz(0,0); dRdz(1,2) = dRdx(0,1); dRdz(2,0) = dRdy(0,1); dRdz(2,1) = dRdx(1,0); dRdz(2,2) = 0.0; } }