Particle class

Contents

Description

This is a handle heterogeneous super-class for the definition of particles.

In DEM, particles are assumed to be soft, so that contact forces and heat exchange are originated by overlaps. Furthermore, their shapes are assumed to be preserved after collisions.

This super-class defines abstract methods that must be implemented in the derived sub-classes:

classdef Particle < handle & matlab.mixin.Heterogeneous

Constant values

    properties (Constant = true, Access = public)
        % Types of particle
        SPHERE   = uint8(1);
        CYLINDER = uint8(2);
    end

Public properties

    properties (SetAccess = public, GetAccess = public)
        % Identification
        type uint8  = uint8.empty;    % flag for type of particle
        id   uint32 = uint32.empty;   % identification number

        % Geometric properties
        char_len double = double.empty;   % characteristic length
        surface  double = double.empty;   % surface area
        cross    double = double.empty;   % in-plane cross-sectional area
        volume   double = double.empty;   % volume
        minertia double = double.empty;   % moment of inertia

        % Physical properties
        material   Material = Material.empty;   % handle to object of Material_Solid subclass
        mass       double   = double.empty;     % mass (density * volume)
        weight     double   = double.empty;     % weight vector (mass * gravity)
        tinertia   double   = double.empty;     % thermal inertia (mass * heat_capacity)
        conv_coeff double   = double.empty;     % convection coefficient

        % Particle-fluid interaction
        nusselt   % handle to object of Nusselt class

        % Neighbors Interactions
        % Attention: These properties may contain references to deleted particles
        interacts Interact = Interact.empty;   % handles to objects of Interact class
        neigh_p   Particle = Particle.empty;   % handles to objects of Particle class of neighbour particles
        neigh_w   Wall     = Wall.empty;       % handles to objects of Wall class of neighbour walls
        neigh_pid uint32   = uint32.empty;     % vector of neighbour particles IDs (int is faster to search than obj)
        neigh_wid uint32   = uint32.empty;     % vector of neighbour walls IDs (int is faster to search than obj)
        verlet_p  Particle = Particle.empty;   % handles to objects of Particle class in the verlet list
        verlet_w  Wall     = Wall.empty;       % handles to objects of Wall class in the verlet list

        % Porosity data
        porosity double = double.empty;   % average porosity (void ratio) around particle
        por_freq double = double.empty;   % average porosity update frequency (in steps) (double to accept NaN)

        % Behavior flags
        free_trl   logical = logical.empty;   % flag for translational free particle
        free_rot   logical = logical.empty;   % flag for rotational free particle
        free_therm logical = logical.empty;   % flag for thermally free particle

        % Prescribed conditions (handles to objects of Condition class)
        pc_force    Condition = Condition.empty;
        pc_torque   Condition = Condition.empty;
        pc_heatflux Condition = Condition.empty;
        pc_heatrate Condition = Condition.empty;

        % Fixed conditions (handles to objects of Condition class)
        fc_translation Condition = Condition.empty;
        fc_rotation    Condition = Condition.empty;
        fc_temperature Condition = Condition.empty;

        % Total forcing terms
        force     double = double.empty;
        torque    double = double.empty;
        heat_rate double = double.empty;

        % Current mechanical state
        coord     double = double.empty;   % coordinates of centroid
        orient    double = double.empty;   % orientation angle
        veloc_trl double = double.empty;   % translational velocity
        veloc_rot double = double.empty;   % rotational velocity
        accel_trl double = double.empty;   % translational acceleration
        accel_rot double = double.empty;   % rotational acceleration

        % Current thermal state
        temperature double = double.empty;   % temperature
        temp_change double = double.empty;   % temperature rate of change
    end

Constructor method

    methods
        function this = Particle(type)
            if (nargin > 0)
                this.type = type;
            end
        end
    end

Default sub-class definition

    methods (Static, Access = protected)
        function defaultObject = getDefaultScalarElement
            defaultObject = Particle_Sphere;
        end
    end

Abstract methods: implemented in derived sub-classes

    methods (Abstract)
        %------------------------------------------------------------------
        setDefaultProps(this);

        %------------------------------------------------------------------
        setCharLen(this);

        %------------------------------------------------------------------
        setSurface(this);

        %------------------------------------------------------------------
        setCrossSec(this);

        %------------------------------------------------------------------
        setVolume(this);

        %------------------------------------------------------------------
        setMInertia(this);

        %------------------------------------------------------------------
        setLocalPorosity(this,por);

        %------------------------------------------------------------------
        [x1,y1,x2,y2] = getBBoxLimits(this);
    end

Public methods

    methods
        %------------------------------------------------------------------
        function setMass(this)
            this.mass = this.volume * this.material.density;
        end

        %------------------------------------------------------------------
        function setWeight(this,g)
            this.weight = this.mass * g;
        end

        %------------------------------------------------------------------
        function setTInertia(this)
            this.tinertia = this.mass * this.material.hcapacity;
        end

        %------------------------------------------------------------------
        function setConvCoeff(this,drv)
            if (~isempty(this.nusselt))
                Nu = this.nusselt.getValue(this,drv);
                this.conv_coeff = Nu * drv.fluid.conduct / this.char_len;
            end
        end

        %------------------------------------------------------------------
        function resetForcingTerms(this)
            this.force     = [0;0];
            this.torque    = 0;
            this.heat_rate = 0;
        end

        %------------------------------------------------------------------
        function addWeight(this)
            if (~isempty(this.weight))
                this.force = this.force + this.weight;
            end
        end

        %------------------------------------------------------------------
        function addGblDampTransl(this,damp_coeff)
            this.force = this.force - damp_coeff * this.veloc_trl;
        end

        %------------------------------------------------------------------
        function addGblDampRot(this,damp_coeff)
            this.torque = this.torque - damp_coeff * this.veloc_rot;
        end

        %------------------------------------------------------------------
        function addPCForce(this,time)
            for i = 1:length(this.pc_force)
                if (this.pc_force(i).isActive(time))
                    this.force = this.force + this.pc_force(i).getValue(time);
                end
            end
        end

        %------------------------------------------------------------------
        function addPCTorque(this,time)
            for i = 1:length(this.pc_torque)
                if (this.pc_torque(i).isActive(time))
                    this.torque = this.torque + this.pc_torque(i).getValue(time);
                end
            end
        end

        %------------------------------------------------------------------
        function addPCHeatFlux(this,time)
            for i = 1:length(this.pc_heatflux)
                if (this.pc_heatflux(i).isActive(time))
                    hr = this.pc_heatflux(i).getValue(time) * this.surface;
                    this.heat_rate = this.heat_rate + hr;
                end
            end
        end

        %------------------------------------------------------------------
        function addPCHeatRate(this,time)
            for i = 1:length(this.pc_heatrate)
                if (this.pc_heatrate(i).isActive(time))
                    this.heat_rate = this.heat_rate + this.pc_heatrate(i).getValue(time);
                end
            end
        end

        %------------------------------------------------------------------
        function addConvection(this,drv)
            if (~isempty(this.conv_coeff))
                this.heat_rate = this.heat_rate + this.conv_coeff * this.surface * (drv.fluid_temp-this.temperature);
            end
        end

        %------------------------------------------------------------------
        function setFixedMech(this,time)
            this.free_trl = true;
            this.free_rot = true;
            for i = 1:length(this.fc_translation)
                if (this.fc_translation(i).isActive(time))
                    this.free_trl = false;
                    break;
                end
            end
            for i = 1:length(this.fc_rotation)
                if (this.fc_rotation(i).isActive(time))
                    this.free_rot = false;
                    break;
                end
            end
        end

        %------------------------------------------------------------------
        function setFixedThermal(this,time)
            this.free_therm = true;
            for i = 1:length(this.fc_temperature)
                if (this.fc_temperature(i).isActive(time))
                    this.free_therm = false;
                    return;
                end
            end
        end

        %------------------------------------------------------------------
        function setFCTranslation(this,time,dt)
            if (this.free_trl)
                return;
            end
            v = [0;0];
            for i = 1:length(this.fc_translation)
                if (this.fc_translation(i).isActive(time))
                    v = v + this.fc_translation(i).getValue(time);
                end
            end
            this.accel_trl = (v-this.veloc_trl) / dt;
            this.veloc_trl =  v;
            this.coord     =  this.coord + v * dt;
        end

        %------------------------------------------------------------------
        function setFCRotation(this,time,dt)
            if (this.free_rot)
                return;
            end
            w = 0;
            for i = 1:length(this.fc_rotation)
                if (this.fc_rotation(i).isActive(time))
                    w = w + this.fc_rotation(i).getValue(time);
                end
            end
            this.accel_rot = (w-this.veloc_rot) / dt;
            this.veloc_rot =  w;
            this.orient    =  this.orient + w * dt;
        end

        %------------------------------------------------------------------
        function setFCTemperature(this,time)
            if (this.free_therm)
                return;
            end
            for i = 1:length(this.fc_temperature)
                if (this.fc_temperature(i).isActive(time))
                    this.temperature = this.fc_temperature(i).getValue(time);
                end
            end
        end

        %------------------------------------------------------------------
        function setAccelTrl(this)
            this.accel_trl = this.force / this.mass;
        end

        %------------------------------------------------------------------
        function setAccelRot(this)
            this.accel_rot = this.torque / this.minertia;
        end

        %------------------------------------------------------------------
        function setTempChange(this)
            this.temp_change = this.heat_rate / this.tinertia;
        end
    end
end