bool
MAST::HeatConductionElementBase::
surface_convection_residual(bool request_jacobian,
                            RealVectorX& f,
                            RealMatrixX& jac,
                            const unsigned int s,
                            MAST::BoundaryConditionBase& p) {
    
    // prepare the side finite element
    std::auto_ptr<libMesh::FEBase> fe;
    std::auto_ptr<libMesh::QBase> qrule;
    _get_side_fe_and_qrule(get_elem_for_quadrature(), s, fe, qrule);

    // get the function from this boundary condition
    const MAST::FieldFunction<Real>
    &coeff = p.get<MAST::FieldFunction<Real> >("convection_coeff"),
    &T_amb = p.get<MAST::FieldFunction<Real> >("ambient_temperature");
    
    const std::vector<Real> &JxW               = fe->get_JxW();
    const std::vector<libMesh::Point>& qpoint  = fe->get_xyz();
    const std::vector<std::vector<Real> >& phi = fe->get_phi();
    const unsigned int n_phi                   = (unsigned int)phi.size();
    
    
    RealVectorX  phi_vec  = RealVectorX::Zero(n_phi);
    RealMatrixX  mat      = RealMatrixX::Zero(n_phi, n_phi);
    Real temp, amb_temp, h_coeff;
    libMesh::Point pt;
    MAST::FEMOperatorMatrix Bmat;
    
    
    for (unsigned int qp=0; qp<qpoint.size(); qp++) {
        
        _local_elem->global_coordinates_location (qpoint[qp], pt);
        
        // now set the shape function values
        for ( unsigned int i_nd=0; i_nd<n_phi; i_nd++ )
            phi_vec(i_nd) = phi[i_nd][qp];
        
        // value of flux
        coeff(pt, _time, h_coeff);
        T_amb(pt, _time, amb_temp);
        temp  = phi_vec.dot(_sol);
        
        // normal flux is given as:
        // qi_ni = h_coeff * (T - T_amb)
        //
        f   += JxW[qp] * phi_vec * h_coeff * (temp - amb_temp);
        
        if (request_jacobian) {
            
            Bmat.reinit(1, phi_vec);
            Bmat.right_multiply_transpose(mat, Bmat);
            jac += JxW[qp] * mat * h_coeff;
        }
    }
    
    return request_jacobian;
}
bool
MAST::HeatConductionElementBase::
surface_flux_residual(bool request_jacobian,
                      RealVectorX& f,
                      RealMatrixX& jac,
                      const unsigned int s,
                      MAST::BoundaryConditionBase& p) {
    
    // prepare the side finite element
    std::auto_ptr<libMesh::FEBase> fe;
    std::auto_ptr<libMesh::QBase> qrule;
    _get_side_fe_and_qrule(get_elem_for_quadrature(), s, fe, qrule);
    
    
    // get the function from this boundary condition
    const MAST::FieldFunction<Real>& func =
    p.get<MAST::FieldFunction<Real> >("heat_flux");
    
    
    const std::vector<Real> &JxW                 = fe->get_JxW();
    const std::vector<libMesh::Point>& qpoint    = fe->get_xyz();
    const std::vector<std::vector<Real> >& phi   = fe->get_phi();
    const unsigned int n_phi                     = (unsigned int)phi.size();
    
    RealVectorX phi_vec  = RealVectorX::Zero(n_phi);
    libMesh::Point pt;
    Real  flux;
    
    for (unsigned int qp=0; qp<qpoint.size(); qp++) {
        
        _local_elem->global_coordinates_location (qpoint[qp], pt);
        
        // now set the shape function values
        for ( unsigned int i_nd=0; i_nd<n_phi; i_nd++ )
            phi_vec(i_nd) = phi[i_nd][qp];
        
        // get the value of flux = q_i . n_i
        func(pt, _time, flux);
        
        f   +=  JxW[qp] * phi_vec * flux;
    }
    
    // calculation of the load vector is independent of solution
    return false;
}
bool
MAST::StructuralElementBase::small_disturbance_surface_pressure_force(bool request_jacobian,
                                                                      DenseRealVector &f,
                                                                      DenseRealMatrix &jac,
                                                                      const unsigned int side,
                                                                      MAST::BoundaryCondition &p) {
    libmesh_assert(!follower_forces); // not implemented yet for follower forces
    libmesh_assert_equal_to(p.type(), MAST::SMALL_DISTURBANCE_MOTION);
    
    MAST::SmallDisturbanceMotion& sd_motion = dynamic_cast<MAST::SmallDisturbanceMotion&>(p);
    MAST::SurfaceMotionBase& surf_motion = sd_motion.get_deformation();
    MAST::SmallDisturbanceSurfacePressure& surf_press = sd_motion.get_pressure();
    
    FEMOperatorMatrix Bmat;
    
    // get the function from this boundary condition
    std::auto_ptr<libMesh::FEBase> fe;
    std::auto_ptr<libMesh::QBase> qrule;
    _get_side_fe_and_qrule(this->local_elem().local_elem(), side, fe, qrule);
    
    const std::vector<Real> &JxW = fe->get_JxW();
    
    // Physical location of the quadrature points
    const std::vector<libMesh::Point>& qpoint = fe->get_xyz();
    const std::vector<std::vector<Real> >& phi = fe->get_phi();
    const unsigned int n_phi = (unsigned int)phi.size();
    const unsigned int n1=3, n2=6*n_phi;
    
    // boundary normals
    const std::vector<libMesh::Point>& face_normals = fe->get_normals();
    
    Real press;
    ValType dpress;
    DenseRealVector phi_vec;
    libMesh::DenseVector<ValType> wtrans, utrans, dn_rot, force, local_f, vec_n2;
    wtrans.resize(3); utrans.resize(3); dn_rot.resize(3);
    phi_vec.resize(n_phi); force.resize(2*n1); local_f.resize(n2);
    vec_n2.resize(n2);
    
    libMesh::Point pt;
    
    for (unsigned int qp=0; qp<qpoint.size(); qp++)
    {
        this->global_coordinates(qpoint[qp], pt);
        
        // now set the shape function values
        for ( unsigned int i_nd=0; i_nd<n_phi; i_nd++ )
            phi_vec(i_nd) = phi[i_nd][qp];
        
        Bmat.reinit(2*n1, phi_vec);

        // get pressure and deformation information
        surf_press.surface_pressure<ValType>(_system.time, pt, press, dpress);
        surf_motion.surface_velocity(_system.time, pt, face_normals[qp],
                                     wtrans, utrans, dn_rot);
        
        //            press = 0.;
        //            dpress = Complex(2./4.*std::real(dn_rot(0)),  2./4./.1*std::imag(utrans(1)));
        //            libMesh::out << q_point[qp](0)
        //            << "  " << std::real(utrans(1))
        //            << "  " << std::imag(utrans(1))
        //            << "  " << std::real(dn_rot(0))
        //            << "  " << std::imag(dn_rot(0))
        //            << "  " << std::real(press)
        //            << "  " << std::imag(press)
        //            << "  " << std::real(dpress)
        //            << "  " << std::imag(dpress) << std::endl;

        // calculate force
        for (unsigned int i_dim=0; i_dim<n1; i_dim++)
            force(i_dim) =  ( press * dn_rot(i_dim) + // steady pressure
                             dpress * face_normals[qp](i_dim)); // unsteady pressure

        
        Bmat.vector_mult_transpose(vec_n2, force);
        
        local_f.add(JxW[qp], vec_n2);
    }
    
    // now transform to the global system and add
    if (_elem.dim() < 3) {
        transform_to_global_system(local_f, vec_n2);
        MAST::add_to_assembled_vector(f, vec_n2);
    }
    else
        MAST::add_to_assembled_vector(f, local_f);
    

    return (request_jacobian && follower_forces);
}
bool
MAST::StructuralElementBase::surface_pressure_force(bool request_jacobian,
                                                    DenseRealVector &f,
                                                    DenseRealMatrix &jac,
                                                    const unsigned int side,
                                                    MAST::BoundaryCondition &p) {

    libmesh_assert(!follower_forces); // not implemented yet for follower forces
    
    FEMOperatorMatrix Bmat;
    
    // get the function from this boundary condition
    MAST::FieldFunction<Real>& func =
    dynamic_cast<MAST::FieldFunction<Real>&>(p.function());
    std::auto_ptr<libMesh::FEBase> fe;
    std::auto_ptr<libMesh::QBase> qrule;
    _get_side_fe_and_qrule(this->get_elem_for_quadrature(), side, fe, qrule);
    
    const std::vector<Real> &JxW = fe->get_JxW();
    
    // Physical location of the quadrature points
    const std::vector<libMesh::Point>& qpoint = fe->get_xyz();
    const std::vector<std::vector<Real> >& phi = fe->get_phi();
    const unsigned int n_phi = (unsigned int)phi.size();
    const unsigned int n1=3, n2=6*n_phi;
    
    // boundary normals
    const std::vector<libMesh::Point>& face_normals = fe->get_normals();
    Real press;
    
    DenseRealVector phi_vec, force, local_f, vec_n2;
    phi_vec.resize(n_phi); force.resize(2*n1); local_f.resize(n2);
    vec_n2.resize(n2);
    
    libMesh::Point pt;
    
    for (unsigned int qp=0; qp<qpoint.size(); qp++)
    {
        this->global_coordinates(qpoint[qp], pt);
        
        // now set the shape function values
        for ( unsigned int i_nd=0; i_nd<n_phi; i_nd++ )
            phi_vec(i_nd) = phi[i_nd][qp];
        
        Bmat.reinit(2*n1, phi_vec);
        
        // get pressure value
        func(pt, _system.time, press);
        
        // calculate force
        for (unsigned int i_dim=0; i_dim<n1; i_dim++)
            force(i_dim) = press * face_normals[qp](i_dim);
        
        Bmat.vector_mult_transpose(vec_n2, force);
        
        local_f.add(JxW[qp], vec_n2);
    }
    
    // now transform to the global system and add
    if (_elem.dim() < 3) {
        transform_to_global_system(local_f, vec_n2);
        f.add(1., vec_n2);
    }
    else
        f.add(1., local_f);
    

    return (request_jacobian && follower_forces);
}
bool
MAST::HeatConductionElementBase::
surface_radiation_residual(bool request_jacobian,
                           RealVectorX& f,
                           RealMatrixX& jac,
                           const unsigned int s,
                           MAST::BoundaryConditionBase& p) {
    
    // prepare the side finite element
    std::auto_ptr<libMesh::FEBase> fe;
    std::auto_ptr<libMesh::QBase> qrule;
    _get_side_fe_and_qrule(get_elem_for_quadrature(), s, fe, qrule);

    // get the function from this boundary condition
    const MAST::FieldFunction<Real>
    &emissivity = p.get<MAST::FieldFunction<Real> >("emissivity");
    
    const MAST::Parameter
    &T_amb      = p.get<MAST::Parameter>("ambient_temperature"),
    &T_ref_zero = p.get<MAST::Parameter>("reference_zero_temperature"),
    &sb_const   = p.get<MAST::Parameter>("stefan_bolzmann_constant");
    
    
    const std::vector<Real> &JxW               = fe->get_JxW();
    const std::vector<libMesh::Point>& qpoint  = fe->get_xyz();
    const std::vector<std::vector<Real> >& phi = fe->get_phi();
    const unsigned int n_phi                   = (unsigned int)phi.size();
    
    RealVectorX phi_vec  = RealVectorX::Zero(n_phi);
    RealMatrixX mat      = RealMatrixX::Zero(n_phi, n_phi);
    const Real
    sbc      = sb_const(),
    amb_temp = T_amb(),
    zero_ref = T_ref_zero();
    Real temp, emiss;
    libMesh::Point pt;
    MAST::FEMOperatorMatrix Bmat;
    
    for (unsigned int qp=0; qp<qpoint.size(); qp++) {
        
        _local_elem->global_coordinates_location (qpoint[qp], pt);
        
        // now set the shape function values
        for ( unsigned int i_nd=0; i_nd<n_phi; i_nd++ )
            phi_vec(i_nd) = phi[i_nd][qp];
        
        // value of flux
        emissivity(pt, _time, emiss);
        temp  = phi_vec.dot(_sol);
        
        f   += JxW[qp] * phi_vec * sbc * emiss *
        (pow(temp-zero_ref, 4.) - pow(amb_temp-zero_ref, 4.));
        
        if (request_jacobian) {
            
            Bmat.reinit(1, phi_vec);
            Bmat.right_multiply_transpose(mat, Bmat);
            jac +=  JxW[qp] * mat * sbc * emiss * 4. * pow(temp-zero_ref, 3.);
        }
    }
    
    
    return request_jacobian;
}