tKeep track of thermal energy on the particle level - Granular.jl - Julia package for granular dynamics simulation
 (HTM) git clone git://src.adamsgaard.dk/Granular.jl
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 6a2b205579d371f3ce2760cc445517592956600c
 (DIR) parent b640f26eebec4330354379ec734a996089ec7def
 (HTM) Author: Anders Damsgaard <andersd@riseup.net>
       Date:   Wed, 21 Feb 2018 11:28:03 -0500
       
       Keep track of thermal energy on the particle level
       
       Diffstat:
         M src/datatypes.jl                    |       4 ++++
         M src/grain.jl                        |      41 +++++++++++++++++++++++++++++--
         M src/interaction.jl                  |      13 +++++++++++--
         M src/io.jl                           |       3 +++
         M test/collision-2floes-oblique.jl    |      12 +++++++++---
         M test/vtk.jl                         |       2 +-
       
       6 files changed, 67 insertions(+), 8 deletions(-)
       ---
 (DIR) diff --git a/src/datatypes.jl b/src/datatypes.jl
       t@@ -70,6 +70,8 @@ mutable struct GrainCylindrical
            ocean_stress::Vector{Float64}
            atmosphere_stress::Vector{Float64}
        
       +    thermal_energy::Float64
       +
            # Visualization parameters
            color::Int
        end
       t@@ -153,6 +155,8 @@ mutable struct GrainArrays
            ocean_stress::Array{Float64, 2}
            atmosphere_stress::Array{Float64, 2}
        
       +    thermal_energy::Vector{Float64}
       +
            color::Vector{Int}
        end
        
 (DIR) diff --git a/src/grain.jl b/src/grain.jl
       t@@ -25,7 +25,9 @@ export addGrainCylindrical!
                                            rotating, enabled, verbose,
                                            ocean_grid_pos, atmosphere_grid_pos,
                                            n_contact, granular_stress, ocean_stress,
       -                                    atmosphere_stress])
       +                                    atmosphere_stress,
       +                                    thermal_energy,
       +                                    color])
        
        Creates and adds a cylindrical grain to a simulation. Most of the arguments 
        are optional, and come with default values.  The only required arguments are 
       t@@ -99,6 +101,7 @@ are optional, and come with default values.  The only required arguments are
            ocean drag [Pa].
        * `atmosphere_stress::Vector{Float64} = [0., 0.]`: resultant stress on grain
            from atmosphere drag [Pa].
       +* `thermal_energy::Float64 = 0.0`: thermal energy of grain [J].
        * `color::Int=0`: type number, usually used for associating a color to the grain
            during visualization.
        
       t@@ -170,6 +173,7 @@ function addGrainCylindrical!(simulation::Simulation,
                                        granular_stress::Vector{Float64} = [0., 0.],
                                        ocean_stress::Vector{Float64} = [0., 0.],
                                        atmosphere_stress::Vector{Float64} = [0., 0.],
       +                                thermal_energy::Float64 = 0.,
                                        color::Int = 0)
        
            # Check input values
       t@@ -267,6 +271,8 @@ function addGrainCylindrical!(simulation::Simulation,
                                         ocean_stress,
                                         atmosphere_stress,
        
       +                                 thermal_energy,
       +
                                         color
                                        )
        
       t@@ -435,6 +441,9 @@ function convertGrainDataToArrays(simulation::Simulation)
                                ## atmosphere_stress
                                zeros(Float64, 3, length(simulation.grains)),
        
       +                        ## thermal_energy
       +                        Array{Float64}(length(simulation.grains)),
       +
                                # Visualization parameters
                                ## color
                                Array{Int}(length(simulation.grains)),
       t@@ -512,6 +521,8 @@ function convertGrainDataToArrays(simulation::Simulation)
                ifarr.atmosphere_stress[1:2, i] =
                    simulation.grains[i].atmosphere_stress
        
       +        ifarr.thermal_energy[i] = simulation.grains[i].thermal_energy
       +
                ifarr.color[i] = simulation.grains[i].color
            end
        
       t@@ -578,6 +589,8 @@ function deleteGrainArrays!(ifarr::GrainArrays)
            ifarr.ocean_stress = f2
            ifarr.atmosphere_stress = f2
        
       +    ifarr.thermal_energy = f1
       +
            ifarr.color = i1
            gc()
            nothing
       t@@ -643,7 +656,9 @@ function printGrainInfo(f::GrainCylindrical)
        
            println("  granular_stress:   $(f.granular_stress) Pa")
            println("  ocean_stress:      $(f.ocean_stress) Pa")
       -    println("  atmosphere_stress: $(f.atmosphere_stress) Pa")
       +    println("  atmosphere_stress: $(f.atmosphere_stress) Pa\n")
       +
       +    println("  thermal_energy:    $(f.thermal_energy) J\n")
        
            println("  color:  $(f.color)\n")
            nothing
       t@@ -690,6 +705,26 @@ function totalGrainKineticRotationalEnergy(simulation::Simulation)
            return E_sum
        end
        
       +export grainThermalEnergy
       +"Returns the thermal energy of the grain, produced by Coulomb slip"
       +function grainThermalEnergy(grain::GrainCylindrical)
       +    return grain.thermal_energy
       +end
       +
       +export totalGrainThermalEnergy
       +"""
       +    totalGrainKineticTranslationalEnergy(simulation)
       +
       +Returns the sum of thermal energy of all grains in a simulation
       +"""
       +function totalGrainThermalEnergy(simulation::Simulation)
       +    E_sum = 0.
       +    for grain in simulation.grains
       +        E_sum += grainThermalEnergy(grain)
       +    end
       +    return E_sum
       +end
       +
        export addBodyForce!
        """
            setBodyForce!(grain, force)
       t@@ -791,6 +826,8 @@ function compareGrains(if1::GrainCylindrical, if2::GrainCylindrical)
            @test if1.ocean_stress ≈ if2.ocean_stress
            @test if1.atmosphere_stress ≈ if2.atmosphere_stress
        
       +    @test if1.thermal_energy ≈ if2.thermal_energy
       +
            @test if1.color ≈ if2.color
            nothing
        end
 (DIR) diff --git a/src/interaction.jl b/src/interaction.jl
       t@@ -256,9 +256,14 @@ function interactGrains!(simulation::Simulation, i::Int, j::Int, ic::Int)
        
            elseif k_t ≈ 0. && γ_t > 0.
                force_t = abs(γ_t * vel_t)
       +
       +        # Coulomb slip
                if force_t > μ_d_minimum*abs(force_n)
                    force_t = μ_d_minimum*abs(force_n)
       -            simulation.grains[i].contact_age[ic] = -simulation.time_step
       +            simulation.grains[i].contact_age[ic] = 0.0
       +            E_shear = abs(force_t)*vel_t*simulation.time_step
       +            simulation.grains[i].thermal_energy += 0.5*E_shear
       +            simulation.grains[j].thermal_energy += 0.5*E_shear
                end
                if vel_t > 0.
                    force_t = -force_t
       t@@ -268,10 +273,14 @@ function interactGrains!(simulation::Simulation, i::Int, j::Int, ic::Int)
        
                force_t = -k_t*δ_t - γ_t*vel_t
        
       +        # Coulomb slip
                if abs(force_t) > μ_d_minimum*abs(force_n)
                    force_t = μ_d_minimum*abs(force_n)*force_t/abs(force_t)
                    δ_t = (-force_t - γ_t*vel_t)/k_t
       -            simulation.grains[i].contact_age[ic] = -simulation.time_step
       +            simulation.grains[i].contact_age[ic] = 0.0
       +            E_shear = abs(force_t)*vel_t*simulation.time_step
       +            simulation.grains[i].thermal_energy += 0.5*E_shear
       +            simulation.grains[j].thermal_energy += 0.5*E_shear
                end
        
            else
 (DIR) diff --git a/src/io.jl b/src/io.jl
       t@@ -428,6 +428,9 @@ function writeGrainVTK(simulation::Simulation,
            WriteVTK.vtk_point_data(vtkfile, ifarr.atmosphere_stress,
                                    "Atmosphere stress [Pa]")
        
       +    WriteVTK.vtk_point_data(vtkfile, ifarr.thermal_energy,
       +                            "Thermal energy [J]")
       +
            WriteVTK.vtk_point_data(vtkfile, ifarr.color,
                                    "Color [-]")
        
 (DIR) diff --git a/test/collision-2floes-oblique.jl b/test/collision-2floes-oblique.jl
       t@@ -35,7 +35,11 @@ Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbos
        
        E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim)
        E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim)
       -@test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol
       +E_thermal_final = Granular.totalGrainThermalEnergy(sim)
       +println(E_kin_lin_init)
       +println(E_kin_lin_final)
       +println(E_thermal_final)
       +@test E_kin_lin_init ≈ E_kin_lin_final+E_thermal_final atol=E_kin_lin_init*tol
        @test E_kin_rot_init ≈ E_kin_rot_final
        
        
       t@@ -48,7 +52,8 @@ Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbos
        
        E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim)
        E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim)
       -@test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol
       +E_thermal_final = Granular.totalGrainThermalEnergy(sim)
       +@test E_kin_lin_init ≈ E_kin_lin_final+E_thermal_final atol=E_kin_lin_init*tol
        @test E_kin_rot_init ≈ E_kin_rot_final
        
        
       t@@ -61,7 +66,8 @@ Granular.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verb
        
        E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim)
        E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim)
       -@test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol
       +E_thermal_final = Granular.totalGrainThermalEnergy(sim)
       +@test E_kin_lin_init ≈ E_kin_lin_final+E_thermal_final atol=E_kin_lin_init*tol
        @test E_kin_rot_init ≈ E_kin_rot_final
        
        info("# Ice floes free to move")
 (DIR) diff --git a/test/vtk.jl b/test/vtk.jl
       t@@ -29,7 +29,7 @@ end
        
        grainpath = "test/test.grains.1.vtu"
        grainchecksum = 
       -"8ce4e4045d150fc75cdb4126edcb32cb4d09f297065602a075cbe34dceef27c7  " *
       +"f8aa4ab923b2466d7a6ffb835bfff4d0e0ff0a168ff267431a082bb3018caaa1  " *
        grainpath * "\n"
        
        graininteractionpath = "test/test.grain-interaction.1.vtp"