Search_SimpleLoop class
Contents
Description
This is a sub-class of the Search class for the implementation of the search algorithm Simple Loop.
This algorithm performs an outer loop over all particles and searches for their interactions through inner loops over all particles with a higher ID number and all walls.
The reference element of each interaction (element 1) is the particle with smaller ID number.
For each interaction found, a binary Interaction object is created to manage the mechanical and / or thermal interaction between both elements.
classdef Search_SimpleLoop < Search
Public properties
properties (SetAccess = public, GetAccess = public)
% Base objects for kinematics
kinpp_sph BinKinematics = BinKinematics.empty; % sphere particle - sphere particle
kinpw_sph_line BinKinematics = BinKinematics.empty; % sphere particle - line wall
kinpw_sph_circ BinKinematics = BinKinematics.empty; % sphere particle - circle wall
kinpp_cyl BinKinematics = BinKinematics.empty; % cylinder particle - sphere particle
kinpw_cyl_line BinKinematics = BinKinematics.empty; % cylinder particle - line wall
kinpw_cyl_circ BinKinematics = BinKinematics.empty; % cylinder particle - circle wall
end
Constructor method
methods
function this = Search_SimpleLoop()
this = this@Search(Search.SIMPLE_LOOP);
this.setDefaultProps();
end
end
Public methods: implementation of super-class declarations
methods
%------------------------------------------------------------------
function setDefaultProps(this)
this.freq = 1;
this.done = false;
this.cutoff = 0;
this.kinpp_sph = BinKinematics_SphereSphere();
this.kinpw_sph_line = BinKinematics_SphereWlin();
this.kinpw_sph_circ = BinKinematics_SphereWcirc();
this.kinpp_cyl = BinKinematics_CylinderCylinder();
this.kinpw_cyl_line = BinKinematics_CylinderWlin();
this.kinpw_cyl_circ = BinKinematics_CylinderWcirc();
end
%------------------------------------------------------------------
function initialize(~,~)
end
%------------------------------------------------------------------
function execute(this,drv)
% Set flags
this.done = true;
rmv = false;
% Outer loop over reference particles
for i = 1:drv.n_particles
p1 = drv.particles(i);
% Inner loop over all other particles with higher ID
for j = 1:drv.n_particles
p2 = drv.particles(j);
if (p1.id >= p2.id)
continue;
end
% Check for existing interaction
if (any(p1.neigh_pid == p2.id))
% Get interaction object
int = findobj(p1.interacts,'elem2',p2);
% Compute separation between elements
int.kinemat = int.kinemat.setRelPos(p1,p2);
% Check if separation is greater than cutoff distance
% Assumption: cutoff ratio applies to maximum radius
if (int.kinemat.separ >= this.cutoff * max(p1.radius,p2.radius))
% Remove interaction references from elements
p1.interacts(p1.interacts==int) = [];
p1.neigh_p(p1.neigh_p==p2) = [];
p1.neigh_pid(p1.neigh_pid==p2.id) = [];
p2.interacts(p2.interacts==int) = [];
p2.neigh_p(p2.neigh_p==p1) = [];
p2.neigh_pid(p2.neigh_pid==p1.id) = [];
% Delete interaction object
delete(int);
rmv = true;
end
else
% Create new particle-particle interaction if needed
this.createInteractPP(drv,p1,p2);
end
end
% Inner loop over all walls
for j = 1:drv.n_walls
w = drv.walls(j);
% Check for existing interaction
if (any(p1.neigh_wid == w.id))
% Get interaction object
int = findobj(p1.interacts,'elem2',w);
% Compute separation between elements
int.kinemat = int.kinemat.setRelPos(p1,w);
% Check if separation is greater than cutoff distance
% Assumption: cutoff ratio applies to particle radius
if (int.kinemat.separ >= this.cutoff * p1.radius)
% Remove interaction references from particle
% (neigh_w is cleaned by searching the id
% to avoid error when it is heterogeneous:
% i.e. different wall types)
p1.interacts(p1.interacts==int) = [];
p1.neigh_w([p1.neigh_w.id]==w.id) = [];
p1.neigh_wid(p1.neigh_wid==w.id) = [];
% Delete interaction object
delete(int);
rmv = true;
end
else
% Create new particle-wall interaction if needed
this.createInteractPW(drv,p1,w);
end
end
end
% Erase handles to removed interactions from global list
if (rmv)
drv.interacts(~isvalid(drv.interacts)) = [];
end
% Update total number of interactions
drv.n_interacts = length(drv.interacts);
end
end
Public methods: sub-class specifics
methods
%------------------------------------------------------------------
function createInteractPP(this,drv,p1,p2)
% Compute separation between particles surfaces
% PS: This is exclusive for round particles to avoid calling the
% base kinematic object (a bit slower).
% For other shapes, the base kinematic object will be used.
dir = p2.coord - p1.coord;
dist = norm(dir);
separ = dist - p1.radius - p2.radius;
% Check if interaction exists
% Assumption: cutoff ratio applies to maximum radius
if (separ >= this.cutoff * max(p1.radius,p2.radius))
return;
end
% Create new interaction object by copying base object
int = copy(this.b_interact);
% Set handles to interecting elements
int.elem1 = p1;
int.elem2 = p2;
% Create binary kinematic object
kin = this.createPPKinematic(p1,dir,dist,separ);
kin.setEffParams(int);
int.kinemat = kin;
% Add references of new interaction to both elements and global list
p1.interacts(end+1) = int;
p1.neigh_p(end+1) = p2;
p1.neigh_pid(end+1) = p2.id;
p2.interacts(end+1) = int;
p2.neigh_p(end+1) = p1;
p2.neigh_pid(end+1) = p1.id;
drv.interacts(end+1) = int;
end
%------------------------------------------------------------------
function createInteractPW(this,drv,p,w)
% Check elements separation and copy kinematics object from base object
% Assumption: cutoff ratio applies to particle radius
switch (this.pwInteractionType(p,w))
case 1
this.kinpw_sph_line.setRelPos(p,w);
if (this.kinpw_sph_line.separ >= this.cutoff * p.radius)
return;
end
kin = copy(this.kinpw_sph_line);
case 2
this.kinpw_sph_circ.setRelPos(p,w);
if (this.kinpw_sph_circ.separ >= this.cutoff * p.radius)
return;
end
kin = copy(this.kinpw_sph_circ);
case 3
this.kinpw_cyl_line.setRelPos(p,w);
if (this.kinpw_cyl_line.separ >= this.cutoff * p.radius)
return;
end
kin = copy(this.kinpw_cyl_line);
case 4
this.kinpw_cyl_circ.setRelPos(p,w);
if (this.kinpw_cyl_circ.separ >= this.cutoff * p.radius)
return;
end
kin = copy(this.kinpw_cyl_circ);
end
% Create new interaction object by copying base object
int = copy(this.b_interact);
% Set handles to interecting elements
int.elem1 = p;
int.elem2 = w;
% Set binary kinematic object
kin.setEffParams(int);
int.kinemat = kin;
% Set flag for insulated interaction
int.insulated = w.insulated;
% Add references of new interaction to particle and global list
p.interacts(end+1) = int;
p.neigh_w(end+1) = w;
p.neigh_wid(end+1) = w.id;
drv.interacts(end+1) = int;
end
end
end