bool ElasticitySystem::mass_residual(bool request_jacobian, DiffContext & context) { FEMContext & c = cast_ref<FEMContext &>(context); FEBase * u_elem_fe; c.get_element_fe(u_var, u_elem_fe); // The number of local degrees of freedom in each variable const unsigned int n_u_dofs = c.get_dof_indices(u_var).size(); // Element Jacobian * quadrature weights for interior integration const std::vector<Real> & JxW = u_elem_fe->get_JxW(); const std::vector<std::vector<Real> > & phi = u_elem_fe->get_phi(); // Residuals that we're populating libMesh::DenseSubVector<libMesh::Number> & Fu = c.get_elem_residual(u_var); libMesh::DenseSubVector<libMesh::Number> & Fv = c.get_elem_residual(v_var); libMesh::DenseSubVector<libMesh::Number> & Fw = c.get_elem_residual(w_var); libMesh::DenseSubMatrix<libMesh::Number> & Kuu = c.get_elem_jacobian(u_var, u_var); libMesh::DenseSubMatrix<libMesh::Number> & Kvv = c.get_elem_jacobian(v_var, v_var); libMesh::DenseSubMatrix<libMesh::Number> & Kww = c.get_elem_jacobian(w_var, w_var); unsigned int n_qpoints = c.get_element_qrule().n_points(); for (unsigned int qp=0; qp != n_qpoints; qp++) { libMesh::Number u_ddot, v_ddot, w_ddot; c.interior_accel(u_var, qp, u_ddot); c.interior_accel(v_var, qp, v_ddot); c.interior_accel(w_var, qp, w_ddot); for (unsigned int i=0; i != n_u_dofs; i++) { Fu(i) += _rho*u_ddot*phi[i][qp]*JxW[qp]; Fv(i) += _rho*v_ddot*phi[i][qp]*JxW[qp]; Fw(i) += _rho*w_ddot*phi[i][qp]*JxW[qp]; if (request_jacobian) { for (unsigned int j=0; j != n_u_dofs; j++) { libMesh::Real jac_term = _rho*phi[i][qp]*phi[j][qp]*JxW[qp]; jac_term *= context.get_elem_solution_accel_derivative(); Kuu(i,j) += jac_term; Kvv(i,j) += jac_term; Kww(i,j) += jac_term; } } } } // If the Jacobian was requested, we computed it. Otherwise, we didn't. return request_jacobian; }
bool ElasticitySystem::mass_residual(bool request_jacobian, DiffContext & context) { FEMContext & c = cast_ref<FEMContext &>(context); // We need to extract the corresponding velocity variable. // This allows us to use either a FirstOrderUnsteadySolver // or a SecondOrderUnsteadySolver. That is, we get back the velocity variable // index for FirstOrderUnsteadySolvers or, if it's a SecondOrderUnsteadySolver, // this is actually just giving us back the same variable index. // If we only wanted to use a SecondOrderUnsteadySolver, then this // step would be unnecessary and we would just // populate the _u_var, etc. blocks of the residual and Jacobian. unsigned int u_dot_var = this->get_second_order_dot_var(_u_var); unsigned int v_dot_var = this->get_second_order_dot_var(_v_var); unsigned int w_dot_var = this->get_second_order_dot_var(_w_var); FEBase * u_elem_fe; c.get_element_fe(u_dot_var, u_elem_fe); // The number of local degrees of freedom in each variable const unsigned int n_u_dofs = c.get_dof_indices(u_dot_var).size(); // Element Jacobian * quadrature weights for interior integration const std::vector<Real> & JxW = u_elem_fe->get_JxW(); const std::vector<std::vector<Real>> & phi = u_elem_fe->get_phi(); // Residuals that we're populating libMesh::DenseSubVector<libMesh::Number> & Fu = c.get_elem_residual(u_dot_var); libMesh::DenseSubVector<libMesh::Number> & Fv = c.get_elem_residual(v_dot_var); libMesh::DenseSubVector<libMesh::Number> & Fw = c.get_elem_residual(w_dot_var); libMesh::DenseSubMatrix<libMesh::Number> & Kuu = c.get_elem_jacobian(u_dot_var, u_dot_var); libMesh::DenseSubMatrix<libMesh::Number> & Kvv = c.get_elem_jacobian(v_dot_var, v_dot_var); libMesh::DenseSubMatrix<libMesh::Number> & Kww = c.get_elem_jacobian(w_dot_var, w_dot_var); unsigned int n_qpoints = c.get_element_qrule().n_points(); for (unsigned int qp=0; qp != n_qpoints; qp++) { // If we only cared about using FirstOrderUnsteadySolvers for time-stepping, // then we could actually just use interior rate, but using interior_accel // allows this assembly to function for both FirstOrderUnsteadySolvers // and SecondOrderUnsteadySolvers libMesh::Number u_ddot, v_ddot, w_ddot; c.interior_accel(u_dot_var, qp, u_ddot); c.interior_accel(v_dot_var, qp, v_ddot); c.interior_accel(w_dot_var, qp, w_ddot); for (unsigned int i=0; i != n_u_dofs; i++) { Fu(i) += _rho*u_ddot*phi[i][qp]*JxW[qp]; Fv(i) += _rho*v_ddot*phi[i][qp]*JxW[qp]; Fw(i) += _rho*w_ddot*phi[i][qp]*JxW[qp]; if (request_jacobian) { for (unsigned int j=0; j != n_u_dofs; j++) { libMesh::Real jac_term = _rho*phi[i][qp]*phi[j][qp]*JxW[qp]; jac_term *= context.get_elem_solution_accel_derivative(); Kuu(i,j) += jac_term; Kvv(i,j) += jac_term; Kww(i,j) += jac_term; } } } } // If the Jacobian was requested, we computed it. Otherwise, we didn't. return request_jacobian; }