Real GapHeatTransfer::computeQpOffDiagJacobian(unsigned jvar) { computeGapValues(); if (!_has_info) return 0.0; unsigned int coupled_component; bool active = false; for (coupled_component = 0; coupled_component < _disp_vars.size(); ++coupled_component) if (jvar == _disp_vars[coupled_component]) { active = true; break; } Real dRdx = 0.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]; }
Real GapHeatTransfer::computeQpJacobian() { computeGapValues(); if (!_has_info) return 0; return _test[_i][_qp] * ((_u[_qp] - _gap_temp) * _edge_multiplier * _gap_conductance_dT[_qp] + _edge_multiplier * _gap_conductance[_qp]) * _phi[_j][_qp]; }
Real GapHeatTransfer::computeQpResidual() { computeGapValues(); if (!_has_info) return 0; Real grad_t = (_u[_qp] - _gap_temp) * _edge_multiplier * _gap_conductance[_qp]; // This is keeping track of this residual contribution so it can be used as the flux on the other side of the gap. if (!_quadrature) { Threads::spin_mutex::scoped_lock lock(slave_flux_mutex); const Real slave_flux = computeSlaveFluxContribution(grad_t); _slave_flux->add(_var.dofIndices()[_i], slave_flux); } return _test[_i][_qp]*grad_t; }
void GapConductance::computeQpProperties() { computeGapValues(); computeQpConductance(); }