Real
RichardsSUPGstandard::dtauSUPG_dp(RealVectorValue vel,
                                  RealVectorValue dvel_dp,
                                  Real traceperm,
                                  RealVectorValue b,
                                  Real db2_dp) const
{
  Real norm_vel = vel.norm();
  if (norm_vel == 0.0)
    return 0.0; // this deriv is not necessarily correct, but i can't see a better thing to do

  Real norm_vel_dp = dvel_dp * vel / norm_vel;

  Real norm_b = b.norm();
  if (norm_b == 0)
    return 0.0; // this deriv is not necessarily correct, but i can't see a better thing to do
  Real norm_b_dp = db2_dp / (2.0 * norm_b);

  Real h = 2.0 * norm_vel / norm_b; // h is a measure of the element length in the "a" direction
  Real h_dp = 2.0 * norm_vel_dp / norm_b - 2.0 * norm_vel * norm_b_dp / (norm_b * norm_b);

  Real alpha = 0.5 * norm_vel * h / (traceperm * _p_SUPG); // this is the Peclet number
  Real alpha_dp = 0.5 * (norm_vel_dp * h + norm_vel * h_dp) / (traceperm * _p_SUPG);

  Real xi_tilde = RichardsSUPGstandard::cosh_relation(alpha);
  Real xi_tilde_prime = RichardsSUPGstandard::cosh_relation_prime(alpha);
  Real xi_tilde_dp = xi_tilde_prime * alpha_dp;

  // Real tau = xi_tilde/norm_b;
  const Real tau_dp = xi_tilde_dp / norm_b - xi_tilde * norm_b_dp / (norm_b * norm_b);

  return tau_dp;
}
RealVectorValue
RichardsSUPGstandard::dtauSUPG_dgradp(RealVectorValue vel,
                                      RealTensorValue dvel_dgradp,
                                      Real traceperm,
                                      RealVectorValue b,
                                      RealVectorValue db2_dgradp) const
{
  Real norm_vel = vel.norm();
  if (norm_vel == 0)
    return RealVectorValue();

  RealVectorValue norm_vel_dgradp(dvel_dgradp * vel / norm_vel);

  Real norm_b = b.norm();
  if (norm_b == 0)
    return RealVectorValue();
  RealVectorValue norm_b_dgradp = db2_dgradp / 2.0 / norm_b;

  Real h = 2 * norm_vel / norm_b; // h is a measure of the element length in the "a" direction
  RealVectorValue h_dgradp(2 * norm_vel_dgradp / norm_b -
                           2.0 * norm_vel * norm_b_dgradp / norm_b / norm_b);

  Real alpha = 0.5 * norm_vel * h / traceperm / _p_SUPG; // this is the Peclet number
  RealVectorValue alpha_dgradp =
      0.5 * (norm_vel_dgradp * h + norm_vel * h_dgradp) / traceperm / _p_SUPG;

  Real xi_tilde = RichardsSUPGstandard::cosh_relation(alpha);
  Real xi_tilde_prime = RichardsSUPGstandard::cosh_relation_prime(alpha);
  RealVectorValue xi_tilde_dgradp = xi_tilde_prime * alpha_dgradp;

  RealVectorValue tau_dgradp =
      xi_tilde_dgradp / norm_b - xi_tilde * norm_b_dgradp / (norm_b * norm_b);

  return tau_dgradp;
}
Exemple #3
0
OrientedBoxInterface::OrientedBoxInterface(const InputParameters & parameters) :
    _center(parameters.get<Point>("center"))
{
  const std::string & name = parameters.get<std::string>("_object_name");

  // Define the bounding box
  Real xmax = 0.5 * parameters.get<Real>("width");
  Real ymax = 0.5 * parameters.get<Real>("length");
  Real zmax = 0.5 * parameters.get<Real>("height");

  Point bottom_left(-xmax, -ymax, -zmax);
  Point top_right(xmax, ymax, zmax);

  _bounding_box = new MeshTools::BoundingBox(bottom_left, top_right);

  /*
   * now create the rotation matrix that rotates the oriented
   * box's width direction to "x", its length direction to "y"
   * and its height direction to "z"
   */
  RealVectorValue w = parameters.get<RealVectorValue>("width_direction");
  RealVectorValue l = parameters.get<RealVectorValue>("length_direction");

  /*
   * Normalize the width and length directions in readiness for
   * insertion into the rotation matrix
   */
  Real len = w.norm();
  if (len == 0.0)
    mooseError("Length of width_direction vector is zero in " << name);
  w /= len;

  len = l.norm();
  if (len == 0.0)
    mooseError("Length of length_direction vector is zero in " << name);
  l /= len;

  if (w*l > 1E-10)
    mooseError("width_direction and length_direction are not perpendicular in " << name);

  // The rotation matrix!
  _rot_matrix = new RealTensorValue(w, l, w.cross(l));

}
Real
RichardsSUPGstandard::tauSUPG(RealVectorValue vel, Real traceperm, RealVectorValue b) const
{
  // vel = velocity, b = bb
  Real norm_v = vel.norm();
  Real norm_b = b.norm(); // Hughes et al investigate infinity-norm and 2-norm.  i just use 2-norm
                          // here.   norm_b ~ 2|a|/ele_length_in_direction_of_a

  if (norm_b == 0)
    return 0.0; // Only way for norm_b=0 is for zero ele size, or vel=0.  Either way we don't have
                // to upwind.

  Real h = 2.0 * norm_v / norm_b; // h is a measure of the element length in the "a" direction
  Real alpha = 0.5 * norm_v * h / (traceperm * _p_SUPG); // this is the Peclet number

  const Real xi_tilde = RichardsSUPGstandard::cosh_relation(alpha);

  return xi_tilde / norm_b;
}
Exemple #5
0
bool
LineSegment::intersect (const LineSegment & l, Point & intersect_p) const
{
  /**
   * First check for concurance:
   *
   *
   * | x1 y1 z1 1 |
   * | x2 y2 z2 1 | = (x3 - x1) * [(x2-x1) x (x4-x3)] = 0
   * | x3 y3 z3 1 |
   * | x4 y4 z4 1 |
   *
   *
   * Solve:
   *   x = _p0 + (_p1 - _p0)*s
   *   x = l.p0 + (l._p1 - l.p0)*t
   *
   *   where
   *   a = _p1 - _p0
   *   b = l._p1 - l._p0
   *   c = l._p0 - _p0
   *
   *   s = (c x b) * (a x b) / | a x b |^2
   */
  RealVectorValue a = _p1 - _p0;
  RealVectorValue b = l._p1 - l._p0;
  RealVectorValue c = l._p0 - _p0;

  RealVectorValue v = a.cross(b);

  // Check for parallel lines
  if (std::abs(v.norm()) < 1.e-10 && std::abs(c.cross(a).norm()) < 1.e-10)
  {
    // TODO: The lines are co-linear but more work is needed to determine and intersection point
    //       it could be the case that the line segments don't lie on the same line or overlap only
    //       a bit
    return true;
  }

  // Check that the lines are coplanar
  Real concur = c * (a.cross(b));
  if (std::abs(concur) > 1.e-10)
    return false;

  Real s = (c.cross(b) * v) / (v*v);
  Real t = (c.cross(a) * v) / (v*v);

  // if s and t are between 0 and 1 then the Line Segments intersect
  // TODO: We could handle other case of clamping to the end of Line
  //       Segements if we want to here

  if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
  {
    intersect_p = _p0 + s*a;
    return true;
  }
  return false;

  /**
   * Parameteric Equation of lines
   * _p0 + t(v0) = l._p0 + u(v1)
   *
   * Case 1: Parallel Lines
   *         v0 x v1 == 0
   *
   * Case 1a: Collinear Lines
   *         v0 x v1 == 0
   *         (l._p0 - _p0) x (_p1 - _p0) == 0
   *
   * Case 2: Intersecting Lines
   *         0 <= t <= 1
   *         0 <= u <= 1
   *
   *
   * Case 1: The lines do not intersect
   *         vleft cross vright = non-zero
   *
   * Case 2: The lines are co-linear
   *         vleft cross vright = zero
   *         vleft (Denominator) = zero
   *
   * Case 3: The line intersect at a single point
   *         vleft cross vright = zero
   *         vleft (Denominator) = non-zero
  RealVectorValue v0 = _p1 - _p0;
  RealVectorValue v1 = l._p1 - l._p0;
  RealVectorValue v2 = l._p0 - _p0;

  RealVectorValue vbot = v0.cross(v1);
  RealVectorValue vtop = v2.cross(v1);

  RealVectorValue crossed = vleft.cross(vright);

  // Case 1: No intersection
  if (std::abs(vleft.cross(vright).size()) > 1.e-10)
    return false;

  // Case 2: Co-linear (just return one of the end points)
  if (std::abs(vleft.size()) < 1.e-10)
  {
    intersect_p = _p0;
    return true;
  }

  // Case 3:

  //TODO: We could detect whether the Line Segments actually overlap
  //      instead of whether the Lines are co-linear

  Real a = vright.size()/vleft.size();
  intersect_p = _p0 + a*v0;
  return true;
     */
}
FrictionalContactProblem::ContactState
FrictionalContactProblem::calculateInteractionSlip(RealVectorValue & slip,
                                                   Real & slip_residual,
                                                   const RealVectorValue & normal,
                                                   const RealVectorValue & residual,
                                                   const RealVectorValue & incremental_slip,
                                                   const RealVectorValue & stiffness,
                                                   const Real friction_coefficient,
                                                   const Real slip_factor,
                                                   const Real slip_too_far_factor,
                                                   const int dim)
{

  ContactState state = STICKING;

  RealVectorValue normal_residual = normal * (normal * residual);
  Real normal_force = normal_residual.norm();

  // _console << "normal=" << info._normal << std::endl;
  // _console << "normal_force=" << normal_force << std::endl;
  // _console << "residual=" << residual << std::endl;
  // _console << "stiffness=" << stiff_vec << std::endl;

  RealVectorValue tangential_force = normal_residual - residual ; // swap sign to make the code more manageable
  Real tangential_force_magnitude = tangential_force.norm();

  Real capacity = normal_force * friction_coefficient;
  if (capacity < 0.0)
    capacity = 0.0;

  Real slip_inc = incremental_slip.norm();

  slip(0)=0.0;
  slip(1)=0.0;
  slip(2)=0.0;

  if (slip_inc > 0)
  {
    state = SLIPPING;
    Real slip_dot_tang_force = incremental_slip*tangential_force / slip_inc;
    if (slip_dot_tang_force < capacity)
    {
      state = SLIPPED_TOO_FAR;
      // _console << "STF slip_dot_force: " << slip_dot_tang_force << " capacity: " << capacity << std::endl;
    }
  }

  Real excess_force = tangential_force_magnitude - capacity;
  if (excess_force < 0.0)
    excess_force = 0;

  if (state == SLIPPED_TOO_FAR)
  {
    RealVectorValue slip_inc_direction = incremental_slip / slip_inc;
    Real tangential_force_in_slip_dir = slip_inc_direction*tangential_force;
    slip_residual = capacity - tangential_force_in_slip_dir;

    RealVectorValue force_from_unit_slip(0.0,0.0,0.0);
    for (int i=0; i<dim; ++i)
      force_from_unit_slip(i) = stiffness(i) * slip_inc_direction(i);

    Real stiffness_slipdir = force_from_unit_slip * slip_inc_direction; //k=f resolved to slip dir because f=kd and d is a unit vector

    Real slip_distance = slip_too_far_factor*(capacity - tangential_force_in_slip_dir) / stiffness_slipdir;
//    _console << "STF dist: " << slip_distance << " inc: " << slip_inc << std::endl;
//    _console << "STF  cap: " << capacity << " tfs: " << tangential_force_in_slip_dir << std::endl;
    if (slip_distance < slip_inc)
    {
//      _console << "STF" << std::endl;
      slip = slip_inc_direction * -slip_distance;
    }
    else
    {
//      _console << "STF max" << std::endl;
      slip = -incremental_slip;
    }
  }
  else if (excess_force > 0)
  {
    state = SLIPPING;
    Real tangential_force_magnitude = tangential_force.norm();
    slip_residual = excess_force;

    RealVectorValue tangential_direction = tangential_force / tangential_force_magnitude;
    RealVectorValue excess_force_vector = tangential_direction * excess_force;


    for (int i=0; i<dim; ++i)
      slip(i) = slip_factor * excess_force_vector(i) / stiffness(i);

    //zero out component of slip in normal direction
    RealVectorValue slip_normal_dir = normal * (normal * slip);
    slip = slip - slip_normal_dir;
  }
  return state;
}