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
  }
Example #2
0
  void BoussinesqBuoyancy::element_time_derivative
  ( bool compute_jacobian,
    AssemblyContext & context )
  {
    // The number of local degrees of freedom in each variable.
    const unsigned int n_u_dofs = context.get_dof_indices(_flow_vars.u()).size();
    const unsigned int n_T_dofs = context.get_dof_indices(_temp_vars.T()).size();

    // Element Jacobian * quadrature weights for interior integration.
    const std::vector<libMesh::Real> &JxW =
      context.get_element_fe(_flow_vars.u())->get_JxW();

    // The velocity shape functions at interior quadrature points.
    const std::vector<std::vector<libMesh::Real> >& vel_phi =
      context.get_element_fe(_flow_vars.u())->get_phi();

    // The temperature shape functions at interior quadrature points.
    const std::vector<std::vector<libMesh::Real> >& T_phi =
      context.get_element_fe(_temp_vars.T())->get_phi();

    // Get residuals
    libMesh::DenseSubVector<libMesh::Number> &Fu = context.get_elem_residual(_flow_vars.u()); // R_{u}
    libMesh::DenseSubVector<libMesh::Number> &Fv = context.get_elem_residual(_flow_vars.v()); // R_{v}
    libMesh::DenseSubVector<libMesh::Number>* Fw = NULL;

    // Get Jacobians
    libMesh::DenseSubMatrix<libMesh::Number> &KuT = context.get_elem_jacobian(_flow_vars.u(), _temp_vars.T()); // R_{u},{T}
    libMesh::DenseSubMatrix<libMesh::Number> &KvT = context.get_elem_jacobian(_flow_vars.v(), _temp_vars.T()); // R_{v},{T}
    libMesh::DenseSubMatrix<libMesh::Number>* KwT = NULL;



    if( this->_flow_vars.dim() == 3 )
      {
        Fw  = &context.get_elem_residual(_flow_vars.w()); // R_{w}
        KwT = &context.get_elem_jacobian(_flow_vars.w(), _temp_vars.T()); // R_{w},{T}
      }

    // Now we will build the element Jacobian and residual.
    // Constructing the residual requires the solution and its
    // gradient from the previous timestep.  This must be
    // calculated at each quadrature point by summing the
    // solution degree-of-freedom values by the appropriate
    // weight functions.
    unsigned int n_qpoints = context.get_element_qrule().n_points();

    for (unsigned int qp=0; qp != n_qpoints; qp++)
      {
        // Compute the solution & its gradient at the old Newton iterate.
        libMesh::Number T;
        T = context.interior_value(_temp_vars.T(), qp);

        // First, an i-loop over the velocity degrees of freedom.
        // We know that n_u_dofs == n_v_dofs so we can compute contributions
        // for both at the same time.
        for (unsigned int i=0; i != n_u_dofs; i++)
          {
            Fu(i) += -_rho*_beta_T*(T - _T_ref)*_g(0)*vel_phi[i][qp]*JxW[qp];
            Fv(i) += -_rho*_beta_T*(T - _T_ref)*_g(1)*vel_phi[i][qp]*JxW[qp];

            if (this->_flow_vars.dim() == 3)
              (*Fw)(i) += -_rho*_beta_T*(T - _T_ref)*_g(2)*vel_phi[i][qp]*JxW[qp];

            if (compute_jacobian)
              {
                for (unsigned int j=0; j != n_T_dofs; j++)
                  {
                    KuT(i,j) += context.get_elem_solution_derivative() *
                      -_rho*_beta_T*_g(0)*vel_phi[i][qp]*T_phi[j][qp]*JxW[qp];
                    KvT(i,j) += context.get_elem_solution_derivative() *
                      -_rho*_beta_T*_g(1)*vel_phi[i][qp]*T_phi[j][qp]*JxW[qp];

                    if (this->_flow_vars.dim() == 3)
                      (*KwT)(i,j) += context.get_elem_solution_derivative() *
                        -_rho*_beta_T*_g(2)*vel_phi[i][qp]*T_phi[j][qp]*JxW[qp];

                  } // End j dof loop
              } // End compute_jacobian check

          } // End i dof loop
      } // End quadrature loop
  }
  void LowMachNavierStokes<Mu,SH,TC>::assemble_momentum_time_deriv( bool /*compute_jacobian*/, 
								    AssemblyContext& context,
								    CachedValues& cache )
  {
    // The number of local degrees of freedom in each variable.
    const unsigned int n_u_dofs = context.get_dof_indices(this->_u_var).size();

    // Check number of dofs is same for _u_var, v_var and w_var.
    libmesh_assert (n_u_dofs == context.get_dof_indices(this->_v_var).size());
    if (this->_dim == 3)
      libmesh_assert (n_u_dofs == context.get_dof_indices(this->_w_var).size());

    // Element Jacobian * quadrature weights for interior integration.
    const std::vector<libMesh::Real> &JxW =
      context.get_element_fe(this->_u_var)->get_JxW();

    // The pressure shape functions at interior quadrature points.
    const std::vector<std::vector<libMesh::Real> >& u_phi =
      context.get_element_fe(this->_u_var)->get_phi();

    // The velocity shape function gradients at interior quadrature points.
    const std::vector<std::vector<libMesh::RealGradient> >& u_gradphi =
      context.get_element_fe(this->_u_var)->get_dphi();

    libMesh::DenseSubVector<libMesh::Number> &Fu = context.get_elem_residual(this->_u_var); // R_{u}
    libMesh::DenseSubVector<libMesh::Number> &Fv = context.get_elem_residual(this->_v_var); // R_{v}
    libMesh::DenseSubVector<libMesh::Number> &Fw = context.get_elem_residual(this->_w_var); // R_{w}

    unsigned int n_qpoints = context.get_element_qrule().n_points();
    for (unsigned int qp=0; qp != n_qpoints; qp++)
      {
	libMesh::Number u, v, p, p0, T;
	u = cache.get_cached_values(Cache::X_VELOCITY)[qp];
	v = cache.get_cached_values(Cache::Y_VELOCITY)[qp];

	T = cache.get_cached_values(Cache::TEMPERATURE)[qp];
	p = cache.get_cached_values(Cache::PRESSURE)[qp];
	p0 = cache.get_cached_values(Cache::THERMO_PRESSURE)[qp];

	libMesh::Gradient grad_u = cache.get_cached_gradient_values(Cache::X_VELOCITY_GRAD)[qp];
	libMesh::Gradient grad_v = cache.get_cached_gradient_values(Cache::Y_VELOCITY_GRAD)[qp];

	libMesh::Gradient grad_w;
	if (this->_dim == 3)
	  grad_w = cache.get_cached_gradient_values(Cache::Z_VELOCITY_GRAD)[qp];

	libMesh::NumberVectorValue grad_uT( grad_u(0), grad_v(0) ); 
	libMesh::NumberVectorValue grad_vT( grad_u(1), grad_v(1) );
	libMesh::NumberVectorValue grad_wT;
	if( this->_dim == 3 )
	  {
	    grad_uT(2) = grad_w(0);
	    grad_vT(2) = grad_w(1);
	    grad_wT = libMesh::NumberVectorValue( grad_u(2), grad_v(2), grad_w(2) );
	  }

	libMesh::NumberVectorValue U(u,v);
	if (this->_dim == 3)
	  U(2) = cache.get_cached_values(Cache::Z_VELOCITY)[qp]; // w

	libMesh::Number divU = grad_u(0) + grad_v(1);
	if (this->_dim == 3)
	  divU += grad_w(2);

	libMesh::Number rho = this->rho( T, p0 );
      
	// Now a loop over the pressure degrees of freedom.  This
	// computes the contributions of the continuity equation.
	for (unsigned int i=0; i != n_u_dofs; i++)
	  {
	    Fu(i) += ( -rho*U*grad_u*u_phi[i][qp]                 // convection term
		       + p*u_gradphi[i][qp](0)                           // pressure term
		       - this->_mu(T)*(u_gradphi[i][qp]*grad_u + u_gradphi[i][qp]*grad_uT
				       - 2.0/3.0*divU*u_gradphi[i][qp](0) )    // diffusion term
		       + rho*this->_g(0)*u_phi[i][qp]                 // hydrostatic term
		       )*JxW[qp]; 

	    Fv(i) += ( -rho*U*grad_v*u_phi[i][qp]                 // convection term
		       + p*u_gradphi[i][qp](1)                           // pressure term
		       - this->_mu(T)*(u_gradphi[i][qp]*grad_v + u_gradphi[i][qp]*grad_vT
				       - 2.0/3.0*divU*u_gradphi[i][qp](1) )    // diffusion term
		       + rho*this->_g(1)*u_phi[i][qp]                 // hydrostatic term
		       )*JxW[qp];
	    if (this->_dim == 3)
	      {
		Fw(i) += ( -rho*U*grad_w*u_phi[i][qp]                 // convection term
			   + p*u_gradphi[i][qp](2)                           // pressure term
			   - this->_mu(T)*(u_gradphi[i][qp]*grad_w + u_gradphi[i][qp]*grad_wT
					   - 2.0/3.0*divU*u_gradphi[i][qp](2) )    // diffusion term
			   + rho*this->_g(2)*u_phi[i][qp]                 // hydrostatic term
			   )*JxW[qp];
	      }

	    /*
	      if (compute_jacobian && context.get_elem_solution_derivative())
	      {
              libmesh_assert (context.get_elem_solution_derivative() == 1.0);

              for (unsigned int j=0; j != n_u_dofs; j++)
	      {
	      // TODO: precompute some terms like:
	      //   (Uvec*vel_gblgradphivec[j][qp]),
	      //   vel_phi[i][qp]*vel_phi[j][qp],
	      //   (vel_gblgradphivec[i][qp]*vel_gblgradphivec[j][qp])

	      Kuu(i,j) += JxW[qp] *
	      (-_rho*vel_phi[i][qp]*(Uvec*vel_gblgradphivec[j][qp])       // convection term
	      -_rho*vel_phi[i][qp]*graduvec_x*vel_phi[j][qp]             // convection term
	      -_mu*(vel_gblgradphivec[i][qp]*vel_gblgradphivec[j][qp])); // diffusion term
	      Kuv(i,j) += JxW[qp] *
	      (-_rho*vel_phi[i][qp]*graduvec_y*vel_phi[j][qp]);           // convection term

	      Kvv(i,j) += JxW[qp] *
	      (-_rho*vel_phi[i][qp]*(Uvec*vel_gblgradphivec[j][qp])       // convection term
	      -_rho*vel_phi[i][qp]*gradvvec_y*vel_phi[j][qp]             // convection term
	      -_mu*(vel_gblgradphivec[i][qp]*vel_gblgradphivec[j][qp])); // diffusion term
	      Kvu(i,j) += JxW[qp] *
	      (-_rho*vel_phi[i][qp]*gradvvec_x*vel_phi[j][qp]);           // convection term

	      if (_dim == 3)
	      {
	      Kuw(i,j) += JxW[qp] *
	      (-_rho*vel_phi[i][qp]*graduvec_z*vel_phi[j][qp]);           // convection term

	      Kvw(i,j) += JxW[qp] *
	      (-_rho*vel_phi[i][qp]*gradvvec_z*vel_phi[j][qp]);           // convection term

	      Kww(i,j) += JxW[qp] *
	      (-_rho*vel_phi[i][qp]*(Uvec*vel_gblgradphivec[j][qp])       // convection term
	      -_rho*vel_phi[i][qp]*gradwvec_z*vel_phi[j][qp]             // convection term
	      -_mu*(vel_gblgradphivec[i][qp]*vel_gblgradphivec[j][qp])); // diffusion term
	      Kwu(i,j) += JxW[qp] *
	      (-_rho*vel_phi[i][qp]*gradwvec_x*vel_phi[j][qp]);           // convection term
	      Kwv(i,j) += JxW[qp] *
	      (-_rho*vel_phi[i][qp]*gradwvec_y*vel_phi[j][qp]);           // convection term
	      }
	      } // end of the inner dof (j) loop

              // Matrix contributions for the up, vp and wp couplings
              for (unsigned int j=0; j != n_p_dofs; j++)
	      {
	      Kup(i,j) += JxW[qp]*vel_gblgradphivec[i][qp](0)*p_phi[j][qp];
	      Kvp(i,j) += JxW[qp]*vel_gblgradphivec[i][qp](1)*p_phi[j][qp];
	      if (_dim == 3)
	      Kwp(i,j) += JxW[qp]*vel_gblgradphivec[i][qp](2)*p_phi[j][qp];
	      } // end of the inner dof (j) loop

	      } // end - if (compute_jacobian && context.get_elem_solution_derivative())

	      } // end of the outer dof (i) loop
	      } // end of the quadrature point (qp) loop
	    */
	  } // End of DoF loop i
      } // End quadrature loop qp

    return;
  }
Example #4
0
  void AveragedTurbine<Mu>::element_time_derivative( bool compute_jacobian,
					      AssemblyContext& context,
					      CachedValues& /* cache */ )
  {
#ifdef GRINS_USE_GRVY_TIMERS
    this->_timer->BeginTimer("AveragedTurbine::element_time_derivative");
#endif

    // Element Jacobian * quadrature weights for interior integration
    const std::vector<libMesh::Real> &JxW = 
      context.get_element_fe(this->_flow_vars.u())->get_JxW();

    // The shape functions at interior quadrature points.
    const std::vector<std::vector<libMesh::Real> >& u_phi = 
      context.get_element_fe(this->_flow_vars.u())->get_phi();

    const std::vector<libMesh::Point>& u_qpoint = 
      context.get_element_fe(this->_flow_vars.u())->get_xyz();

    // The number of local degrees of freedom in each variable
    const unsigned int n_u_dofs = context.get_dof_indices(this->_flow_vars.u()).size();

    // The subvectors and submatrices we need to fill:
    libMesh::DenseSubMatrix<libMesh::Number> &Kuu = context.get_elem_jacobian(this->_flow_vars.u(), this->_flow_vars.u()); // R_{u},{u}
    libMesh::DenseSubMatrix<libMesh::Number> &Kuv = context.get_elem_jacobian(this->_flow_vars.u(), this->_flow_vars.v()); // R_{u},{v}
    libMesh::DenseSubMatrix<libMesh::Number> &Kvu = context.get_elem_jacobian(this->_flow_vars.v(), this->_flow_vars.u()); // R_{v},{u}
    libMesh::DenseSubMatrix<libMesh::Number> &Kvv = context.get_elem_jacobian(this->_flow_vars.v(), this->_flow_vars.v()); // R_{v},{v}

    libMesh::DenseSubMatrix<libMesh::Number> &Kus =
            context.get_elem_jacobian(this->_flow_vars.u(),
                                      this->fan_speed_var()); // R_{u},{s}
    libMesh::DenseSubMatrix<libMesh::Number> &Ksu =
            context.get_elem_jacobian(this->fan_speed_var(),
                                      this->_flow_vars.u()); // R_{s},{u}
    libMesh::DenseSubMatrix<libMesh::Number> &Kvs =
            context.get_elem_jacobian(this->_flow_vars.v(),
                                      this->fan_speed_var()); // R_{v},{s}
    libMesh::DenseSubMatrix<libMesh::Number> &Ksv =
            context.get_elem_jacobian(this->fan_speed_var(),
                                      this->_flow_vars.v()); // R_{s},{v}
    libMesh::DenseSubMatrix<libMesh::Number> &Kss =
            context.get_elem_jacobian(this->fan_speed_var(),
                                      this->fan_speed_var()); // R_{s},{s}

    libMesh::DenseSubMatrix<libMesh::Number>* Kwu = NULL;
    libMesh::DenseSubMatrix<libMesh::Number>* Kwv = NULL;
    libMesh::DenseSubMatrix<libMesh::Number>* Kww = NULL;
    libMesh::DenseSubMatrix<libMesh::Number>* Kuw = NULL;
    libMesh::DenseSubMatrix<libMesh::Number>* Kvw = NULL;

    libMesh::DenseSubMatrix<libMesh::Number>* Ksw = NULL;
    libMesh::DenseSubMatrix<libMesh::Number>* Kws = NULL;

    libMesh::DenseSubVector<libMesh::Number> &Fu = context.get_elem_residual(this->_flow_vars.u()); // R_{u}
    libMesh::DenseSubVector<libMesh::Number> &Fv = context.get_elem_residual(this->_flow_vars.v()); // R_{v}
    libMesh::DenseSubVector<libMesh::Number>* Fw = NULL;

    libMesh::DenseSubVector<libMesh::Number> &Fs = context.get_elem_residual(this->fan_speed_var()); // R_{s}

    if( this->mesh_dim(context) == 3 )
      {
        Kuw = &context.get_elem_jacobian(this->_flow_vars.u(), this->_flow_vars.w()); // R_{u},{w}
        Kvw = &context.get_elem_jacobian(this->_flow_vars.v(), this->_flow_vars.w()); // R_{v},{w}

        Kwu = &context.get_elem_jacobian(this->_flow_vars.w(), this->_flow_vars.u()); // R_{w},{u}
        Kwv = &context.get_elem_jacobian(this->_flow_vars.w(), this->_flow_vars.v()); // R_{w},{v}
        Kww = &context.get_elem_jacobian(this->_flow_vars.w(), this->_flow_vars.w()); // R_{w},{w}
        Fw  = &context.get_elem_residual(this->_flow_vars.w()); // R_{w}

        Ksw = &context.get_elem_jacobian(this->fan_speed_var(), this->_flow_vars.w()); // R_{s},{w}
        Kws = &context.get_elem_jacobian(this->_flow_vars.w(), this->fan_speed_var()); // R_{w},{s}

        Fw  = &context.get_elem_residual(this->_flow_vars.w()); // R_{w}
      }

    unsigned int n_qpoints = context.get_element_qrule().n_points();

    for (unsigned int qp=0; qp != n_qpoints; qp++)
      {
        // Compute the solution at the old Newton iterate.
        libMesh::Number u, v, s;
        u = context.interior_value(this->_flow_vars.u(), qp);
        v = context.interior_value(this->_flow_vars.v(), qp);
        s = context.interior_value(this->fan_speed_var(), qp);

        libMesh::NumberVectorValue U(u,v);
        if (this->mesh_dim(context) == 3)
          U(2) = context.interior_value(this->_flow_vars.w(), qp); // w

        libMesh::NumberVectorValue U_B_1;
        libMesh::NumberVectorValue F;
        libMesh::NumberTensorValue dFdU;
        libMesh::NumberTensorValue* dFdU_ptr =
          compute_jacobian ? &dFdU : NULL;
        libMesh::NumberVectorValue dFds;
        libMesh::NumberVectorValue* dFds_ptr =
          compute_jacobian ? &dFds : NULL;
        if (!this->compute_force(u_qpoint[qp], context.time, U, s,
                                 U_B_1, F, dFdU_ptr, dFds_ptr))
          continue;

        libMesh::Real jac = JxW[qp];

        // Using this dot product to derive torque *depends* on s=1
        // and U_B_1 corresponding to 1 rad/sec base velocity; this
        // means that the length of U_B_1 is equal to radius.

        // F is the force on the air, so *negative* F is the force on
        // the turbine.
        Fs(0) -= U_B_1 * F * jac;

        if (compute_jacobian)
          {
            Kss(0,0) -= U_B_1 * dFds * jac;

            for (unsigned int j=0; j != n_u_dofs; j++)
              {
                libMesh::Real jac_j = JxW[qp] * u_phi[j][qp];

                for (unsigned int d=0; d != 3; ++d)
                  {
                    Ksu(0,j) -= jac_j * U_B_1(d) * dFdU(d,0);
                    Ksv(0,j) -= jac_j * U_B_1(d) * dFdU(d,1);
                  }

                if (this->mesh_dim(context) == 3)
                  {
                    for (unsigned int d=0; d != 3; ++d)
                      (*Ksw)(0,j) -= jac_j * U_B_1(d) * dFdU(d,2);
                  }

              } // End j dof loop
          }

        for (unsigned int i=0; i != n_u_dofs; i++)
          {
            const libMesh::Number jac_i = jac * u_phi[i][qp];

            Fu(i) += F(0)*jac_i;
            Fv(i) += F(1)*jac_i;

            if( this->mesh_dim(context) == 3 )
              (*Fw)(i) += F(2)*jac_i;

	    if( compute_jacobian )
              {
                Kus(i,0) += dFds(0) * jac_i;
                Kvs(i,0) += dFds(1) * jac_i;
                if( this->mesh_dim(context) == 3 )
                  (*Kws)(i,0) += dFds(2) * jac_i;

                for (unsigned int j=0; j != n_u_dofs; j++)
                  {
                    const libMesh::Number jac_ij = jac_i * u_phi[j][qp];
                    Kuu(i,j) += jac_ij * dFdU(0,0);
                    Kuv(i,j) += jac_ij * dFdU(0,1);
                    Kvu(i,j) += jac_ij * dFdU(1,0);
                    Kvv(i,j) += jac_ij * dFdU(1,1);

                    if( this->mesh_dim(context) == 3 )
                      {
                        (*Kuw)(i,j) += jac_ij * dFdU(0,2);
                        (*Kvw)(i,j) += jac_ij * dFdU(1,2);
                        (*Kwu)(i,j) += jac_ij * dFdU(2,0);
                        (*Kwv)(i,j) += jac_ij * dFdU(2,1);
                        (*Kww)(i,j) += jac_ij * dFdU(2,2);
                      }
                  }
              }
          }
      }


#ifdef GRINS_USE_GRVY_TIMERS
    this->_timer->EndTimer("AveragedTurbine::element_time_derivative");
#endif

    return;
  }
  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 assemble_postvars_rhs (EquationSystems& es,
                      const std::string& system_name)
{

  const Real E    = es.parameters.get<Real>("E");
  const Real NU    = es.parameters.get<Real>("NU");
  const Real KPERM    = es.parameters.get<Real>("KPERM");
  
	Real sum_jac_postvars=0;
	
	Real av_pressure=0;
	Real total_volume=0;

#include "assemble_preamble_postvars.cpp"

  for ( ; el != end_el; ++el)
    {    
 
      const Elem* elem = *el;

      dof_map.dof_indices (elem, dof_indices);
      dof_map.dof_indices (elem, dof_indices_u, u_var);
      dof_map.dof_indices (elem, dof_indices_v, v_var);
      dof_map.dof_indices (elem, dof_indices_p, p_var);
      dof_map.dof_indices (elem, dof_indices_x, x_var);
      dof_map.dof_indices (elem, dof_indices_y, y_var);
      #if THREED
      dof_map.dof_indices (elem, dof_indices_w, w_var);
      dof_map.dof_indices (elem, dof_indices_z, z_var);
      #endif

      const unsigned int n_dofs   = dof_indices.size();
      const unsigned int n_u_dofs = dof_indices_u.size(); 
      const unsigned int n_v_dofs = dof_indices_v.size();
      const unsigned int n_p_dofs = dof_indices_p.size();
      const unsigned int n_x_dofs = dof_indices_x.size(); 
      const unsigned int n_y_dofs = dof_indices_y.size();
      #if THREED
      const unsigned int n_w_dofs = dof_indices_w.size();
      const unsigned int n_z_dofs = dof_indices_z.size();
      #endif
      
      fe_disp->reinit  (elem);
      fe_vel->reinit  (elem);
      fe_pres->reinit (elem);

      Ke.resize (n_dofs, n_dofs);
      Fe.resize (n_dofs);

      Kuu.reposition (u_var*n_u_dofs, u_var*n_u_dofs, n_u_dofs, n_u_dofs);
      Kuv.reposition (u_var*n_u_dofs, v_var*n_u_dofs, n_u_dofs, n_v_dofs);
      Kup.reposition (u_var*n_u_dofs, p_var*n_u_dofs, n_u_dofs, n_p_dofs);
      Kux.reposition (u_var*n_u_dofs, p_var*n_u_dofs + n_p_dofs , n_u_dofs, n_x_dofs);
      Kuy.reposition (u_var*n_u_dofs, p_var*n_u_dofs + n_p_dofs+n_x_dofs , n_u_dofs, n_y_dofs);
      #if THREED
      Kuw.reposition (u_var*n_u_dofs, w_var*n_u_dofs, n_u_dofs, n_w_dofs);
      Kuz.reposition (u_var*n_u_dofs, p_var*n_u_dofs + n_p_dofs+2*n_x_dofs , n_u_dofs, n_z_dofs);
      #endif

      Kvu.reposition (v_var*n_v_dofs, u_var*n_v_dofs, n_v_dofs, n_u_dofs);
      Kvv.reposition (v_var*n_v_dofs, v_var*n_v_dofs, n_v_dofs, n_v_dofs);
      Kvp.reposition (v_var*n_v_dofs, p_var*n_v_dofs, n_v_dofs, n_p_dofs);
      Kvx.reposition (v_var*n_v_dofs, p_var*n_u_dofs + n_p_dofs , n_v_dofs, n_x_dofs);
      Kvy.reposition (v_var*n_v_dofs, p_var*n_u_dofs + n_p_dofs+n_x_dofs , n_v_dofs, n_y_dofs);
      #if THREED
      Kvw.reposition (v_var*n_u_dofs, w_var*n_u_dofs, n_v_dofs, n_w_dofs);
      Kuz.reposition (v_var*n_u_dofs, p_var*n_u_dofs + n_p_dofs+2*n_x_dofs , n_u_dofs, n_z_dofs);
      #endif

      #if THREED
      Kwu.reposition (w_var*n_w_dofs, u_var*n_v_dofs, n_v_dofs, n_u_dofs);
      Kwv.reposition (w_var*n_w_dofs, v_var*n_v_dofs, n_v_dofs, n_v_dofs);
      Kwp.reposition (w_var*n_w_dofs, p_var*n_v_dofs, n_v_dofs, n_p_dofs);
      Kwx.reposition (w_var*n_w_dofs, p_var*n_u_dofs + n_p_dofs , n_v_dofs, n_x_dofs);
      Kwy.reposition (w_var*n_w_dofs, p_var*n_u_dofs + n_p_dofs+n_x_dofs , n_v_dofs, n_y_dofs);
      Kww.reposition (w_var*n_w_dofs, w_var*n_u_dofs, n_v_dofs, n_w_dofs);
      Kwz.reposition (w_var*n_w_dofs, p_var*n_u_dofs + n_p_dofs+2*n_x_dofs , n_u_dofs, n_z_dofs);
      #endif

      Kpu.reposition (p_var*n_u_dofs, u_var*n_u_dofs, n_p_dofs, n_u_dofs);
      Kpv.reposition (p_var*n_u_dofs, v_var*n_u_dofs, n_p_dofs, n_v_dofs);
      Kpp.reposition (p_var*n_u_dofs, p_var*n_u_dofs, n_p_dofs, n_p_dofs);
      Kpx.reposition (p_var*n_v_dofs, p_var*n_u_dofs + n_p_dofs , n_p_dofs, n_x_dofs);
      Kpy.reposition (p_var*n_v_dofs, p_var*n_u_dofs + n_p_dofs+n_x_dofs , n_p_dofs, n_y_dofs);
      #if THREED
      Kpw.reposition (p_var*n_u_dofs, w_var*n_u_dofs, n_p_dofs, n_w_dofs);
      Kpz.reposition (p_var*n_u_dofs, p_var*n_u_dofs + n_p_dofs+2*n_x_dofs , n_p_dofs, n_z_dofs);
      #endif

      Kxu.reposition (p_var*n_u_dofs + n_p_dofs, u_var*n_u_dofs, n_x_dofs, n_u_dofs);
      Kxv.reposition (p_var*n_u_dofs + n_p_dofs, v_var*n_u_dofs, n_x_dofs, n_v_dofs);
      Kxp.reposition (p_var*n_u_dofs + n_p_dofs, p_var*n_u_dofs, n_x_dofs, n_p_dofs);
      Kxx.reposition (p_var*n_u_dofs + n_p_dofs, p_var*n_u_dofs + n_p_dofs , n_x_dofs, n_x_dofs);
      Kxy.reposition (p_var*n_u_dofs + n_p_dofs, p_var*n_u_dofs + n_p_dofs+n_x_dofs , n_x_dofs, n_y_dofs);
      #if THREED
      Kxw.reposition (p_var*n_u_dofs + n_p_dofs, w_var*n_u_dofs, n_x_dofs, n_w_dofs);
      Kxz.reposition (p_var*n_u_dofs + n_p_dofs, p_var*n_u_dofs + n_p_dofs+2*n_x_dofs , n_x_dofs, n_z_dofs);
      #endif


      Kyu.reposition (p_var*n_u_dofs + n_p_dofs+n_x_dofs, u_var*n_u_dofs, n_y_dofs, n_u_dofs);
      Kyv.reposition (p_var*n_u_dofs + n_p_dofs+n_x_dofs, v_var*n_u_dofs, n_y_dofs, n_v_dofs);
      Kyp.reposition (p_var*n_u_dofs + n_p_dofs+n_x_dofs, p_var*n_u_dofs, n_y_dofs, n_p_dofs);
      Kyx.reposition (p_var*n_u_dofs + n_p_dofs+n_x_dofs, p_var*n_u_dofs + n_p_dofs , n_y_dofs, n_x_dofs);
      Kyy.reposition (p_var*n_u_dofs + n_p_dofs+n_x_dofs, p_var*n_u_dofs + n_p_dofs+n_x_dofs , n_y_dofs, n_y_dofs);
      #if THREED
      Kyw.reposition (p_var*n_u_dofs + n_p_dofs+n_x_dofs, w_var*n_u_dofs, n_x_dofs, n_w_dofs);
      Kyz.reposition (p_var*n_u_dofs + n_p_dofs+n_x_dofs, p_var*n_u_dofs + n_p_dofs+2*n_x_dofs , n_x_dofs, n_z_dofs);
      #endif

      #if THREED
      Kzu.reposition (p_var*n_u_dofs + n_p_dofs+2*n_x_dofs, u_var*n_u_dofs, n_y_dofs, n_u_dofs);
      Kzv.reposition (p_var*n_u_dofs + n_p_dofs+2*n_x_dofs, v_var*n_u_dofs, n_y_dofs, n_v_dofs);
      Kzp.reposition (p_var*n_u_dofs + n_p_dofs+2*n_x_dofs, p_var*n_u_dofs, n_y_dofs, n_p_dofs);
      Kzx.reposition (p_var*n_u_dofs + n_p_dofs+2*n_x_dofs, p_var*n_u_dofs + n_p_dofs , n_y_dofs, n_x_dofs);
      Kzy.reposition (p_var*n_u_dofs + n_p_dofs+2*n_x_dofs, p_var*n_u_dofs + n_p_dofs+n_x_dofs , n_y_dofs, n_y_dofs);
      Kzw.reposition (p_var*n_u_dofs + n_p_dofs+2*n_x_dofs, w_var*n_u_dofs, n_x_dofs, n_w_dofs);
      Kzz.reposition (p_var*n_u_dofs + n_p_dofs+2*n_x_dofs, p_var*n_u_dofs + n_p_dofs+2*n_x_dofs , n_x_dofs, n_z_dofs);
      #endif



      Fu.reposition (u_var*n_u_dofs, n_u_dofs);
      Fv.reposition (v_var*n_u_dofs, n_v_dofs);
      Fp.reposition (p_var*n_u_dofs, n_p_dofs);
      Fx.reposition (p_var*n_u_dofs + n_p_dofs, n_x_dofs);
      Fy.reposition (p_var*n_u_dofs + n_p_dofs+n_x_dofs, n_y_dofs);
      #if THREED
      Fw.reposition (w_var*n_u_dofs, n_w_dofs);
      Fz.reposition (p_var*n_u_dofs + n_p_dofs+2*n_x_dofs, n_y_dofs);
      #endif
    
	    std::vector<unsigned int> undefo_index;
		  PoroelasticConfig material(dphi,psi);

		
      // Now we will build the element matrix.
      for (unsigned int qp=0; qp<qrule.n_points(); qp++)
        {       
		  
		  
		  Number   p_solid = 0.;

		  grad_u_mat(0) = grad_u_mat(1) = grad_u_mat(2) = 0;
		
		  for (unsigned int d = 0; d < dim; ++d) {
			std::vector<Number> u_undefo;
			std::vector<Number> u_undefo_ref;

			//Fills the vector di with the global degree of freedom indices for the element. :dof_indicies
			
			

			
			Last_non_linear_soln.get_dof_map().dof_indices(elem, undefo_index,d);
			Last_non_linear_soln.current_local_solution->get(undefo_index, u_undefo);
			reference.current_local_solution->get(undefo_index, u_undefo_ref);

			for (unsigned int l = 0; l != n_u_dofs; l++){
			   grad_u_mat(d).add_scaled(dphi[l][qp], u_undefo[l]+u_undefo_ref[l]); 
			}
		  }
          
		  for (unsigned int l=0; l<n_p_dofs; l++)
		  {
			p_solid += psi[l][qp]*Last_non_linear_soln.current_local_solution->el(dof_indices_p[l]);
		}
		
		Point rX;
		material.init_for_qp(rX,grad_u_mat, p_solid, qp,0, p_solid,es);
		Real J=material.J;
		 Real I_1=material.I_1;
		 Real I_2=material.I_2;
		 Real I_3=material.I_3;
		 RealTensor sigma=material.sigma;
		 
		 av_pressure=av_pressure + p_solid*JxW[qp];
		 
		 /*
		 		 		std::cout<<"grad_u_mat(0)" << grad_u_mat(0) <<std::endl;

		 		std::cout<<" J " << J <<std::endl;

		std::cout<<" sigma " << sigma <<std::endl;
		*/
		 Real sigma_sum_sq=pow(sigma(0,0)*sigma(0,0)+sigma(0,1)*sigma(0,1)+sigma(0,2)*sigma(0,2)+sigma(1,0)*sigma(1,0)+sigma(1,1)*sigma(1,1)+sigma(1,2)*sigma(1,2)+sigma(2,0)*sigma(2,0)+sigma(2,1)*sigma(2,1)+sigma(2,2)*sigma(2,2),0.5);
		 
		// std::cout<<" J " << J <<std::endl;


		 sum_jac_postvars=sum_jac_postvars+JxW[qp];
 

		
		for (unsigned int i=0; i<n_u_dofs; i++){
          Fu(i) += I_1*JxW[qp]*phi[i][qp];
          Fv(i) += I_2*JxW[qp]*phi[i][qp];
          Fw(i) += I_3*JxW[qp]*phi[i][qp];

	        Fx(i) += sigma_sum_sq*JxW[qp]*phi[i][qp];
          Fy(i) += J*JxW[qp]*phi[i][qp];
          Fz(i) += 0*JxW[qp]*phi[i][qp];
    }
    
    
 
		for (unsigned int i=0; i<n_p_dofs; i++){
            Fp(i) += J*JxW[qp]*psi[i][qp];
		}
    
          

          
          
} // end qp





  system.rhs->add_vector(Fe, dof_indices);

  system.matrix->add_matrix (Ke, dof_indices);

} // end of element loop
  
	
    system.matrix->close();
    system.rhs->close();



    std::cout<<"Assemble postvars rhs->l2_norm () "<<system.rhs->l2_norm ()<<std::endl;

		
	 std::cout<<"sum_jac   "<< sum_jac_postvars <<std::endl;
	 
	  std::cout<<"av_pressure   "<< av_pressure/sum_jac_postvars <<std::endl;

  return;
}
Example #7
0
  void VelocityPenalty<Mu>::element_time_derivative( bool compute_jacobian,
					         AssemblyContext& context,
					         CachedValues& /* cache */ )
  {
#ifdef GRINS_USE_GRVY_TIMERS
    this->_timer->BeginTimer("VelocityPenalty::element_time_derivative");
#endif

    // Element Jacobian * quadrature weights for interior integration
    const std::vector<libMesh::Real> &JxW = 
      context.get_element_fe(this->_flow_vars.u_var())->get_JxW();

    // The shape functions at interior quadrature points.
    const std::vector<std::vector<libMesh::Real> >& u_phi = 
      context.get_element_fe(this->_flow_vars.u_var())->get_phi();

    const std::vector<libMesh::Point>& u_qpoint = 
      context.get_element_fe(this->_flow_vars.u_var())->get_xyz();

    // The number of local degrees of freedom in each variable
    const unsigned int n_u_dofs = context.get_dof_indices(this->_flow_vars.u_var()).size();

    // The subvectors and submatrices we need to fill:
    libMesh::DenseSubMatrix<libMesh::Number> &Kuu = context.get_elem_jacobian(this->_flow_vars.u_var(), this->_flow_vars.u_var()); // R_{u},{u}
    libMesh::DenseSubMatrix<libMesh::Number> &Kuv = context.get_elem_jacobian(this->_flow_vars.u_var(), this->_flow_vars.v_var()); // R_{u},{v}
    libMesh::DenseSubMatrix<libMesh::Number> &Kvu = context.get_elem_jacobian(this->_flow_vars.v_var(), this->_flow_vars.u_var()); // R_{v},{u}
    libMesh::DenseSubMatrix<libMesh::Number> &Kvv = context.get_elem_jacobian(this->_flow_vars.v_var(), this->_flow_vars.v_var()); // R_{v},{v}

    libMesh::DenseSubMatrix<libMesh::Number>* Kwu = NULL;
    libMesh::DenseSubMatrix<libMesh::Number>* Kwv = NULL;
    libMesh::DenseSubMatrix<libMesh::Number>* Kww = NULL;
    libMesh::DenseSubMatrix<libMesh::Number>* Kuw = NULL;
    libMesh::DenseSubMatrix<libMesh::Number>* Kvw = NULL;

    libMesh::DenseSubVector<libMesh::Number> &Fu = context.get_elem_residual(this->_flow_vars.u_var()); // R_{u}
    libMesh::DenseSubVector<libMesh::Number> &Fv = context.get_elem_residual(this->_flow_vars.v_var()); // R_{v}
    libMesh::DenseSubVector<libMesh::Number>* Fw = NULL;

    if( this->_dim == 3 )
      {
        Kuw = &context.get_elem_jacobian(this->_flow_vars.u_var(), this->_flow_vars.w_var()); // R_{u},{w}
        Kvw = &context.get_elem_jacobian(this->_flow_vars.v_var(), this->_flow_vars.w_var()); // R_{v},{w}

        Kwu = &context.get_elem_jacobian(this->_flow_vars.w_var(), this->_flow_vars.u_var()); // R_{w},{u}
        Kwv = &context.get_elem_jacobian(this->_flow_vars.w_var(), this->_flow_vars.v_var()); // R_{w},{v}
        Kww = &context.get_elem_jacobian(this->_flow_vars.w_var(), this->_flow_vars.w_var()); // R_{w},{w}
        Fw  = &context.get_elem_residual(this->_flow_vars.w_var()); // R_{w}
      }

    unsigned int n_qpoints = context.get_element_qrule().n_points();

    for (unsigned int qp=0; qp != n_qpoints; qp++)
      {
        // Compute the solution at the old Newton iterate.
        libMesh::Number u, v;
        u = context.interior_value(this->_flow_vars.u_var(), qp);
        v = context.interior_value(this->_flow_vars.v_var(), qp);

        libMesh::NumberVectorValue U(u,v);
        if (this->_dim == 3)
          U(2) = context.interior_value(this->_flow_vars.w_var(), qp); // w

        libMesh::NumberVectorValue F;
        libMesh::NumberTensorValue dFdU;
        libMesh::NumberTensorValue* dFdU_ptr =
          compute_jacobian ? &dFdU : NULL;
        if (!this->compute_force(u_qpoint[qp], context, U, F, dFdU_ptr))
          continue;

        const libMesh::Real jac = JxW[qp];

        for (unsigned int i=0; i != n_u_dofs; i++)
          {
            const libMesh::Number jac_i = jac * u_phi[i][qp];

            Fu(i) += F(0)*jac_i;

            Fv(i) += F(1)*jac_i;
            if( this->_dim == 3 )
              {
                (*Fw)(i) += F(2)*jac_i;
              }

	    if( compute_jacobian )
              {
                for (unsigned int j=0; j != n_u_dofs; j++)
                  {
                    const libMesh::Number jac_ij = context.get_elem_solution_derivative() * jac_i * u_phi[j][qp];
                    Kuu(i,j) += jac_ij * dFdU(0,0);
                    Kuv(i,j) += jac_ij * dFdU(0,1);
                    Kvu(i,j) += jac_ij * dFdU(1,0);
                    Kvv(i,j) += jac_ij * dFdU(1,1);

                    if( this->_dim == 3 )
                      {
                        (*Kuw)(i,j) += jac_ij * dFdU(0,2);
                        (*Kvw)(i,j) += jac_ij * dFdU(1,2);

                        (*Kwu)(i,j) += jac_ij * dFdU(2,0);
                        (*Kwv)(i,j) += jac_ij * dFdU(2,1);
                        (*Kww)(i,j) += jac_ij * dFdU(2,2);
                      }
                  }
              }
          }
      }


#ifdef GRINS_USE_GRVY_TIMERS
    this->_timer->EndTimer("VelocityPenalty::element_time_derivative");
#endif

    return;
  }
Example #8
0
float metodo(int i,float gamma,int tam,float dx, float dt,float re0, float re1, float re2, float re0mas, float re1mas, float re2mas,float retam0, float retam1,float retam2,float retmenos0, float retmenos1,float retmenos2,float re0ceros,float re1ceros,float re2ceros, float *salida0,float *salida1,float *salida2){
   
   float U0,U1,U2,U0ceros,U1ceros,U2ceros, Utam0,Utam1,Utam2,Utmenos0,Utmenos1,Utmenos2,U0mas,U1mas,U2mas;
   float utemppos0,utemppos1,utemppos2,utempneg0,utempneg1,utempneg2;
   float F0Umas,F1Umas,F2Umas,F0U,F1U,F2U,F0Uceros,F1Uceros,F2Uceros,F0Utam,F1Utam,F2Utam,F0Umenos,F1Umenos,F2Umenos;
   float Ftemppos0,Ftemppos1,Ftemppos2,Ftempneg0,Ftempneg1,Ftempneg2;
    
   float unew0,unew1,unew2;

    

    Uv(gamma,re0, re1,re2, &U0,&U1,&U2);
    Uv(gamma,re0mas, re1mas, re2mas, &U0mas,&U1mas,&U2mas);
    Uv(gamma,re0ceros, re1ceros, re2ceros, &U0ceros,&U1ceros,&U2ceros);
    Uv(gamma,retam0, retam1,retam2, &Utam0,&Utam1,&Utam2);
    Uv(gamma,retmenos0, retmenos1,retmenos2, &Utmenos0,&Utmenos1,&Utmenos2);

 
    Fv(gamma,U0mas,U1mas,U2mas, &F0Umas,&F1Umas,&F2Umas);
    Fv(gamma,U0,U1,U2, &F0U,&F1U,&F2U);
    Fv(gamma,U0ceros,U1ceros,U2ceros, &F0Uceros,&F1Uceros,&F2Uceros);
    
    Fv(gamma,Utam0,Utam1,Utam2, &F0Utam,&F1Utam,&F2Utam);
    Fv(gamma,Utmenos0,Utmenos1,Utmenos2, &F0Umenos,&F1Umenos,&F2Umenos);
    
    if (i==0){
            utemppos0= 0.5*( U0mas+U0 - (dt/dx)*( F0Umas- F0U ));
            utemppos1= 0.5*( U0mas+U1 - (dt/dx)*( F1Umas- F1U ));
            utemppos2= 0.5*( U0mas+U2 - (dt/dx)*( F2Umas- F2U ));
   
            utempneg0 = 0.5*( U0ceros+U0 - (dt/dx)*( F0Uceros - F0U  ) );
            utempneg1 = 0.5*( U0ceros+U1 - (dt/dx)*( F1Uceros - F1U  ) );
            utempneg2 = 0.5*( U0ceros+U2 - (dt/dx)*( F2Uceros - F2U  ) );
            Fv(gamma,utemppos0, utemppos1, utemppos2, &Ftemppos0,&Ftemppos1,&Ftemppos2);
            Fv(gamma,utempneg0, utempneg1, utempneg2, &Ftempneg0,&Ftempneg1,&Ftempneg2);
      }    
    if (i==(tam-1)){
        
            utemppos0 = 0.5*( Utam0+U0 - (dt/dx)*( F0Utam - F0U ));
            utemppos1 = 0.5*( Utam1+U1 - (dt/dx)*( F1Utam - F1U ));
            utemppos2 = 0.5*( Utam2+U2 - (dt/dx)*( F2Utam - F2U ));

            utempneg0 = 0.5*( Utmenos0+U0 - (dt/dx)*(F0Umenos - F0U ));
            utempneg1 = 0.5*( Utmenos1+U1 - (dt/dx)*(F1Umenos - F1U ));
            utempneg2 = 0.5*( Utmenos2+U2 - (dt/dx)*(F2Umenos - F2U ));
        
            Fv(gamma,utemppos0, utemppos1, utemppos2, &Ftemppos0,&Ftemppos1,&Ftemppos2);
            Fv(gamma,utempneg0, utempneg1, utempneg2, &Ftempneg0,&Ftempneg1,&Ftempneg2);
          }
    else {
    
            utemppos0 = 0.5*( U0mas+U0  - (dt/dx)*( F0Umas - F0U ) );
            utemppos1 = 0.5*( U1mas+U1  - (dt/dx)*( F1Umas - F1U ) );
            utemppos2 = 0.5*( U2mas+U2  - (dt/dx)*( F2Umas - F2U ) );
 
            utempneg0 = 0.5*( Utmenos0+U0 - (dt/dx)*( F0Umenos - F0U) );
            utempneg1 = 0.5*( Utmenos1+U1 - (dt/dx)*( F0Umenos - F1U) );
            utempneg2 = 0.5*( Utmenos2+U2 - (dt/dx)*( F0Umenos - F2U) );
            Fv(gamma,utemppos0, utemppos1, utemppos2, &Ftemppos0,&Ftemppos1,&Ftemppos2);
            Fv(gamma,utempneg0, utempneg1, utempneg2, &Ftempneg0,&Ftempneg1,&Ftempneg2);

           }
    
        unew0 = U0 - (dt/dx)*( Ftemppos0 - Ftempneg0 );
        unew1 = U1 - (dt/dx)*( Ftemppos1 - Ftempneg1 );
        unew2 = U2 - (dt/dx)*( Ftemppos2 - Ftempneg2 );
         *salida1 = unew0;
         *salida0 = unew1/unew0;
         *salida2 = (gamma-1.0)*( unew2 - ( unew0*(unew1/unew0)*(unew1/unew0) )/2.0);
       


  }
Example #9
0
/*!
  \brief When the user selects the OK button the new table is calculated
  packaged up, dumped to a file as well as being sent to the ECU to live 
  a long and happy life
  \param widget is the OK button the user clicked
  \param data is unused
  \returns TRUE on success, FALSE otherwise
  */
G_MODULE_EXPORT gboolean afr_calibrate_calc_and_dl(GtkWidget *widget, gpointer data)
{
	static gdouble diywbBv[] = { 0.00, 1.40, 1.45, 1.50, 1.55, 1.60, 
		1.65, 1.70, 1.75, 1.80, 1.85, 1.90, 1.95, 2.00, 2.05, 2.10,
		2.15, 2.20, 2.25, 2.30, 2.35, 2.40, 2.45, 2.50, 2.55, 2.60,
		2.65,  2.70,  2.75,  2.80,  2.85,  2.90,  4.00,  5.01 };
	static gdouble diywbBa[] = { 7.42, 10.08, 10.23, 10.38, 10.53, 10.69,
		10.86, 11.03, 11.20, 11.38, 11.57, 11.76, 11.96, 12.17, 12.38,
		12.60, 12.83, 13.07, 13.31, 13.57, 13.84, 14.11, 14.40, 14.70,
		15.25, 15.84, 16.48, 17.18, 17.93, 18.76, 19.66, 20.66, 40.00,
		60.00 };
	static gdouble lbwbBv[] = {0.00,  2.05,  4.21,  4.98,  5.01};
	static gdouble lbwbBa[] = {1.00, 11.00, 14.70, 16.00, 99.00};
	static gdouble teSVoutBv[] = { 1.024, 1.076, 1.126, 1.177, 1.227,
		1.278, 1.330, 1.380, 1.431, 1.481, 1.532, 1.581,
		1.626, 1.672, 1.717, 1.761, 1.802, 1.842, 1.883,
		1.926, 1.971, 2.015, 2.053, 2.104, 2.150, 2.192,
		2.231, 2.267, 2.305, 2.347, 2.398, 2.455, 2.514,
		2.556, 2.602, 2.650, 2.698, 2.748, 2.797, 2.846,
		2.900, 2.945, 2.991, 3.037, 3.083, 3.129, 3.175,
		3.221, 3.266, 3.313, 3.359, 3.404, 3.451, 3.496,
		3.542, 3.587, 3.634, 3.680, 3.725, 3.772, 3.817,
		3.863, 3.910, 3.955, 4.001 };
	static gdouble teSVoutBa[] = { 8.95, 9.11, 9.26, 9.41, 9.56, 9.71,
		9.87, 10.02, 10.17, 10.32, 10.47, 10.63, 10.78,
		10.93, 11.08, 11.24, 11.39, 11.54, 11.69, 11.86,
		12.04, 12.23, 12.39, 12.62, 12.83, 13.03, 13.21,
		13.4, 13.59, 13.82, 14.1, 14.43, 14.83, 15.31,
		15.85, 16.47, 17.15, 17.9, 18.7, 19.57, 20.5,
		21.5, 22.59, 23.78, 25.1, 26.54, 28.14, 29.9,
		31.87, 34.11, 36.81, 40.27, 45.1, 52.38, 63.92,
		82.66, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0, 99.0,
		99.0, 99.0};
	static gdouble aemLinBv[] = { 0.00, 0.16, 0.31, 0.47, 0.62, 0.78,
		0.94, 1.09, 1.25, 1.40, 1.56, 1.72, 1.87, 2.03, 2.18,
		2.34, 2.50, 2.65, 2.81, 2.96, 3.12, 3.27, 3.43, 3.59,
		3.74, 3.90, 4.05, 4.21, 4.37, 4.52, 4.68, 4.83, 4.99, 5.01 };
	static gdouble aemLinBa[] = { 9.72, 10.01, 10.35, 10.64, 10.98,
		11.27, 11.55, 11.90, 12.18, 12.47, 12.81, 13.10, 13.44,
		13.73, 14.01, 14.35, 14.64, 14.93, 15.27, 15.56, 15.84,
		16.18, 16.47, 16.81, 17.10, 17.39, 17.73, 18.01, 18.36,
		18.64, 18.93, 19.27, 19.56, 99.00 };
	static gdouble aemNonBv[] = { 0.00, 0.16, 0.31, 0.47, 0.62, 0.78,
		0.94, 1.09, 1.25, 1.40, 1.56, 1.72, 1.87, 2.03, 2.18,
		2.34, 2.50, 2.65, 2.81, 2.96, 3.12, 3.27, 3.43, 3.59,
		3.74, 3.90, 4.05, 4.21, 4.37, 4.52, 4.68, 4.83, 4.99,
		5.01 };
	static gdouble aemNonBa[] = { 8.41, 8.52, 8.64, 8.81, 8.98, 9.09,
		9.26, 9.44, 9.61, 9.78, 9.95, 10.12, 10.29, 10.47,
		10.69, 10.92, 11.15, 11.38, 11.67, 11.95, 12.24, 12.58,
		12.92, 13.27, 13.67, 14.13, 14.64, 15.21, 15.84, 16.53,
		17.27, 18.19, 19.44, 99.00 };
	static gdouble fjoBv[] = { 0.000, 0.811, 0.816, 1.256, 1.325,
		1.408, 1.447, 1.667, 1.784, 1.804, 1.872, 1.984, 2.023,
		2.126, 2.209, 2.268, 2.414, 2.454, 2.473, 2.502, 2.522,
		2.581, 2.610, 2.717, 2.766, 2.820, 2.908, 2.933, 2.977,
		3.021, 3.079, 3.099, 3.104, 5.000 };
	static gdouble fjoBa[] = { 0.000, 9.996, 10.011, 11.113, 11.290,
		11.481, 11.569, 12.142, 12.451, 12.510, 12.730, 13.024,
		13.142, 13.465, 13.715, 13.892, 14.377, 14.524, 14.597,
		14.759, 14.876, 15.273, 15.479, 16.302, 16.714, 17.170,
		18.008, 18.243, 18.684, 19.184, 19.801, 19.977, 20.007,
		29.400 };
	static gdouble zeitronixBv[] = { 0.000, 0.150, 0.310, 0.460, 0.620,
		0.780, 0.930, 1.090, 1.240, 1.400, 1.560, 1.710, 1.870,
		2.020, 2.180, 2.340, 2.500, 2.650, 2.800, 2.960, 3.000,
		3.120, 3.270, 5.010 };
	static gdouble zeitronixBa[] = { 0.000, 9.700, 9.900, 10.100,
		10.300, 10.500, 10.700, 11.000, 11.400, 11.700, 12.100,
		12.400, 12.800, 13.200, 13.700, 14.200, 14.700, 15.600,
		16.900, 18.500, 18.800, 19.900, 21.200, 99.000 };
	static gdouble genericBv[4] = { 0.0, 1.0,  4.0, 5.01 };
	static gdouble genericBa[4] = { 0.0, 9.7, 19.7, 99.0 };
	gdouble *Bv = NULL;
	gdouble *Ba = NULL;
	gdouble voltage = 0.0;
	gdouble deltaVoltage = 0.0;
	gdouble vPct = 0.0;
	gint nB = 0;
	gint iV = 0;
	gint adcCount = 0;
	gchar * filename = NULL;
	gdouble afr = 0.0;
	gdouble (*Fv)(gint adc) = NULL;
	gboolean NB = FALSE;
	guint8 table[nADC];
	time_t tim;
	FILE *f = NULL;
	Firmware_Details *firmware = NULL;
	extern gconstpointer *global_data;

	firmware = DATA_GET(global_data,"firmware");

#define USE_TABLE(prefix) \
	Bv = prefix ## Bv; \
	Ba = prefix ## Ba; \
	nB = (sizeof(prefix ## Bv) / sizeof(gdouble));


#define USE_FUNC(prefix) \
	Fv = prefix ## Fv

	switch (afr_enum)
	{
		case narrowBand:
			NB = TRUE;
			USE_FUNC(NB);
			break;
		case diyWB:
			USE_TABLE(diywb);
			break; 
		case dynojetLinear:
			USE_FUNC (djWBlin);
			break;
		case fjo:
			USE_TABLE(fjo);
			break;
		case aemLinear:
			USE_TABLE(aemLin);
			break;
		case aemNonLinear:
			USE_TABLE(aemNon);
			break;
		case twintec:
			USE_FUNC (inno05);
			break;
		case techEdgeLinear:
			USE_FUNC (teWBlin);
			break;
		case techEdgeNonLinear:
			USE_TABLE(teSVout);
			break;
		case innovate12:
			USE_FUNC (inno12);
			break;
		case innovate05:
			USE_FUNC (inno05);
			break;
		case innovateLC1:
			USE_FUNC (innoLC1);
			break;
		case lambdaBoy:
			USE_TABLE(lbwb);
			break;
		case zeitronix:
			USE_TABLE(zeitronix);
			break;
		case genericWB:
			genericBv[1] = g_ascii_strtod(gtk_entry_get_text(GTK_ENTRY(lookup_widget_f("voltage1_entry"))),NULL);
			genericBv[2] = g_ascii_strtod(gtk_entry_get_text(GTK_ENTRY(lookup_widget_f("voltage2_entry"))),NULL);
			genericBa[1] = g_ascii_strtod(gtk_entry_get_text(GTK_ENTRY(lookup_widget_f("afr1_entry"))),NULL);
			genericBa[2] = g_ascii_strtod(gtk_entry_get_text(GTK_ENTRY(lookup_widget_f("afr2_entry"))),NULL);
			USE_TABLE(generic);
			break;
		default:
			printf(_("default case, shouldn't have gotten here. afr_enum is %i"),afr_enum);
			break;
	}
	filename = g_build_filename(HOME(), "afrtable.log",NULL);
	f = fopen(filename, "w");
	g_free(filename);
	iV = 0;
	afr = 0.0;
	time(&tim);

	fprintf(f, "//------------------------------------------------------------------------------\n");
	fprintf(f, "//--  Generated by MegaTunix %s", ctime(&tim));
	fprintf(f, "//--  This file merely records what was sent to your MS-II, and may be        --\n");
	fprintf(f, "//--  deleted at any time.                                                    --\n");
	fprintf(f, "//--  Selected type: %-57s--\n", afr_name);
	fprintf(f, "//------------------------------------------------------------------------------\n");
	fprintf(f, "#ifndef GCC_BUILD\n");
	fprintf(f, "#pragma ROM_VAR EGO_ROM\n");
	fprintf(f, "#endif\n");
	fprintf(f, "const unsigned char egofactor_table[%d] EEPROM_ATTR = {\n", nADC);
	fprintf(f, "         //     afr  adcCount voltage\n");
	for (adcCount = 0; adcCount < nADC; adcCount++) 
	{
		voltage = adcCount / (nADC-1.0) * 5.0;
		if (NB) 
		{
			afr = 0.0;
			table[adcCount] = (adcCount > nADC/5.0) ? 0 : (gint16)(nADC/5.0 - adcCount);
		}
		else 
		{
			if (Fv)
				afr = Fv(adcCount);
			else 
			{
				/* Use curve data from tabular expression of transfer function.*/
				while (voltage > Bv[iV]) 
					iV++;
				deltaVoltage = Bv[iV] - Bv[iV-1];
				if (fabs(deltaVoltage) < 1e-10) /* Curve data is crap.*/
					afr = 999.0;
				else 
				{
					vPct = 1.0 - (Bv[iV] - voltage) / deltaVoltage;
					afr  = vPct * (Ba[iV] - Ba[iV-1]) + Ba[iV-1];
				}
			}
			table[adcCount] = (guint8)(afr*10.0+0.5);
		}

		fprintf(f, "   %4d%c // %7.3f   %4d   %6.3f\n", table[adcCount], (adcCount<nADC-1)?',':' ', afr, adcCount, voltage);
	}
	fprintf(f, "};\n");
	fprintf(f, "#ifndef GCC_BUILD\n");
	fprintf(f, "#pragma ROM_VAR DEFAULT\n");
	fprintf(f, "#endif\n");
	fprintf(f, "//------------------------------------------------------------------------------\n");
	fclose(f);

	ms_table_write(firmware->ego_table_page,
			firmware->page_params[firmware->ego_table_page]->length,
			(guint8 *)table);

	return TRUE;
}
// The matrix assembly function to be called at each time step to
// prepare for the linear solve.
void assemble_solid (EquationSystems& es,
                      const std::string& system_name)
{

//es.print_info();

#if LOG_ASSEMBLE_PERFORMANCE
  PerfLog perf_log("Assemble");
  perf_log.push("assemble stiffness");
#endif

    // Get a reference to the auxiliary system
  //TransientExplicitSystem& aux_system = es.get_system<TransientExplicitSystem>("Newton-update");

  // It is a good idea to make sure we are assembling
  // the proper system.
  libmesh_assert (system_name == "Newton-update");
  
  // Get a constant reference to the mesh object.
  const MeshBase& mesh = es.get_mesh();
  
  // The dimension that we are running
  const unsigned int dim = mesh.mesh_dimension();
  
  // Get a reference to the Stokes system object.
  TransientLinearImplicitSystem & newton_update =
   es.get_system<TransientLinearImplicitSystem> ("Newton-update");

  // New
   TransientLinearImplicitSystem & last_non_linear_soln =
    es.get_system<TransientLinearImplicitSystem> ("Last-non-linear-soln");

 TransientLinearImplicitSystem & fluid_system_vel =
    es.get_system<TransientLinearImplicitSystem> ("fluid-system-vel");

#if VELOCITY
TransientLinearImplicitSystem&  velocity = es.get_system<TransientLinearImplicitSystem>("velocity-system");
#endif

#if UN_MINUS_ONE
TransientLinearImplicitSystem & unm1 =
    es.get_system<TransientLinearImplicitSystem> ("unm1-system");
#endif
test(62);
const System & ref_sys = es.get_system("Reference-Configuration"); 
test(63);
  
  // Numeric ids corresponding to each variable in the system
  const unsigned int u_var = last_non_linear_soln .variable_number ("u");
  const unsigned int v_var = last_non_linear_soln .variable_number ("v");
  const unsigned int w_var = last_non_linear_soln .variable_number ("w");
#if INCOMPRESSIBLE
  const unsigned int p_var = last_non_linear_soln .variable_number ("p");
#endif 



#if FLUID_P_CONST
    const unsigned int m_var = fluid_system_vel.variable_number ("fluid_M");
  std::vector<unsigned int> dof_indices_m;
#endif


  // Get the Finite Element type for "u".  Note this will be
  // the same as the type for "v".
  FEType fe_vel_type = last_non_linear_soln.variable_type(u_var);


test(64);

#if INCOMPRESSIBLE
  // Get the Finite Element type for "p".
  FEType fe_pres_type = last_non_linear_soln .variable_type(p_var);
#endif 

  // Build a Finite Element object of the specified type for
  // the velocity variables.
  AutoPtr<FEBase> fe_vel  (FEBase::build(dim, fe_vel_type));
  
#if INCOMPRESSIBLE 
  // Build a Finite Element object of the specified type for
  // the pressure variables.
  AutoPtr<FEBase> fe_pres (FEBase::build(dim, fe_pres_type));
#endif 
  // A Gauss quadrature rule for numerical integration.
  // Let the \p FEType object decide what order rule is appropriate.
  QGauss qrule (dim, fe_vel_type.default_quadrature_order());

  // Tell the finite element objects to use our quadrature rule.
  fe_vel->attach_quadrature_rule (&qrule);
test(65);
//        AutoPtr<QBase> qrule2(fe_vel_type.default_quadrature_rule(dim));
// fe_vel->attach_quadrature_rule (qrule2.get());

#if INCOMPRESSIBLE 
  fe_pres->attach_quadrature_rule (&qrule);
#endif
  // The element Jacobian * quadrature weight at each integration point.   
  const std::vector<Real>& JxW = fe_vel->get_JxW();

  // The element shape functions evaluated at the quadrature points.
  const std::vector<std::vector<Real> >& phi = fe_vel->get_phi();

  // The element shape function gradients for the velocity
  // variables evaluated at the quadrature points.
  const std::vector<std::vector<RealGradient> >& dphi = fe_vel->get_dphi();
test(66);
#if INCOMPRESSIBLE 
  // The element shape functions for the pressure variable
  // evaluated at the quadrature points.
  const std::vector<std::vector<Real> >& psi = fe_pres->get_phi();
#endif
  
 const std::vector<Point>& coords = fe_vel->get_xyz();

  // A reference to the \p DofMap object for this system.  The \p DofMap
  // object handles the index translation from node and element numbers
  // to degree of freedom numbers.  We will talk more about the \p DofMap
  // in future examples.
  const DofMap & dof_map = last_non_linear_soln .get_dof_map();

#if FLUID_P_CONST 
  const DofMap & dof_map_fluid = fluid_system_vel .get_dof_map();
#endif

  // K will be the jacobian
  // F will be the Residual
  DenseMatrix<Number> Ke;
  DenseVector<Number> Fe;

  DenseSubMatrix<Number>
    Kuu(Ke), Kuv(Ke), Kuw(Ke),  
    Kvu(Ke), Kvv(Ke), Kvw(Ke),  
    Kwu(Ke), Kwv(Ke), Kww(Ke); 
    



#if INCOMPRESSIBLE
  DenseSubMatrix<Number>  Kup(Ke),Kvp(Ke),Kwp(Ke), Kpu(Ke), Kpv(Ke), Kpw(Ke), Kpp(Ke);
 #endif;
    
  DenseSubVector<Number>
    Fu(Fe), Fv(Fe), Fw(Fe);
#if INCOMPRESSIBLE
  DenseSubVector<Number>    Fp(Fe);
#endif
  // This vector will hold the degree of freedom indices for
  // the element.  These define where in the global system
  // the element degrees of freedom get mapped.
  std::vector<unsigned int> dof_indices;
  std::vector<unsigned int> dof_indices_u;
  std::vector<unsigned int> dof_indices_v;
  std::vector<unsigned int> dof_indices_w;
  
#if INCOMPRESSIBLE
  std::vector<unsigned int> dof_indices_p;
#endif
   

#if INERTIA
test(67);
  const unsigned int a_var = last_non_linear_soln.variable_number ("a");
  const unsigned int b_var = last_non_linear_soln.variable_number ("b");
  const unsigned int c_var = last_non_linear_soln.variable_number ("c");

//B block
  DenseSubMatrix<Number>
  Kua(Ke), Kub(Ke), Kuc(Ke),
  Kva(Ke), Kvb(Ke), Kvc(Ke),
  Kwa(Ke), Kwb(Ke), Kwc(Ke); 

//C block
  DenseSubMatrix<Number>
  Kau(Ke), Kav(Ke), Kaw(Ke),
  Kbu(Ke), Kbv(Ke), Kbw(Ke),
  Kcu(Ke), Kcv(Ke), Kcw(Ke);

//D block
  DenseSubMatrix<Number>
  Kaa(Ke), Kab(Ke), Kac(Ke),
  Kba(Ke), Kbb(Ke), Kbc(Ke),
  Kca(Ke), Kcb(Ke), Kcc(Ke);

  DenseSubVector<Number>
  Fa(Fe), Fb(Fe), Fc(Fe);

  std::vector<unsigned int> dof_indices_a;
  std::vector<unsigned int> dof_indices_b;
  std::vector<unsigned int> dof_indices_c;
test(68);
#endif

    DenseMatrix<Real> stiff;
  DenseVector<Real> res;
  VectorValue<Gradient> grad_u_mat;

  VectorValue<Gradient> grad_u_mat_old;
    const Real dt    = es.parameters.get<Real>("dt");
    const Real progress    = es.parameters.get<Real>("progress");


#if PORO 
  DenseVector<Real> p_stiff;
  DenseVector<Real> p_res;
  PoroelasticConfig material(dphi,psi);
#endif

  // Just calculate jacobian contribution when we need to
  material.calculate_linearized_stiffness = true;
  MeshBase::const_element_iterator       el     = mesh.active_local_elements_begin();
  const MeshBase::const_element_iterator end_el = mesh.active_local_elements_end(); 

  for ( ; el != end_el; ++el)
    {  
test(69);  
      const Elem* elem = *el;
      
      dof_map.dof_indices (elem, dof_indices);
      dof_map.dof_indices (elem, dof_indices_u, u_var);
      dof_map.dof_indices (elem, dof_indices_v, v_var);
      dof_map.dof_indices (elem, dof_indices_w, w_var);
#if INCOMPRESSIBLE
      dof_map.dof_indices (elem, dof_indices_p, p_var);
#endif
      const unsigned int n_dofs   = dof_indices.size();
      const unsigned int n_u_dofs = dof_indices_u.size(); 
      const unsigned int n_v_dofs = dof_indices_v.size(); 
      const unsigned int n_w_dofs = dof_indices_w.size(); 
#if INCOMPRESSIBLE
      const unsigned int n_p_dofs = dof_indices_p.size();
#endif

#if FLUID_P_CONST
      dof_map_fluid.dof_indices (elem, dof_indices_m, m_var);
#endif
      //elem->print_info();

      fe_vel->reinit  (elem);

#if INCOMPRESSIBLE
      fe_pres->reinit (elem);
#endif

      Ke.resize (n_dofs, n_dofs);
      Fe.resize (n_dofs);

      Kuu.reposition (u_var*n_u_dofs, u_var*n_u_dofs, n_u_dofs, n_u_dofs);
      Kuv.reposition (u_var*n_u_dofs, v_var*n_u_dofs, n_u_dofs, n_v_dofs);
      Kuw.reposition (u_var*n_u_dofs, w_var*n_u_dofs, n_u_dofs, n_w_dofs);
      #if INCOMPRESSIBLE
      Kup.reposition (u_var*n_u_dofs, p_var*n_u_dofs, n_u_dofs, n_p_dofs);
      #endif
      Kvu.reposition (v_var*n_v_dofs, u_var*n_v_dofs, n_v_dofs, n_u_dofs);
      Kvv.reposition (v_var*n_v_dofs, v_var*n_v_dofs, n_v_dofs, n_v_dofs);
      Kvw.reposition (v_var*n_v_dofs, w_var*n_v_dofs, n_v_dofs, n_w_dofs);
      #if INCOMPRESSIBLE
      Kvp.reposition (v_var*n_v_dofs, p_var*n_v_dofs, n_v_dofs, n_p_dofs);
      #endif
      
      Kwu.reposition (w_var*n_w_dofs, u_var*n_w_dofs, n_w_dofs, n_u_dofs);
      Kwv.reposition (w_var*n_w_dofs, v_var*n_w_dofs, n_w_dofs, n_v_dofs);
      Kww.reposition (w_var*n_w_dofs, w_var*n_w_dofs, n_w_dofs, n_w_dofs);
      #if INCOMPRESSIBLE
      Kwp.reposition (w_var*n_w_dofs, p_var*n_w_dofs, n_w_dofs, n_p_dofs);
      Kpu.reposition (p_var*n_u_dofs, u_var*n_u_dofs, n_p_dofs, n_u_dofs);
      Kpv.reposition (p_var*n_u_dofs, v_var*n_u_dofs, n_p_dofs, n_v_dofs);
      Kpw.reposition (p_var*n_u_dofs, w_var*n_u_dofs, n_p_dofs, n_w_dofs);
      Kpp.reposition (p_var*n_u_dofs, p_var*n_u_dofs, n_p_dofs, n_p_dofs);
      #endif



      
      Fu.reposition (u_var*n_u_dofs, n_u_dofs);
      Fv.reposition (v_var*n_u_dofs, n_v_dofs);
      Fw.reposition (w_var*n_u_dofs, n_w_dofs);
      #if INCOMPRESSIBLE
      Fp.reposition (p_var*n_u_dofs, n_p_dofs);
      #endif




#if INERTIA

//B block
   Kua.reposition (u_var*n_u_dofs, 3*n_u_dofs + n_p_dofs, n_u_dofs, n_u_dofs);
   Kub.reposition (u_var*n_u_dofs, 4*n_u_dofs + n_p_dofs, n_u_dofs, n_v_dofs);
   Kuc.reposition (u_var*n_u_dofs, 5*n_u_dofs + n_p_dofs, n_u_dofs, n_w_dofs);
   Kva.reposition (v_var*n_v_dofs, 3*n_u_dofs + n_p_dofs, n_v_dofs, n_u_dofs);
   Kvb.reposition (v_var*n_v_dofs, 4*n_u_dofs + n_p_dofs, n_v_dofs, n_v_dofs);
   Kvc.reposition (v_var*n_v_dofs, 5*n_u_dofs + n_p_dofs, n_v_dofs, n_w_dofs);
   Kwa.reposition (w_var*n_w_dofs, 3*n_u_dofs + n_p_dofs, n_w_dofs, n_u_dofs);
   Kwb.reposition (w_var*n_w_dofs, 4*n_u_dofs + n_p_dofs, n_w_dofs, n_v_dofs);
   Kwc.reposition (w_var*n_w_dofs, 5*n_u_dofs + n_p_dofs, n_w_dofs, n_w_dofs);

test(701);  
//C block
   Kau.reposition (3*n_u_dofs + n_p_dofs, u_var*n_u_dofs, n_u_dofs, n_u_dofs);
   Kav.reposition (3*n_u_dofs + n_p_dofs, v_var*n_u_dofs, n_u_dofs, n_v_dofs);
   Kaw.reposition (3*n_u_dofs + n_p_dofs, w_var*n_u_dofs, n_u_dofs, n_w_dofs);
   Kbu.reposition (4*n_u_dofs + n_p_dofs, u_var*n_v_dofs, n_v_dofs, n_u_dofs);
   Kbv.reposition (4*n_u_dofs + n_p_dofs, v_var*n_v_dofs, n_v_dofs, n_v_dofs);
   Kbw.reposition (4*n_u_dofs + n_p_dofs, w_var*n_v_dofs, n_v_dofs, n_w_dofs);
   Kcu.reposition (5*n_u_dofs + n_p_dofs, u_var*n_w_dofs, n_w_dofs, n_u_dofs);
   Kcv.reposition (5*n_u_dofs + n_p_dofs, v_var*n_w_dofs, n_w_dofs, n_v_dofs);
   Kcw.reposition (5*n_u_dofs + n_p_dofs, w_var*n_w_dofs, n_w_dofs, n_w_dofs);

//D block
   Kaa.reposition (3*n_u_dofs + n_p_dofs, 3*n_u_dofs + n_p_dofs, n_u_dofs, n_u_dofs);
   Kab.reposition (3*n_u_dofs + n_p_dofs, 4*n_u_dofs + n_p_dofs, n_u_dofs, n_v_dofs);
   Kac.reposition (3*n_u_dofs + n_p_dofs, 5*n_u_dofs + n_p_dofs, n_u_dofs, n_w_dofs);
   Kba.reposition (4*n_u_dofs + n_p_dofs, 3*n_u_dofs + n_p_dofs, n_v_dofs, n_u_dofs);
   Kbb.reposition (4*n_u_dofs + n_p_dofs, 4*n_u_dofs + n_p_dofs, n_v_dofs, n_v_dofs);
   Kbc.reposition (4*n_u_dofs + n_p_dofs, 5*n_u_dofs + n_p_dofs, n_v_dofs, n_w_dofs);
   Kca.reposition (5*n_u_dofs + n_p_dofs, 3*n_u_dofs + n_p_dofs, n_w_dofs, n_u_dofs);
   Kcb.reposition (5*n_u_dofs + n_p_dofs, 4*n_u_dofs + n_p_dofs, n_w_dofs, n_v_dofs);
   Kcc.reposition (5*n_u_dofs + n_p_dofs, 5*n_u_dofs + n_p_dofs, n_w_dofs, n_w_dofs);


Fa.reposition (3*n_u_dofs + n_p_dofs, n_u_dofs);
Fb.reposition (4*n_u_dofs + n_p_dofs, n_v_dofs);
Fc.reposition (5*n_u_dofs + n_p_dofs, n_w_dofs);

  dof_map.dof_indices (elem, dof_indices_a, a_var);
  dof_map.dof_indices (elem, dof_indices_b, b_var);
  dof_map.dof_indices (elem, dof_indices_c, c_var);

test(71);  
#endif


      System& aux_system = es.get_system<System>("Reference-Configuration");
      std::vector<unsigned int> undefo_index;
      std::vector<unsigned int> vel_index;           

      for (unsigned int qp=0; qp<qrule.n_points(); qp++)
        {



 Point rX;
 for (unsigned int l=0; l<n_u_dofs; l++)
            {
rX(0) += phi[l][qp]*ref_sys.current_local_solution->el(dof_indices_u[l]);
rX(1) += phi[l][qp]*ref_sys.current_local_solution->el(dof_indices_v[l]);
rX(2) += phi[l][qp]*ref_sys.current_local_solution->el(dof_indices_w[l]);
            }



#if INERTIA || DT
test(72);  
Real rho_s=15;

Point current_x;
 for (unsigned int l=0; l<n_u_dofs; l++)
 {
current_x(0) += phi[l][qp]*last_non_linear_soln.current_local_solution->el(dof_indices_u[l]);
current_x(1) += phi[l][qp]*last_non_linear_soln.current_local_solution->el(dof_indices_v[l]);
current_x(2) += phi[l][qp]*last_non_linear_soln.current_local_solution->el(dof_indices_w[l]);
}

Point old_x;
 for (unsigned int l=0; l<n_u_dofs; l++)
 {
old_x(0) += phi[l][qp]*last_non_linear_soln.old_local_solution->el(dof_indices_u[l]);
old_x(1) += phi[l][qp]*last_non_linear_soln.old_local_solution->el(dof_indices_v[l]);
old_x(2) += phi[l][qp]*last_non_linear_soln.old_local_solution->el(dof_indices_w[l]);
}
#if INERTIA
Point old_vel;
 for (unsigned int l=0; l<n_u_dofs; l++)
 {
old_vel(0) += phi[l][qp]*last_non_linear_soln.old_local_solution->el(dof_indices_a[l]);
old_vel(1) += phi[l][qp]*last_non_linear_soln.old_local_solution->el(dof_indices_b[l]);
old_vel(2) += phi[l][qp]*last_non_linear_soln.old_local_solution->el(dof_indices_c[l]);
}
Point current_vel;
 for (unsigned int l=0; l<n_u_dofs; l++)
 {
current_vel(0) += phi[l][qp]*last_non_linear_soln.current_local_solution->el(dof_indices_a[l]);
current_vel(1) += phi[l][qp]*last_non_linear_soln.current_local_solution->el(dof_indices_b[l]);
current_vel(2) += phi[l][qp]*last_non_linear_soln.current_local_solution->el(dof_indices_c[l]);
}
#endif

#if UN_MINUS_ONE
Point unm1_x;
 for (unsigned int l=0; l<n_u_dofs; l++)
 {
unm1_x(0) += phi[l][qp]*unm1.old_local_solution->el(dof_indices_u[l]);
unm1_x(1) += phi[l][qp]*unm1.old_local_solution->el(dof_indices_v[l]);
unm1_x(2) += phi[l][qp]*unm1.old_local_solution->el(dof_indices_w[l]);
}
#endif

Point value_acc;
Point value_acc_alt;

#if DT
for (unsigned int d = 0; d < dim; ++d) {
 value_acc_alt(d) = (rho_s)*( ((current_x(d)-rX(d))-(old_x(d)-rX(d)))-((old_x(d)-rX(d))- (unm1_x(d)-rX(d))) );  
value_acc(d) = (rho_s)*((current_x(d))-2*(old_x(d))+ (unm1_x(d)));  
value_acc(d) = (rho_s)*((current_x(d))-(old_x(d)));  
}
#endif

Point res_1;
Point res_2;
#if INERTIA
for (unsigned int d = 0; d < dim; ++d) {
res_1(d) = (rho_s)*((current_vel(d))-(old_vel(d)));
res_2(d) = current_x(d)-dt*current_vel(d)-old_x(d);    
}
/*
std::cout<<" current_vel "<<current_vel<<std::endl;
std::cout<<" res_1 "<<res_1<<std::endl;
std::cout<<" res_2 "<<res_2<<std::endl;
*/
#endif



test(73);  
#endif


Number   p_solid = 0.;

#if MOVING_MESH
	grad_u_mat(0) = grad_u_mat(1) = grad_u_mat(2) = 0;
    for (unsigned int d = 0; d < dim; ++d) {
      std::vector<Number> u_undefo;
//Fills the vector di with the global degree of freedom indices for the element. :dof_indicies
      aux_system.get_dof_map().dof_indices(elem, undefo_index,d);
      aux_system.current_local_solution->get(undefo_index, u_undefo);
      for (unsigned int l = 0; l != n_u_dofs; l++)
        grad_u_mat(d).add_scaled(dphi[l][qp], u_undefo[l]); 
 }
#endif


//#include "fixed_mesh_in_solid_assemble_code.txt"
          
      #if INCOMPRESSIBLE
      for (unsigned int l=0; l<n_p_dofs; l++)
            {
              p_solid += psi[l][qp]*last_non_linear_soln.current_local_solution->el(dof_indices_p[l]);
            }
      #endif
	  


#if INCOMPRESSIBLE 
Real m=0;
Real p_fluid=0;

#if FLUID_VEL 
for (unsigned int l=0; l<n_p_dofs; l++)
 {
   p_fluid += psi[l][qp]*fluid_system_vel.current_local_solution->el(dof_indices_p[l]);
 }

//As outlined in Chappel p=(p_curr-p_old)/2
 Real p_fluid_old=0;
for (unsigned int l=0; l<n_p_dofs; l++)
 {
   p_fluid_old += psi[l][qp]*fluid_system_vel.old_local_solution->el(dof_indices_p[l]);
 }
p_fluid=0.5*p_fluid+0.5*p_fluid_old;


Real m_old=0;

#if FLUID_P_CONST
for (unsigned int l=0; l<n_p_dofs; l++)
 {
   m += psi[l][qp]*fluid_system_vel.current_local_solution->el(dof_indices_m[l]);
 }


for (unsigned int l=0; l<n_p_dofs; l++)
 {
   m_old += psi[l][qp]*fluid_system_vel.old_local_solution->el(dof_indices_m[l]);
 }
#endif

material.init_for_qp(grad_u_mat, p_solid, qp, 1.0*m+0.0*m_old, p_fluid);

#endif
#endif //#if INCOMPRESSIBLE


#if INCOMPRESSIBLE && ! PORO
material.init_for_qp(grad_u_mat, p_solid, qp);
#endif 

          for (unsigned int i=0; i<n_u_dofs; i++)
            {
            res.resize(dim);
            material.get_residual(res, i);
            res.scale(JxW[qp]);
#if INERTIA
            res.scale(dt);
#endif

#if DT
            res.scale(dt);
#endif
//std::cout<< "res "<<res<<std::endl;

      	    Fu(i) += res(0);              
            Fv(i) += res(1) ; 
	    Fw(i) += res(2);  

  	#if GRAVITY
        Real grav=0.0;
        Fu(i) += progress*grav*JxW[qp]*phi[i][qp];
	#endif

#if INERTIA
      Fu(i) +=  JxW[qp]*phi[i][qp]*res_1(0); 
      Fv(i) +=  JxW[qp]*phi[i][qp]*res_1(1);     
      Fw(i) +=  JxW[qp]*phi[i][qp]*res_1(2); 

      Fa(i) +=  JxW[qp]*phi[i][qp]*res_2(0);  
      Fb(i) +=  JxW[qp]*phi[i][qp]*res_2(1);      
      Fc(i) +=  JxW[qp]*phi[i][qp]*res_2(2);  
#endif


// Matrix contributions for the uu and vv couplings.
for (unsigned int j=0; j<n_u_dofs; j++)
   {
    material.get_linearized_stiffness(stiff, i, j);
    stiff.scale(JxW[qp]);

#if DT
            res.scale(dt);
#endif

#if INERTIA 
    stiff.scale(dt);
    Kua(i,j)+=  rho_s*JxW[qp]*phi[i][qp]*phi[j][qp];      
    Kvb(i,j)+=  rho_s*JxW[qp]*phi[i][qp]*phi[j][qp];
    Kwc(i,j)+=  rho_s*JxW[qp]*phi[i][qp]*phi[j][qp];


    Kau(i,j)+=  JxW[qp]*phi[i][qp]*phi[j][qp];      
    Kbv(i,j)+=  JxW[qp]*phi[i][qp]*phi[j][qp];
    Kcw(i,j)+=  JxW[qp]*phi[i][qp]*phi[j][qp];

    Kaa(i,j)+=  -dt*JxW[qp]*phi[i][qp]*phi[j][qp];      
    Kbb(i,j)+=  -dt*JxW[qp]*phi[i][qp]*phi[j][qp];
    Kcc(i,j)+=  -dt*JxW[qp]*phi[i][qp]*phi[j][qp];
#endif




    Kuu(i,j)+=  stiff(u_var, u_var);
    Kuv(i,j)+=  stiff(u_var, v_var);
    Kuw(i,j)+=  stiff(u_var, w_var);	      
    Kvu(i,j)+=  stiff(v_var, u_var);
    Kvv(i,j)+=  stiff(v_var, v_var);
    Kvw(i,j)+=  stiff(v_var, w_var);
    Kwu(i,j)+=  stiff(w_var, u_var);
    Kwv(i,j)+=  stiff(w_var, v_var);
    Kww(i,j)+=  stiff(w_var, w_var); 


#if GRAVITY
    Kuu(i,j)+= 1*JxW[qp]*phi[i][qp]*phi[j][qp];
#endif
                }
            }


#if INCOMPRESSIBLE && FLUID_P_CONST
         for (unsigned int i = 0; i < n_p_dofs; i++) {
	  material.get_p_residual(p_res, i);
	  p_res.scale(JxW[qp]);
          Fp(i) += p_res(0);
	  }
    
    for (unsigned int i = 0; i < n_u_dofs; i++) {
          for (unsigned int j = 0; j < n_p_dofs; j++) {
	    material.get_linearized_uvw_p_stiffness(p_stiff, i, j);
	   p_stiff.scale(JxW[qp]);
            Kup(i, j) += p_stiff(0);
	    Kvp(i, j) += p_stiff(1);
            Kwp(i, j) += p_stiff(2);
	  }
    }
    
    for (unsigned int i = 0; i < n_p_dofs; i++) {
          for (unsigned int j = 0; j < n_u_dofs; j++) {
	    material.get_linearized_p_uvw_stiffness(p_stiff, i, j);
	    p_stiff.scale(JxW[qp]);
      Kpu(i, j) += p_stiff(0);
	    Kpv(i, j) += p_stiff(1);
      Kpw(i, j) += p_stiff(2);
       }
    }
#endif

#if CHAP && ! FLUID_P_CONST
           for (unsigned int i = 0; i < n_p_dofs; i++) {
         Fp(i) += 0*JxW[qp]*psi[i][qp];
    }
    
    for (unsigned int i = 0; i < n_p_dofs; i++) {
          for (unsigned int j = 0; j < n_p_dofs; j++) {
            Kpp(i, j) += 1*JxW[qp]*psi[i][qp]*psi[j][qp];
    }
    }
#endif



}//end of qp loop

      newton_update.matrix->add_matrix (Ke, dof_indices);
      newton_update.rhs->add_vector    (Fe, dof_indices);
} // end of element loop

     //   dof_map.constrain_element_matrix_and_vector (Ke, Fe, dof_indices);
     newton_update.rhs->close();
     newton_update.matrix->close();

#if LOG_ASSEMBLE_PERFORMANCE
perf_log.pop("assemble stiffness");
#endif 

#if LOG_ASSEMBLE_PERFORMANCE
perf_log.push("assemble bcs");
#endif

//Assemble the boundary conditions.
assemble_bcs(es);

#if LOG_ASSEMBLE_PERFORMANCE
perf_log.pop("assemble bcs");
#endif

std::ofstream lhs_out("lhsoutS3.dat");
Ke.print(lhs_out);
lhs_out.close();
  return;
}
void BoussinesqBuoyancyAdjointStabilization<Mu>::element_time_derivative( bool compute_jacobian,
        AssemblyContext& context,
        CachedValues& /*cache*/ )
{
#ifdef GRINS_USE_GRVY_TIMERS
    this->_timer->BeginTimer("BoussinesqBuoyancyAdjointStabilization::element_time_derivative");
#endif

    // The number of local degrees of freedom in each variable.
    const unsigned int n_u_dofs = context.get_dof_indices(_flow_vars.u_var()).size();
    const unsigned int n_T_dofs = context.get_dof_indices(_temp_vars.T_var()).size();

    // Element Jacobian * quadrature weights for interior integration.
    const std::vector<libMesh::Real> &JxW =
        context.get_element_fe(_flow_vars.u_var())->get_JxW();

    const std::vector<std::vector<libMesh::Real> >& T_phi =
        context.get_element_fe(this->_temp_vars.T_var())->get_phi();

    const std::vector<std::vector<libMesh::Real> >& u_phi =
        context.get_element_fe(this->_flow_vars.u_var())->get_phi();

    const std::vector<std::vector<libMesh::RealGradient> >& u_gradphi =
        context.get_element_fe(this->_flow_vars.u_var())->get_dphi();

    const std::vector<std::vector<libMesh::RealTensor> >& u_hessphi =
        context.get_element_fe(this->_flow_vars.u_var())->get_d2phi();

    // Get residuals and jacobians
    libMesh::DenseSubVector<libMesh::Number> &Fu = context.get_elem_residual(_flow_vars.u_var()); // R_{u}
    libMesh::DenseSubVector<libMesh::Number> &Fv = context.get_elem_residual(_flow_vars.v_var()); // R_{v}
    libMesh::DenseSubVector<libMesh::Number> *Fw = NULL;

    libMesh::DenseSubMatrix<libMesh::Number> &KuT =
        context.get_elem_jacobian(_flow_vars.u_var(), _temp_vars.T_var()); // J_{uT}
    libMesh::DenseSubMatrix<libMesh::Number> &KvT =
        context.get_elem_jacobian(_flow_vars.v_var(), _temp_vars.T_var()); // J_{vT}
    libMesh::DenseSubMatrix<libMesh::Number> &Kuu =
        context.get_elem_jacobian(_flow_vars.u_var(), _flow_vars.u_var()); // J_{uu}
    libMesh::DenseSubMatrix<libMesh::Number> &Kuv =
        context.get_elem_jacobian(_flow_vars.u_var(), _flow_vars.v_var()); // J_{uv}
    libMesh::DenseSubMatrix<libMesh::Number> &Kvu =
        context.get_elem_jacobian(_flow_vars.v_var(), _flow_vars.u_var()); // J_{vu}
    libMesh::DenseSubMatrix<libMesh::Number> &Kvv =
        context.get_elem_jacobian(_flow_vars.v_var(), _flow_vars.v_var()); // J_{vv}

    libMesh::DenseSubMatrix<libMesh::Number> *KwT = NULL;
    libMesh::DenseSubMatrix<libMesh::Number> *Kuw = NULL;
    libMesh::DenseSubMatrix<libMesh::Number> *Kvw = NULL;
    libMesh::DenseSubMatrix<libMesh::Number> *Kwu = NULL;
    libMesh::DenseSubMatrix<libMesh::Number> *Kwv = NULL;
    libMesh::DenseSubMatrix<libMesh::Number> *Kww = NULL;

    if(this->_dim == 3)
    {
        Fw = &context.get_elem_residual(this->_flow_vars.w_var()); // R_{w}
        KwT = &context.get_elem_jacobian
              (_flow_vars.w_var(), _temp_vars.T_var()); // J_{wT}
        Kuw = &context.get_elem_jacobian
              (_flow_vars.u_var(), _flow_vars.w_var()); // J_{uw}
        Kvw = &context.get_elem_jacobian
              (_flow_vars.v_var(), _flow_vars.w_var()); // J_{vw}
        Kwu = &context.get_elem_jacobian
              (_flow_vars.w_var(), _flow_vars.u_var()); // J_{wu}
        Kwv = &context.get_elem_jacobian
              (_flow_vars.w_var(), _flow_vars.v_var()); // J_{wv}
        Kww = &context.get_elem_jacobian
              (_flow_vars.w_var(), _flow_vars.w_var()); // J_{ww}
    }

    // Now we will build the element Jacobian and residual.
    // Constructing the residual requires the solution and its
    // gradient from the previous timestep.  This must be
    // calculated at each quadrature point by summing the
    // solution degree-of-freedom values by the appropriate
    // weight functions.
    unsigned int n_qpoints = context.get_element_qrule().n_points();

    libMesh::FEBase* fe = context.get_element_fe(this->_flow_vars.u_var());

    for (unsigned int qp=0; qp != n_qpoints; qp++)
    {
        libMesh::RealGradient g = this->_stab_helper.compute_g( fe, context, qp );
        libMesh::RealTensor G = this->_stab_helper.compute_G( fe, context, qp );

        libMesh::RealGradient U( context.interior_value( this->_flow_vars.u_var(), qp ),
                                 context.interior_value( this->_flow_vars.v_var(), qp ) );
        if( this->_dim == 3 )
        {
            U(2) = context.interior_value( this->_flow_vars.w_var(), qp );
        }

        // Compute the viscosity at this qp
        libMesh::Real mu_qp = this->_mu(context, qp);

        libMesh::Real tau_M;
        libMesh::Real d_tau_M_d_rho;
        libMesh::Gradient d_tau_M_dU;

        if (compute_jacobian)
            this->_stab_helper.compute_tau_momentum_and_derivs
            ( context, qp, g, G, this->_rho, U, mu_qp,
              tau_M, d_tau_M_d_rho, d_tau_M_dU,
              this->_is_steady );
        else
            tau_M = this->_stab_helper.compute_tau_momentum
                    ( context, qp, g, G, this->_rho, U, mu_qp,
                      this->_is_steady );

        // Compute the solution & its gradient at the old Newton iterate.
        libMesh::Number T;
        T = context.interior_value(_temp_vars.T_var(), qp);

        libMesh::RealGradient d_residual_dT = _rho_ref*_beta_T*_g;
        // d_residual_dU = 0
        libMesh::RealGradient residual = (T-_T_ref)*d_residual_dT;

        for (unsigned int i=0; i != n_u_dofs; i++)
        {
            libMesh::Real test_func = this->_rho*U*u_gradphi[i][qp] +
                                      mu_qp*( u_hessphi[i][qp](0,0) + u_hessphi[i][qp](1,1) + u_hessphi[i][qp](2,2) );
            Fu(i) += -tau_M*residual(0)*test_func*JxW[qp];

            Fv(i) += -tau_M*residual(1)*test_func*JxW[qp];

            if (_dim == 3)
            {
                (*Fw)(i) += -tau_M*residual(2)*test_func*JxW[qp];
            }

            if (compute_jacobian)
            {
                libMesh::Gradient d_test_func_dU = this->_rho*u_gradphi[i][qp];
                // d_test_func_dT = 0

                for (unsigned int j=0; j != n_u_dofs; ++j)
                {
                    Kuu(i,j) += -tau_M*residual(0)*d_test_func_dU(0)*u_phi[j][qp]*JxW[qp] * context.get_elem_solution_derivative();
                    Kuu(i,j) += -d_tau_M_dU(0)*u_phi[j][qp]*residual(0)*test_func*JxW[qp] * context.get_elem_solution_derivative();
                    Kuv(i,j) += -tau_M*residual(0)*d_test_func_dU(1)*u_phi[j][qp]*JxW[qp] * context.get_elem_solution_derivative();
                    Kuv(i,j) += -d_tau_M_dU(1)*u_phi[j][qp]*residual(0)*test_func*JxW[qp] * context.get_elem_solution_derivative();
                    Kvu(i,j) += -tau_M*residual(1)*d_test_func_dU(0)*u_phi[j][qp]*JxW[qp] * context.get_elem_solution_derivative();
                    Kvu(i,j) += -d_tau_M_dU(0)*u_phi[j][qp]*residual(1)*test_func*JxW[qp] * context.get_elem_solution_derivative();
                    Kvv(i,j) += -tau_M*residual(1)*d_test_func_dU(1)*u_phi[j][qp]*JxW[qp] * context.get_elem_solution_derivative();
                    Kvv(i,j) += -d_tau_M_dU(1)*u_phi[j][qp]*residual(1)*test_func*JxW[qp] * context.get_elem_solution_derivative();
                }

                for (unsigned int j=0; j != n_T_dofs; ++j)
                {
                    // KuT(i,j) += -tau_M*residual(0)*dtest_func_dT[j]*JxW[qp] * context.get_elem_solution_derivative();
                    KuT(i,j) += -tau_M*d_residual_dT(0)*T_phi[j][qp]*test_func*JxW[qp] * context.get_elem_solution_derivative();
                    // KvT(i,j) += -tau_M*residual(1)*dtest_func_dT[j]*JxW[qp] * context.get_elem_solution_derivative();
                    KvT(i,j) += -tau_M*d_residual_dT(1)*T_phi[j][qp]*test_func*JxW[qp] * context.get_elem_solution_derivative();
                }
                if (_dim == 3)
                {
                    for (unsigned int j=0; j != n_T_dofs; ++j)
                    {
                        // KwT(i,j) += -tau_M*residual(2)*dtest_func_dT[j]*JxW[qp] * context.get_elem_solution_derivative();
                        (*KwT)(i,j) += -tau_M*d_residual_dT(2)*T_phi[j][qp]*test_func*JxW[qp] * context.get_elem_solution_derivative();
                    }

                    for (unsigned int j=0; j != n_u_dofs; ++j)
                    {
                        (*Kuw)(i,j) += -tau_M*residual(0)*d_test_func_dU(2)*u_phi[j][qp]*JxW[qp] * context.get_elem_solution_derivative();
                        (*Kuw)(i,j) += -d_tau_M_dU(2)*u_phi[j][qp]*residual(0)*test_func*JxW[qp] * context.get_elem_solution_derivative();
                        (*Kvw)(i,j) += -tau_M*residual(1)*d_test_func_dU(2)*u_phi[j][qp]*JxW[qp] * context.get_elem_solution_derivative();
                        (*Kvw)(i,j) += -d_tau_M_dU(2)*u_phi[j][qp]*residual(1)*test_func*JxW[qp] * context.get_elem_solution_derivative();
                        (*Kwu)(i,j) += -tau_M*residual(2)*d_test_func_dU(0)*u_phi[j][qp]*JxW[qp] * context.get_elem_solution_derivative();
                        (*Kwu)(i,j) += -d_tau_M_dU(0)*u_phi[j][qp]*residual(2)*test_func*JxW[qp] * context.get_elem_solution_derivative();
                        (*Kwv)(i,j) += -tau_M*residual(2)*d_test_func_dU(1)*u_phi[j][qp]*JxW[qp] * context.get_elem_solution_derivative();
                        (*Kwv)(i,j) += -d_tau_M_dU(1)*u_phi[j][qp]*residual(2)*test_func*JxW[qp] * context.get_elem_solution_derivative();
                        (*Kww)(i,j) += -tau_M*residual(2)*d_test_func_dU(2)*u_phi[j][qp]*JxW[qp] * context.get_elem_solution_derivative();
                        (*Kww)(i,j) += -d_tau_M_dU(2)*u_phi[j][qp]*residual(2)*test_func*JxW[qp] * context.get_elem_solution_derivative();
                    }
                }

            } // End compute_jacobian check

        } // End i dof loop
    } // End quadrature loop

#ifdef GRINS_USE_GRVY_TIMERS
    this->_timer->EndTimer("BoussinesqBuoyancyAdjointStabilization::element_time_derivative");
#endif

    return;
}
void LowMachNavierStokesSPGSMStabilization<Mu,SH,TC>::assemble_momentum_mass_residual( bool /*compute_jacobian*/,
        AssemblyContext& context )
{
    // The number of local degrees of freedom in each variable.
    const unsigned int n_u_dofs = context.get_dof_indices(this->_flow_vars.u()).size();

    // Check number of dofs is same for _flow_vars.u(), v_var and w_var.
    libmesh_assert (n_u_dofs == context.get_dof_indices(this->_flow_vars.v()).size());
    if (this->mesh_dim(context) == 3)
        libmesh_assert (n_u_dofs == context.get_dof_indices(this->_flow_vars.w()).size());

    // Element Jacobian * quadrature weights for interior integration.
    const std::vector<libMesh::Real> &JxW =
        context.get_element_fe(this->_flow_vars.u())->get_JxW();

    // The velocity shape function gradients at interior quadrature points.
    const std::vector<std::vector<libMesh::RealGradient> >& u_gradphi =
        context.get_element_fe(this->_flow_vars.u())->get_dphi();

    libMesh::DenseSubVector<libMesh::Number> &Fu = context.get_elem_residual(this->_flow_vars.u()); // R_{u}
    libMesh::DenseSubVector<libMesh::Number> &Fv = context.get_elem_residual(this->_flow_vars.v()); // R_{v}
    libMesh::DenseSubVector<libMesh::Real>* Fw = NULL;

    if( this->mesh_dim(context) == 3 )
    {
        Fw  = &context.get_elem_residual(this->_flow_vars.w()); // R_{w}
    }

    unsigned int n_qpoints = context.get_element_qrule().n_points();
    for (unsigned int qp=0; qp != n_qpoints; qp++)
    {
        libMesh::Real T = context.fixed_interior_value( this->_temp_vars.T(), qp );
        libMesh::Real rho = this->rho( T, this->get_p0_transient( context, qp ) );

        libMesh::Real mu = this->_mu(T);

        libMesh::RealGradient U( context.fixed_interior_value(this->_flow_vars.u(), qp),
                                 context.fixed_interior_value(this->_flow_vars.v(), qp) );

        libMesh::RealGradient grad_u = context.fixed_interior_gradient(this->_flow_vars.u(), qp);
        libMesh::RealGradient grad_v = context.fixed_interior_gradient(this->_flow_vars.v(), qp);
        libMesh::RealGradient grad_w;

        if( this->mesh_dim(context) == 3 )
        {
            U(2) = context.fixed_interior_value(this->_flow_vars.w(), qp);
            grad_w = context.fixed_interior_gradient(this->_flow_vars.w(), qp);
        }

        libMesh::FEBase* fe = context.get_element_fe(this->_flow_vars.u());

        libMesh::RealGradient g = this->_stab_helper.compute_g( fe, context, qp );
        libMesh::RealTensor G = this->_stab_helper.compute_G( fe, context, qp );

        libMesh::Real tau_M = this->_stab_helper.compute_tau_momentum( context, qp, g, G, rho, U, mu, false );
        libMesh::Real tau_C = this->_stab_helper.compute_tau_continuity( tau_M, g );

        libMesh::Real RC_t = this->compute_res_continuity_transient( context, qp );
        libMesh::RealGradient RM_s = this->compute_res_momentum_steady( context, qp );
        libMesh::RealGradient RM_t = this->compute_res_momentum_transient( context, qp );

        for (unsigned int i=0; i != n_u_dofs; i++)
        {
            Fu(i) -= ( tau_C*RC_t*u_gradphi[i][qp](0)
                       + tau_M*RM_t(0)*rho*U*u_gradphi[i][qp] )*JxW[qp];

            Fv(i) -= ( tau_C*RC_t*u_gradphi[i][qp](1)
                       + tau_M*RM_t(1)*rho*U*u_gradphi[i][qp] )*JxW[qp];

            if( this->mesh_dim(context) == 3 )
            {
                (*Fw)(i) -= ( tau_C*RC_t*u_gradphi[i][qp](2)
                              + tau_M*RM_t(2)*rho*U*u_gradphi[i][qp] )*JxW[qp];
            }
        }

    }
    return;
}
Example #13
0
  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;
  }