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; }
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; }
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; }