예제 #1
0
  void CanteraTransport::D( const CachedValues& cache, unsigned int qp,
			    std::vector<libMesh::Real>& D ) const
  {
    const libMesh::Real T = cache.get_cached_values(Cache::TEMPERATURE)[qp];
    const libMesh::Real P = cache.get_cached_values(Cache::THERMO_PRESSURE)[qp];
    const std::vector<libMesh::Real>& Y = cache.get_cached_vector_values(Cache::MASS_FRACTIONS)[qp];

    libmesh_assert_equal_to( Y.size(), D.size() );
    libmesh_assert_equal_to( Y.size(), _cantera_gas.nSpecies() );

    {
      libMesh::Threads::spin_mutex::scoped_lock lock(cantera_mutex);
    
      /*! \todo Need to make sure this will work in a threaded environment.
	Not sure if we will get thread lock here or not. */
      try
	{
	  _cantera_gas.setState_TPY(T, P, &Y[0]);
	  _cantera_transport.getMixDiffCoeffsMass(&D[0]);
	}
      catch(Cantera::CanteraError)
	{
	  Cantera::showErrors(std::cerr);
	  libmesh_error();
	}

    }

    return;
  }
예제 #2
0
  libMesh::Real CanteraThermodynamics::cv( const CachedValues& cache, unsigned int qp ) const
  {
    const libMesh::Real T = cache.get_cached_values(Cache::TEMPERATURE)[qp];
    const libMesh::Real P = cache.get_cached_values(Cache::THERMO_PRESSURE)[qp];
    const std::vector<libMesh::Real>& Y = cache.get_cached_vector_values(Cache::MASS_FRACTIONS)[qp];
    
    libmesh_assert_equal_to( Y.size(), _cantera_gas.nSpecies() );

    libMesh::Real cv = 0.0;

    {
      /*! \todo Need to make sure this will work in a threaded environment.
	Not sure if we will get thread lock here or not. */
      libMesh::Threads::spin_mutex::scoped_lock lock(cantera_mutex);

      try
	{
	  _cantera_gas.setState_TPY( T, P, &Y[0] );
	  
	  cv = _cantera_gas.cv_mass();
	}
      catch(Cantera::CanteraError)
	{
	  Cantera::showErrors(std::cerr);
	  libmesh_error();
	}

    }

    return cv;
  }
  libMesh::Real AntiochWilkeTransportEvaluator<Th,V,C,D>::k( const CachedValues& cache, unsigned int qp )
  {
    const libMesh::Real T = cache.get_cached_values(Cache::TEMPERATURE)[qp];
    const std::vector<libMesh::Real>& Y = cache.get_cached_vector_values(Cache::MASS_FRACTIONS)[qp];

    return this->k( T, Y );
  }
  void AntiochWilkeTransportEvaluator<Th,V,C,D>::mu_and_k( const CachedValues& cache, unsigned int qp,
                                                           libMesh::Real& mu, libMesh::Real& k ) 
  {
    const libMesh::Real T = cache.get_cached_values(Cache::TEMPERATURE)[qp];
    const std::vector<libMesh::Real>& Y = cache.get_cached_vector_values(Cache::MASS_FRACTIONS)[qp];

    _wilke_evaluator->mu_and_k( T, Y, mu, k );
    return;
  }
예제 #5
0
  void LowMachNavierStokes<Mu,SH,TC>::assemble_energy_time_deriv( bool /*compute_jacobian*/,
								  AssemblyContext& context,
								  CachedValues& cache )
  {
    // The number of local degrees of freedom in each variable.
    const unsigned int n_T_dofs = context.get_dof_indices(this->_T_var).size();

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

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

    // The temperature shape functions gradients at interior quadrature points.
    const std::vector<std::vector<libMesh::RealGradient> >& T_gradphi =
      context.get_element_fe(this->_T_var)->get_dphi();

    libMesh::DenseSubVector<libMesh::Number> &FT = context.get_elem_residual(this->_T_var); // R_{T}

    unsigned int n_qpoints = context.get_element_qrule().n_points();
    for (unsigned int qp=0; qp != n_qpoints; qp++)
      {
	libMesh::Number u, v, T, p0;
	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];
	p0 = cache.get_cached_values(Cache::THERMO_PRESSURE)[qp];

	libMesh::Gradient grad_T = cache.get_cached_gradient_values(Cache::TEMPERATURE_GRAD)[qp];

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

	libMesh::Number k = this->_k(T);
	libMesh::Number cp = this->_cp(T);

	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_T_dofs; i++)
	  {
	    FT(i) += ( -rho*cp*U*grad_T*T_phi[i][qp] // convection term
		       - k*grad_T*T_gradphi[i][qp]            // diffusion term
		       )*JxW[qp]; 
	  }
      }

    return;
  }
  void AntiochWilkeTransportEvaluator<Th,V,C,D>::D( const CachedValues& cache, unsigned int qp,
                                                    std::vector<libMesh::Real>& D )
  {
    const libMesh::Real rho = cache.get_cached_values(Cache::MIXTURE_DENSITY)[qp];
    
    /*! \todo Find a way to cache these so we don't have to recompute them */
    const libMesh::Real cp = this->cp(cache,qp);
    const libMesh::Real k = this->k(cache,qp);

    this->D(rho,cp,k,D);
    
    return;
  }
예제 #7
0
  void LowMachNavierStokes<Mu,SH,TC>::compute_element_cache( const AssemblyContext& context, 
							     const std::vector<libMesh::Point>& points,
							     CachedValues& cache )
  {
    if( cache.is_active(Cache::PERFECT_GAS_DENSITY) )
      {
	std::vector<libMesh::Real> rho_values;
	rho_values.reserve( points.size() );
	
	for( std::vector<libMesh::Point>::const_iterator point = points.begin();
	     point != points.end(); point++ )
	  {
	    libMesh::Real T = this->T(*point,context);
	    libMesh::Real p0 = this->get_p0_steady(context,*point);

	    rho_values.push_back(this->rho( T, p0 ) );
	  }

	cache.set_values( Cache::PERFECT_GAS_DENSITY, rho_values );
      }

    return;
  }
예제 #8
0
  void CanteraThermodynamics::h( const CachedValues& cache, unsigned int qp,
				 std::vector<libMesh::Real>& h) const
  {
    const libMesh::Real T = cache.get_cached_values(Cache::TEMPERATURE)[qp];
    const libMesh::Real P = cache.get_cached_values(Cache::THERMO_PRESSURE)[qp];
    const std::vector<libMesh::Real>& Y = cache.get_cached_vector_values(Cache::MASS_FRACTIONS)[qp];

    libmesh_assert_equal_to( Y.size(), h.size() );
    libmesh_assert_equal_to( Y.size(), _cantera_gas.nSpecies() );

    {
      /*! \todo Need to make sure this will work in a threaded environment.
	Not sure if we will get thread lock here or not. */
      libMesh::Threads::spin_mutex::scoped_lock lock(cantera_mutex);
    
      try
	{
	  _cantera_gas.setState_TPY( T, P, &Y[0] );
	  
	  _cantera_gas.getEnthalpy_RT( &h[0] );
	}
      catch(Cantera::CanteraError)
	{
	  Cantera::showErrors(std::cerr);
	  libmesh_error();
	}

    for( unsigned int s = 0; s < h.size(); s++ )
      {
	h[s] *= _cantera_mixture.R(s)*T;
      }

    }

    return;
  }
예제 #9
0
  void LowMachNavierStokes<Mu,SH,TC>::assemble_mass_time_deriv( bool /*compute_jacobian*/, 
								AssemblyContext& context,
								CachedValues& cache )
  {
    // The number of local degrees of freedom in each variable.
    const unsigned int n_p_dofs = context.get_dof_indices(this->_p_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> >& p_phi =
      context.get_element_fe(this->_p_var)->get_phi();

    libMesh::DenseSubVector<libMesh::Number> &Fp = context.get_elem_residual(this->_p_var); // R_{p}

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

    for (unsigned int qp=0; qp != n_qpoints; qp++)
      {
	libMesh::Number u, v, 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];

	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_T = cache.get_cached_gradient_values(Cache::TEMPERATURE_GRAD)[qp];

	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)
          {
	    libMesh::Gradient grad_w = cache.get_cached_gradient_values(Cache::Z_VELOCITY_GRAD)[qp];
	    divU += grad_w(2);
          }

	// Now a loop over the pressure degrees of freedom.  This
	// computes the contributions of the continuity equation.
	for (unsigned int i=0; i != n_p_dofs; i++)
	  {
	    Fp(i) += (-U*grad_T/T + divU)*p_phi[i][qp]*JxW[qp];
	  }
      }

    return;
  }
  void GasRecombinationCatalyticWall<Chemistry>::apply_fluxes( AssemblyContext& context,
                                                               const CachedValues& cache,
                                                               const bool request_jacobian )
  {
    libmesh_do_once(libmesh_deprecated());

    libMesh::FEGenericBase<libMesh::Real>* side_fe = NULL;
    context.get_side_fe( _reactant_var_idx, side_fe );

    // The number of local degrees of freedom in each variable.
    const unsigned int n_var_dofs = context.get_dof_indices(_reactant_var_idx).size();

    libmesh_assert_equal_to( n_var_dofs, context.get_dof_indices(_product_var_idx).size() );

    // Element Jacobian * quadrature weight for side integration.
    const std::vector<libMesh::Real> &JxW_side = side_fe->get_JxW();

    // The var shape functions at side quadrature points.
    const std::vector<std::vector<libMesh::Real> >& var_phi_side = side_fe->get_phi();

    // Physical location of the quadrature points
    const std::vector<libMesh::Point>& var_qpoint = side_fe->get_xyz();

    // reactant residual
    libMesh::DenseSubVector<libMesh::Number> &F_r_var = context.get_elem_residual(_reactant_var_idx);

    // product residual
    libMesh::DenseSubVector<libMesh::Number> &F_p_var = context.get_elem_residual(_product_var_idx);

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

    for (unsigned int qp=0; qp != n_qpoints; qp++)
      {
        libMesh::Real jac = JxW_side[qp];

        if(Physics::is_axisymmetric())
          {
            const libMesh::Number r = var_qpoint[qp](0);
            jac *= r;
          }

        const libMesh::Real rho = cache.get_cached_values(Cache::MIXTURE_DENSITY)[qp];

        const libMesh::Real Y_r = cache.get_cached_vector_values(Cache::MASS_FRACTIONS)[qp][this->_reactant_species_idx];

        const libMesh::Real T = cache.get_cached_values(Cache::TEMPERATURE)[qp];

        const libMesh::Real r_value = this->compute_reactant_mass_flux(rho, Y_r, T);

        const libMesh::Real p_value = -r_value;

        for (unsigned int i=0; i != n_var_dofs; i++)
          {
            F_r_var(i) += r_value*var_phi_side[i][qp]*jac;

            F_p_var(i) += p_value*var_phi_side[i][qp]*jac;

            if( request_jacobian )
              {
                libmesh_not_implemented();
              }
          }
      }
  }
예제 #11
0
  void LowMachNavierStokes<Mu,SH,TC>::compute_element_time_derivative_cache( const AssemblyContext& context, 
									     CachedValues& cache )
  {
    const unsigned int n_qpoints = context.get_element_qrule().n_points();

    std::vector<libMesh::Real> u, v, w, T, p, p0;
    u.resize(n_qpoints);
    v.resize(n_qpoints);
    if( this->_dim > 2 )
      w.resize(n_qpoints);
    
    T.resize(n_qpoints);
    p.resize(n_qpoints);
    p0.resize(n_qpoints);

    std::vector<libMesh::Gradient> grad_u, grad_v, grad_w, grad_T;
    grad_u.resize(n_qpoints);
    grad_v.resize(n_qpoints);
    if( this->_dim > 2 )
      grad_w.resize(n_qpoints);
    
    grad_T.resize(n_qpoints);

    for (unsigned int qp = 0; qp != n_qpoints; ++qp)
      {
	u[qp] = context.interior_value(this->_u_var, qp);
	v[qp] = context.interior_value(this->_v_var, qp);

	grad_u[qp] = context.interior_gradient(this->_u_var, qp);
	grad_v[qp] = context.interior_gradient(this->_v_var, qp);
	if( this->_dim > 2 )
	  {
	    w[qp] = context.interior_value(this->_w_var, qp);
	    grad_w[qp] = context.interior_gradient(this->_w_var, qp);
	  }
	T[qp] = context.interior_value(this->_T_var, qp);
	grad_T[qp] = context.interior_gradient(this->_T_var, qp);

	p[qp] = context.interior_value(this->_p_var, qp);
	p0[qp] = this->get_p0_steady(context, qp);
      }
    
    cache.set_values(Cache::X_VELOCITY, u);
    cache.set_values(Cache::Y_VELOCITY, v);
    
    cache.set_gradient_values(Cache::X_VELOCITY_GRAD, grad_u);
    cache.set_gradient_values(Cache::Y_VELOCITY_GRAD, grad_v);
    
    if(this->_dim > 2)
      {
	cache.set_values(Cache::Z_VELOCITY, w);
	cache.set_gradient_values(Cache::Z_VELOCITY_GRAD, grad_w);
      }

    cache.set_values(Cache::TEMPERATURE, T);
    cache.set_gradient_values(Cache::TEMPERATURE_GRAD, grad_T);

    cache.set_values(Cache::PRESSURE, p);
    cache.set_values(Cache::THERMO_PRESSURE, p0);

    return;
  }
예제 #12
0
  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;
  }