void ElasticMembranePressure<PressureType>::element_time_derivative ( bool compute_jacobian, AssemblyContext & context ) { unsigned int u_var = this->_disp_vars.u(); unsigned int v_var = this->_disp_vars.v(); unsigned int w_var = this->_disp_vars.w(); const unsigned int n_u_dofs = context.get_dof_indices(u_var).size(); const std::vector<libMesh::Real> &JxW = this->get_fe(context)->get_JxW(); const std::vector<std::vector<libMesh::Real> >& u_phi = this->get_fe(context)->get_phi(); const MultiphysicsSystem & system = context.get_multiphysics_system(); unsigned int u_dot_var = system.get_second_order_dot_var(u_var); unsigned int v_dot_var = system.get_second_order_dot_var(v_var); unsigned int w_dot_var = system.get_second_order_dot_var(w_var); libMesh::DenseSubVector<libMesh::Number> &Fu = context.get_elem_residual(u_dot_var); libMesh::DenseSubVector<libMesh::Number> &Fv = context.get_elem_residual(v_dot_var); libMesh::DenseSubVector<libMesh::Number> &Fw = context.get_elem_residual(w_dot_var); libMesh::DenseSubMatrix<libMesh::Number>& Kuv = context.get_elem_jacobian(u_dot_var,v_var); libMesh::DenseSubMatrix<libMesh::Number>& Kuw = context.get_elem_jacobian(u_dot_var,w_var); libMesh::DenseSubMatrix<libMesh::Number>& Kvu = context.get_elem_jacobian(v_dot_var,u_var); libMesh::DenseSubMatrix<libMesh::Number>& Kvw = context.get_elem_jacobian(v_dot_var,w_var); libMesh::DenseSubMatrix<libMesh::Number>& Kwu = context.get_elem_jacobian(w_dot_var,u_var); libMesh::DenseSubMatrix<libMesh::Number>& Kwv = context.get_elem_jacobian(w_dot_var,v_var); unsigned int n_qpoints = context.get_element_qrule().n_points(); // All shape function gradients are w.r.t. master element coordinates const std::vector<std::vector<libMesh::Real> >& dphi_dxi = this->get_fe(context)->get_dphidxi(); const std::vector<std::vector<libMesh::Real> >& dphi_deta = this->get_fe(context)->get_dphideta(); const libMesh::DenseSubVector<libMesh::Number>& u_coeffs = context.get_elem_solution( u_var ); const libMesh::DenseSubVector<libMesh::Number>& v_coeffs = context.get_elem_solution( v_var ); const libMesh::DenseSubVector<libMesh::Number>& w_coeffs = context.get_elem_solution( w_var ); const std::vector<libMesh::RealGradient>& dxdxi = this->get_fe(context)->get_dxyzdxi(); const std::vector<libMesh::RealGradient>& dxdeta = this->get_fe(context)->get_dxyzdeta(); for (unsigned int qp=0; qp != n_qpoints; qp++) { // sqrt(det(a_cov)), a_cov being the covariant metric tensor of undeformed body libMesh::Real sqrt_a = sqrt( dxdxi[qp]*dxdxi[qp]*dxdeta[qp]*dxdeta[qp] - dxdxi[qp]*dxdeta[qp]*dxdeta[qp]*dxdxi[qp] ); // Gradients are w.r.t. master element coordinates libMesh::Gradient grad_u, grad_v, grad_w; for( unsigned int d = 0; d < n_u_dofs; d++ ) { libMesh::RealGradient u_gradphi( dphi_dxi[d][qp], dphi_deta[d][qp] ); grad_u += u_coeffs(d)*u_gradphi; grad_v += v_coeffs(d)*u_gradphi; grad_w += w_coeffs(d)*u_gradphi; } libMesh::RealGradient dudxi( grad_u(0), grad_v(0), grad_w(0) ); libMesh::RealGradient dudeta( grad_u(1), grad_v(1), grad_w(1) ); libMesh::RealGradient A_1 = dxdxi[qp] + dudxi; libMesh::RealGradient A_2 = dxdeta[qp] + dudeta; libMesh::RealGradient A_3 = A_1.cross(A_2); // Compute pressure at this quadrature point libMesh::Real press = (*_pressure)(context,qp); // Small optimization libMesh::Real p_over_sa = press/sqrt_a; /* The formula here is actually P*\sqrt{\frac{A}{a}}*A_3, where A_3 is a unit vector But, |A_3| = \sqrt{A} so the normalizing part kills the \sqrt{A} in the numerator, so we can leave it out and *not* normalize A_3. */ libMesh::RealGradient traction = p_over_sa*A_3; for (unsigned int i=0; i != n_u_dofs; i++) { // Small optimization libMesh::Real phi_times_jac = u_phi[i][qp]*JxW[qp]; Fu(i) -= traction(0)*phi_times_jac; Fv(i) -= traction(1)*phi_times_jac; Fw(i) -= traction(2)*phi_times_jac; if( compute_jacobian ) { for (unsigned int j=0; j != n_u_dofs; j++) { libMesh::RealGradient u_gradphi( dphi_dxi[j][qp], dphi_deta[j][qp] ); const libMesh::Real dt0_dv = p_over_sa*(u_gradphi(0)*A_2(2) - A_1(2)*u_gradphi(1)); const libMesh::Real dt0_dw = p_over_sa*(A_1(1)*u_gradphi(1) - u_gradphi(0)*A_2(1)); const libMesh::Real dt1_du = p_over_sa*(A_1(2)*u_gradphi(1) - u_gradphi(0)*A_2(2)); const libMesh::Real dt1_dw = p_over_sa*(u_gradphi(0)*A_2(0) - A_1(0)*u_gradphi(1)); const libMesh::Real dt2_du = p_over_sa*(u_gradphi(0)*A_2(1) - A_1(1)*u_gradphi(1)); const libMesh::Real dt2_dv = p_over_sa*(A_1(0)*u_gradphi(1) - u_gradphi(0)*A_2(0)); Kuv(i,j) -= dt0_dv*phi_times_jac; Kuw(i,j) -= dt0_dw*phi_times_jac; Kvu(i,j) -= dt1_du*phi_times_jac; Kvw(i,j) -= dt1_dw*phi_times_jac; Kwu(i,j) -= dt2_du*phi_times_jac; Kwv(i,j) -= dt2_dv*phi_times_jac; } } } } }
void ElasticCableRayleighDamping<StressStrainLaw>::damping_residual( bool compute_jacobian, AssemblyContext& context, CachedValues& /*cache*/) { // First, do the "mass" contribution this->mass_residual_impl(compute_jacobian, context, &libMesh::FEMContext::interior_rate, &libMesh::DiffContext::get_elem_solution_rate_derivative, _mu_factor); // Now do the stiffness contribution const unsigned int n_u_dofs = context.get_dof_indices(this->_disp_vars.u()).size(); const std::vector<libMesh::Real> &JxW = this->get_fe(context)->get_JxW(); // Residuals that we're populating libMesh::DenseSubVector<libMesh::Number> &Fu = context.get_elem_residual(this->_disp_vars.u()); libMesh::DenseSubVector<libMesh::Number> &Fv = context.get_elem_residual(this->_disp_vars.v()); libMesh::DenseSubVector<libMesh::Number> &Fw = context.get_elem_residual(this->_disp_vars.w()); //Grab the Jacobian matrix as submatrices //libMesh::DenseMatrix<libMesh::Number> &K = context.get_elem_jacobian(); libMesh::DenseSubMatrix<libMesh::Number> &Kuu = context.get_elem_jacobian(this->_disp_vars.u(),this->_disp_vars.u()); libMesh::DenseSubMatrix<libMesh::Number> &Kuv = context.get_elem_jacobian(this->_disp_vars.u(),this->_disp_vars.v()); libMesh::DenseSubMatrix<libMesh::Number> &Kuw = context.get_elem_jacobian(this->_disp_vars.u(),this->_disp_vars.w()); libMesh::DenseSubMatrix<libMesh::Number> &Kvu = context.get_elem_jacobian(this->_disp_vars.v(),this->_disp_vars.u()); libMesh::DenseSubMatrix<libMesh::Number> &Kvv = context.get_elem_jacobian(this->_disp_vars.v(),this->_disp_vars.v()); libMesh::DenseSubMatrix<libMesh::Number> &Kvw = context.get_elem_jacobian(this->_disp_vars.v(),this->_disp_vars.w()); libMesh::DenseSubMatrix<libMesh::Number> &Kwu = context.get_elem_jacobian(this->_disp_vars.w(),this->_disp_vars.u()); libMesh::DenseSubMatrix<libMesh::Number> &Kwv = context.get_elem_jacobian(this->_disp_vars.w(),this->_disp_vars.v()); libMesh::DenseSubMatrix<libMesh::Number> &Kww = context.get_elem_jacobian(this->_disp_vars.w(),this->_disp_vars.w()); unsigned int n_qpoints = context.get_element_qrule().n_points(); // All shape function gradients are w.r.t. master element coordinates const std::vector<std::vector<libMesh::Real> >& dphi_dxi = this->get_fe(context)->get_dphidxi(); const libMesh::DenseSubVector<libMesh::Number>& u_coeffs = context.get_elem_solution( this->_disp_vars.u() ); const libMesh::DenseSubVector<libMesh::Number>& v_coeffs = context.get_elem_solution( this->_disp_vars.v() ); const libMesh::DenseSubVector<libMesh::Number>& w_coeffs = context.get_elem_solution( this->_disp_vars.w() ); const libMesh::DenseSubVector<libMesh::Number>& dudt_coeffs = context.get_elem_solution_rate( this->_disp_vars.u() ); const libMesh::DenseSubVector<libMesh::Number>& dvdt_coeffs = context.get_elem_solution_rate( this->_disp_vars.v() ); const libMesh::DenseSubVector<libMesh::Number>& dwdt_coeffs = context.get_elem_solution_rate( this->_disp_vars.w() ); // Need these to build up the covariant and contravariant metric tensors const std::vector<libMesh::RealGradient>& dxdxi = this->get_fe(context)->get_dxyzdxi(); const unsigned int dim = 1; // The cable dimension is always 1 for this physics for (unsigned int qp=0; qp != n_qpoints; qp++) { // Gradients are w.r.t. master element coordinates libMesh::Gradient grad_u, grad_v, grad_w; libMesh::Gradient dgradu_dt, dgradv_dt, dgradw_dt; for( unsigned int d = 0; d < n_u_dofs; d++ ) { libMesh::RealGradient u_gradphi( dphi_dxi[d][qp] ); grad_u += u_coeffs(d)*u_gradphi; grad_v += v_coeffs(d)*u_gradphi; grad_w += w_coeffs(d)*u_gradphi; dgradu_dt += dudt_coeffs(d)*u_gradphi; dgradv_dt += dvdt_coeffs(d)*u_gradphi; dgradw_dt += dwdt_coeffs(d)*u_gradphi; } libMesh::RealGradient grad_x( dxdxi[qp](0) ); libMesh::RealGradient grad_y( dxdxi[qp](1) ); libMesh::RealGradient grad_z( dxdxi[qp](2) ); libMesh::TensorValue<libMesh::Real> a_cov, a_contra, A_cov, A_contra; libMesh::Real lambda_sq = 0; this->compute_metric_tensors( qp, *(this->get_fe(context)), context, grad_u, grad_v, grad_w, a_cov, a_contra, A_cov, A_contra, lambda_sq ); // Compute stress tensor libMesh::TensorValue<libMesh::Real> tau; ElasticityTensor C; this->_stress_strain_law.compute_stress_and_elasticity(dim,a_contra,a_cov,A_contra,A_cov,tau,C); libMesh::Real jac = JxW[qp]; for (unsigned int i=0; i != n_u_dofs; i++) { libMesh::RealGradient u_gradphi( dphi_dxi[i][qp] ); libMesh::Real u_diag_factor = _lambda_factor*this->_A*jac*tau(0,0)*dgradu_dt(0)*u_gradphi(0); libMesh::Real v_diag_factor = _lambda_factor*this->_A*jac*tau(0,0)*dgradv_dt(0)*u_gradphi(0); libMesh::Real w_diag_factor = _lambda_factor*this->_A*jac*tau(0,0)*dgradw_dt(0)*u_gradphi(0); const libMesh::Real C1 = _lambda_factor*this->_A*jac*C(0,0,0,0)*u_gradphi(0); const libMesh::Real gamma_u = (grad_x(0)+grad_u(0)); const libMesh::Real gamma_v = (grad_y(0)+grad_v(0)); const libMesh::Real gamma_w = (grad_z(0)+grad_w(0)); const libMesh::Real x_term = C1*gamma_u; const libMesh::Real y_term = C1*gamma_v; const libMesh::Real z_term = C1*gamma_w; const libMesh::Real dt_term = dgradu_dt(0)*gamma_u + dgradv_dt(0)*gamma_v + dgradw_dt(0)*gamma_w; Fu(i) += u_diag_factor + x_term*dt_term; Fv(i) += v_diag_factor + y_term*dt_term; Fw(i) += w_diag_factor + z_term*dt_term; } if( compute_jacobian ) { for(unsigned int i=0; i != n_u_dofs; i++) { libMesh::RealGradient u_gradphi_I( dphi_dxi[i][qp] ); for(unsigned int j=0; j != n_u_dofs; j++) { libMesh::RealGradient u_gradphi_J( dphi_dxi[j][qp] ); libMesh::Real common_factor = _lambda_factor*this->_A*jac*u_gradphi_I(0); const libMesh::Real diag_term_1 = common_factor*tau(0,0)*u_gradphi_J(0)*context.get_elem_solution_rate_derivative(); const libMesh::Real dgamma_du = ( u_gradphi_J(0)*(grad_x(0)+grad_u(0)) ); const libMesh::Real dgamma_dv = ( u_gradphi_J(0)*(grad_y(0)+grad_v(0)) ); const libMesh::Real dgamma_dw = ( u_gradphi_J(0)*(grad_z(0)+grad_w(0)) ); const libMesh::Real diag_term_2_factor = common_factor*C(0,0,0,0)*context.get_elem_solution_derivative(); Kuu(i,j) += diag_term_1 + dgradu_dt(0)*diag_term_2_factor*dgamma_du; Kuv(i,j) += dgradu_dt(0)*diag_term_2_factor*dgamma_dv; Kuw(i,j) += dgradu_dt(0)*diag_term_2_factor*dgamma_dw; Kvu(i,j) += dgradv_dt(0)*diag_term_2_factor*dgamma_du; Kvv(i,j) += diag_term_1 + dgradv_dt(0)*diag_term_2_factor*dgamma_dv; Kvw(i,j) += dgradv_dt(0)*diag_term_2_factor*dgamma_dw; Kwu(i,j) += dgradw_dt(0)*diag_term_2_factor*dgamma_du; Kwv(i,j) += dgradw_dt(0)*diag_term_2_factor*dgamma_dv; Kww(i,j) += diag_term_1 + dgradw_dt(0)*diag_term_2_factor*dgamma_dw; const libMesh::Real C1 = common_factor*C(0,0,0,0); const libMesh::Real gamma_u = (grad_x(0)+grad_u(0)); const libMesh::Real gamma_v = (grad_y(0)+grad_v(0)); const libMesh::Real gamma_w = (grad_z(0)+grad_w(0)); const libMesh::Real x_term = C1*gamma_u; const libMesh::Real y_term = C1*gamma_v; const libMesh::Real z_term = C1*gamma_w; const libMesh::Real ddtterm_du = u_gradphi_J(0)*(gamma_u*context.get_elem_solution_rate_derivative() + dgradu_dt(0)*context.get_elem_solution_derivative()); const libMesh::Real ddtterm_dv = u_gradphi_J(0)*(gamma_v*context.get_elem_solution_rate_derivative() + dgradv_dt(0)*context.get_elem_solution_derivative()); const libMesh::Real ddtterm_dw = u_gradphi_J(0)*(gamma_w*context.get_elem_solution_rate_derivative() + dgradw_dt(0)*context.get_elem_solution_derivative()); Kuu(i,j) += x_term*ddtterm_du; Kuv(i,j) += x_term*ddtterm_dv; Kuw(i,j) += x_term*ddtterm_dw; Kvu(i,j) += y_term*ddtterm_du; Kvv(i,j) += y_term*ddtterm_dv; Kvw(i,j) += y_term*ddtterm_dw; Kwu(i,j) += z_term*ddtterm_du; Kwv(i,j) += z_term*ddtterm_dv; Kww(i,j) += z_term*ddtterm_dw; const libMesh::Real dt_term = dgradu_dt(0)*gamma_u + dgradv_dt(0)*gamma_v + dgradw_dt(0)*gamma_w; // Here, we're missing derivatives of C(0,0,0,0) w.r.t. strain // Nonzero for hyperelasticity models const libMesh::Real dxterm_du = C1*u_gradphi_J(0)*context.get_elem_solution_derivative(); const libMesh::Real dyterm_dv = dxterm_du; const libMesh::Real dzterm_dw = dxterm_du; Kuu(i,j) += dxterm_du*dt_term; Kvv(i,j) += dyterm_dv*dt_term; Kww(i,j) += dzterm_dw*dt_term; } // end j-loop } // end i-loop } // end if(compute_jacobian) } // end qp loop }
void ElasticMembraneConstantPressure::element_time_derivative( bool compute_jacobian, AssemblyContext& context, CachedValues& /*cache*/ ) { const unsigned int n_u_dofs = context.get_dof_indices(_disp_vars.u()).size(); const std::vector<libMesh::Real> &JxW = this->get_fe(context)->get_JxW(); const std::vector<std::vector<libMesh::Real> >& u_phi = this->get_fe(context)->get_phi(); libMesh::DenseSubVector<libMesh::Number> &Fu = context.get_elem_residual(_disp_vars.u()); libMesh::DenseSubVector<libMesh::Number> &Fv = context.get_elem_residual(_disp_vars.v()); libMesh::DenseSubVector<libMesh::Number> &Fw = context.get_elem_residual(_disp_vars.w()); libMesh::DenseSubMatrix<libMesh::Number>& Kuv = context.get_elem_jacobian(_disp_vars.u(),_disp_vars.v()); libMesh::DenseSubMatrix<libMesh::Number>& Kuw = context.get_elem_jacobian(_disp_vars.u(),_disp_vars.w()); libMesh::DenseSubMatrix<libMesh::Number>& Kvu = context.get_elem_jacobian(_disp_vars.v(),_disp_vars.u()); libMesh::DenseSubMatrix<libMesh::Number>& Kvw = context.get_elem_jacobian(_disp_vars.v(),_disp_vars.w()); libMesh::DenseSubMatrix<libMesh::Number>& Kwu = context.get_elem_jacobian(_disp_vars.w(),_disp_vars.u()); libMesh::DenseSubMatrix<libMesh::Number>& Kwv = context.get_elem_jacobian(_disp_vars.w(),_disp_vars.v()); unsigned int n_qpoints = context.get_element_qrule().n_points(); // All shape function gradients are w.r.t. master element coordinates const std::vector<std::vector<libMesh::Real> >& dphi_dxi = this->get_fe(context)->get_dphidxi(); const std::vector<std::vector<libMesh::Real> >& dphi_deta = this->get_fe(context)->get_dphideta(); const libMesh::DenseSubVector<libMesh::Number>& u_coeffs = context.get_elem_solution( _disp_vars.u() ); const libMesh::DenseSubVector<libMesh::Number>& v_coeffs = context.get_elem_solution( _disp_vars.v() ); const libMesh::DenseSubVector<libMesh::Number>& w_coeffs = context.get_elem_solution( _disp_vars.w() ); const std::vector<libMesh::RealGradient>& dxdxi = this->get_fe(context)->get_dxyzdxi(); const std::vector<libMesh::RealGradient>& dxdeta = this->get_fe(context)->get_dxyzdeta(); for (unsigned int qp=0; qp != n_qpoints; qp++) { // sqrt(det(a_cov)), a_cov being the covariant metric tensor of undeformed body libMesh::Real sqrt_a = sqrt( dxdxi[qp]*dxdxi[qp]*dxdeta[qp]*dxdeta[qp] - dxdxi[qp]*dxdeta[qp]*dxdeta[qp]*dxdxi[qp] ); // Gradients are w.r.t. master element coordinates libMesh::Gradient grad_u, grad_v, grad_w; for( unsigned int d = 0; d < n_u_dofs; d++ ) { libMesh::RealGradient u_gradphi( dphi_dxi[d][qp], dphi_deta[d][qp] ); grad_u += u_coeffs(d)*u_gradphi; grad_v += v_coeffs(d)*u_gradphi; grad_w += w_coeffs(d)*u_gradphi; } libMesh::RealGradient dudxi( grad_u(0), grad_v(0), grad_w(0) ); libMesh::RealGradient dudeta( grad_u(1), grad_v(1), grad_w(1) ); libMesh::RealGradient A_1 = dxdxi[qp] + dudxi; libMesh::RealGradient A_2 = dxdeta[qp] + dudeta; libMesh::RealGradient A_3 = A_1.cross(A_2); /* The formula here is actually P*\sqrt{\frac{A}{a}}*A_3, where A_3 is a unit vector But, |A_3| = \sqrt{A} so the normalizing part kills the \sqrt{A} in the numerator, so we can leave it out and *not* normalize A_3. */ libMesh::RealGradient traction = _pressure/sqrt_a*A_3; libMesh::Real jac = JxW[qp]; for (unsigned int i=0; i != n_u_dofs; i++) { Fu(i) -= traction(0)*u_phi[i][qp]*jac; Fv(i) -= traction(1)*u_phi[i][qp]*jac; Fw(i) -= traction(2)*u_phi[i][qp]*jac; if( compute_jacobian ) { for (unsigned int j=0; j != n_u_dofs; j++) { libMesh::RealGradient u_gradphi( dphi_dxi[j][qp], dphi_deta[j][qp] ); const libMesh::Real dt0_dv = _pressure/sqrt_a*(u_gradphi(0)*A_2(2) - A_1(2)*u_gradphi(1)); const libMesh::Real dt0_dw = _pressure/sqrt_a*(A_1(1)*u_gradphi(1) - u_gradphi(0)*A_2(1)); const libMesh::Real dt1_du = _pressure/sqrt_a*(A_1(2)*u_gradphi(1) - u_gradphi(0)*A_2(2)); const libMesh::Real dt1_dw = _pressure/sqrt_a*(u_gradphi(0)*A_2(0) - A_1(0)*u_gradphi(1)); const libMesh::Real dt2_du = _pressure/sqrt_a*(u_gradphi(0)*A_2(1) - A_1(1)*u_gradphi(1)); const libMesh::Real dt2_dv = _pressure/sqrt_a*(A_1(0)*u_gradphi(1) - u_gradphi(0)*A_2(0)); Kuv(i,j) -= dt0_dv*u_phi[i][qp]*jac; Kuw(i,j) -= dt0_dw*u_phi[i][qp]*jac; Kvu(i,j) -= dt1_du*u_phi[i][qp]*jac; Kvw(i,j) -= dt1_dw*u_phi[i][qp]*jac; Kwu(i,j) -= dt2_du*u_phi[i][qp]*jac; Kwv(i,j) -= dt2_dv*u_phi[i][qp]*jac; } } } } return; }