BinKinematics_CylinderCylinder class
Contents
Description
This is a sub-class of the BinKinematics class for the implementation of the Cylinder-Cylinder binary kinematics for particle-particle interactions of type Particle Cylinder.
classdef BinKinematics_CylinderCylinder < BinKinematics
Constructor method
methods function this = BinKinematics_CylinderCylinder(dir,dist,separ) this = this@BinKinematics(BinKinematics.PARTICLE_PARTICLE,BinKinematics.CYLINDER_CYLINDER); if (nargin == 3) this.dir = dir; this.dist = dist; this.distc = dist; this.separ = separ; end end end
Public methods: implementation of super-class declarations
methods %------------------------------------------------------------------ function setEffParams(~,int) p1 = int.elem1; p2 = int.elem2; m1 = p1.material; m2 = p2.material; % Effective and average parameters int.eff_radius = p1.radius * p2.radius / (p1.radius + p2.radius); int.eff_mass = p1.mass * p2.mass / (p1.mass + p2.mass); if (~isempty(m1.young) && ~isempty(m1.poisson) && ~isempty(m2.young) && ~isempty(m2.poisson)) int.eff_young = 1 / ((1-m1.poisson^2)/m1.young + (1-m2.poisson^2)/m2.young); if (~isempty(m1.young0) && ~isempty(m2.young0)) int.eff_young0 = 1 / ((1-m1.poisson^2)/m1.young0 + (1-m2.poisson^2)/m2.young0); end end if (~isempty(m1.shear) && ~isempty(m1.poisson) && ~isempty(m2.shear) && ~isempty(m2.poisson)) int.eff_shear = 1 / ((2-m1.poisson)/m1.shear + (2-m2.poisson)/m2.shear); end if (~isempty(m1.poisson) && ~isempty(m2.poisson)) int.avg_poisson = (m1.poisson + m2.poisson) / 2; end if (~isempty(m1.conduct) && ~isempty(m2.conduct)) int.eff_conduct = m1.conduct * m2.conduct / (m1.conduct + m2.conduct); int.avg_conduct = (p1.radius + p2.radius) / (p1.radius/m1.conduct + p2.radius/m2.conduct); end end %------------------------------------------------------------------ function this = setRelPos(this,p1,p2) this.dir = p2.coord - p1.coord; this.dist = norm(this.dir); this.distc = this.dist; this.separ = this.dist - p1.radius - p2.radius; end %------------------------------------------------------------------ function this = setOverlaps(this,int,dt) p1 = int.elem1; p2 = int.elem2; % Normal overlap and unit vector this.ovlp_n = -this.separ; this.dir_n = this.dir / this.dist; % Positions of contact point relative to centroids % Assumption: half of the overlap c1 = (p1.radius - this.ovlp_n/2) * this.dir_n; c2 = -(p2.radius - this.ovlp_n/2) * this.dir_n; % Velocities at contact point (3D due to cross-product) w1 = cross([0;0;p1.veloc_rot],[c1(1);c1(2);0]); w2 = cross([0;0;p2.veloc_rot],[c2(1);c2(2);0]); vc1 = p1.veloc_trl + w1(1:2); vc2 = p2.veloc_trl + w2(1:2); % Relative velocities this.vel_trl = vc1 - vc2; this.vel_rot = w1(1:2) + w2(1:2); this.vel_ang = p1.veloc_rot - p2.veloc_rot; % Normal overlap rate of change this.vel_n = dot(this.vel_trl,this.dir_n); % Tangential relative velocity vt = this.vel_trl - this.vel_n * this.dir_n; % Tangential unit vector if (any(vt)) this.dir_t = vt / norm(vt); else this.dir_t = [0;0]; end % Tangential overlap rate of change this.vel_t = dot(this.vel_trl,this.dir_t); % Tangential overlap if (isempty(this.ovlp_t)) this.ovlp_t = this.vel_t * dt; else this.ovlp_t = this.ovlp_t + this.vel_t * dt; end end %------------------------------------------------------------------ function this = setContactArea(this,int) % Needed properties d = this.dist; r1 = int.elem1.radius; r2 = int.elem2.radius; r1_2 = r1 * r1; r2_2 = r2 * r2; % Contact radius % (abs to avoid imag. numbers when particles are inside each other) this.contact_radius = sqrt(abs(r1_2 - ((r1_2-r2_2+d^2)/(2*d))^2)); % Contact correction if (~isempty(int.corarea)) % Adjusted radius int.corarea.fixRadius(int); % Adjusted distance consistent with adjusted radius this.distc = sqrt(r1^2-this.contact_radius^2) + sqrt(r2^2-this.contact_radius^2); end end %------------------------------------------------------------------ function this = setVoronoiEdge(this,drv,int) % Indices of common vertices between particles common = intersect(drv.vor_idx{int.elem1.id},... drv.vor_idx{int.elem2.id}); % Compute edge length according to number of common vertices if (length(common) == 2) if (common(1) == 1) % index of unbounded point is 1 (always the 1st element) % Assumption: bounded side of the edge is mirroed to the unbounded side A = polyarea([int.elem1.coord(1),int.elem2.coord(1),drv.vor_vtx(common(2),1)],... [int.elem1.coord(2),int.elem2.coord(2),drv.vor_vtx(common(2),2)]); this.vedge = 4 * A / this.dist; else pt1 = drv.vor_vtx(common(1),:); pt2 = drv.vor_vtx(common(2),:); this.vedge = norm(pt1-pt2); end elseif (length(common) == 3) % always 1 unbounded point (index is 1) idx = common(common~=1); pt1 = drv.vor_vtx(idx(1),:); pt2 = drv.vor_vtx(idx(2),:); this.vedge = norm(pt1-pt2); else this.vedge = 0; end end %------------------------------------------------------------------ function addContactForceNormalToParticles(~,int) int.elem1.force = int.elem1.force + int.cforcen.total_force; int.elem2.force = int.elem2.force - int.cforcen.total_force; end %------------------------------------------------------------------ function addContactForceTangentToParticles(~,int) int.elem1.force = int.elem1.force + int.cforcet.total_force; int.elem2.force = int.elem2.force - int.cforcet.total_force; end %------------------------------------------------------------------ function addContactTorqueTangentToParticles(this,int) % Tangential force vector for each particle ft1 = int.cforcet.total_force; ft2 = -ft1; % Lever arm for each particle % Assumption: half of the overlap l1 = (int.elem1.radius-this.ovlp_n/2) * this.dir_n; l2 = -(int.elem2.radius-this.ovlp_n/2) * this.dir_n; % Torque from tangential contact force (3D due to cross-product) torque1 = cross([l1(1);l1(2);0],[ft1(1);ft1(2);0]); torque2 = cross([l2(1);l2(2);0],[ft2(1);ft2(2);0]); torque1 = torque1(3); torque2 = torque2(3); % Add torque from tangential contact force to particles int.elem1.torque = int.elem1.torque + torque1; int.elem2.torque = int.elem2.torque + torque2; end %------------------------------------------------------------------ function addRollResistTorqueToParticles(~,int) int.elem1.torque = int.elem1.torque + int.rollres.torque; int.elem2.torque = int.elem2.torque + int.rollres.torque; end %------------------------------------------------------------------ function addDirectConductionToParticles(~,int) int.elem1.heat_rate = int.elem1.heat_rate + int.dconduc.total_hrate; int.elem2.heat_rate = int.elem2.heat_rate - int.dconduc.total_hrate; end %------------------------------------------------------------------ function addIndirectConductionToParticles(~,int) int.elem1.heat_rate = int.elem1.heat_rate + int.iconduc.total_hrate; int.elem2.heat_rate = int.elem2.heat_rate - int.iconduc.total_hrate; end end
end