TORTOISE

Introduction

TORTOISE is a set of C++ libraries that allows for the computation of the strongly out of equilibrium dynamics in realistic materials. It addresses the time evolution of the full Boltzmann equation including transport and scattering under no close-to-equilibrium approximation and keeping all the involved populations free to change in time. It does not calculate dispersions or scattering amplitudes, which are required as input.


The most critical point is that it conserves exactly (actually to machine precision) particle number, momentum and energy. The exact conservation of those quantities is essential for the time propagation, over different timescales, of systems far from equilibrium not in contact with a bath (i.e. when it is interesting to explicitly compute the time propagation of all the quasiparticles involved in the system). When parts of the system are treated as a bath (usually phonons), energy is dissipated and an exact energy-conserving method is not necessary. However when that is not the case, even a small error in the energy conservation at each time step piles up over many time steps, leading the numerical solution to converge to a wrong equilibrium (in the best case), or not to converge at all, making predictions spanning several timescales meaningless. All TORTOISE libraries are build to conserve all the above mentioned quantities to machine precision, and can therefore describe thermalisation and partial thermalisation processes happening over very different timescales.


You can find the latest stable version of TORTOISE at:

https://github.com/MarcoBattiato/TORTOISE


There is a version under current development with more features. Write an email to marco.battiato@ntu.edu.sg to request for access.

TORTOISE Tutorial

This tutorial below is a work in progress. It is mainly meant as a general introduction and showcase of some functionalities of the library.

Below you can find few presentations that are meant to give an introduction to TORTOISE. They are taylored towards bachelor students who might not have taken courses like statistical mechanics, and have taken only one solid state physics and one numerical methods course.

BoltzmannScatteringElementaryIntro.pptx

Elementary introduction to the Boltzmann scattering equation

This presentation gives a brief introduction to the Boltzmann scattering equation. It is taylored toward bachelor students who might not have taken courses like statistical mechanics, and have taken only one solid state physics course.

If you are looking for a derivation of the Boltzmann scattering integral, you can find it very nicely covered  in Snoke's Solid State Physics, Chapter 4 Paragraphs 4.7 and 4.8.

NumericalMethodIntro_1.pptx

Brief introduction to the numerical method in TORTOISE Part 1

This presentation is the part 1 of an introduction to the numerical method used in TORTOISE. It is taylored to bachelor students, who however have taken some introductory course in numerical methods.

Overview

TORTOISE can calculate thermalisation dynamics in matherials of any dimensionality. It takes quasiparticles' dispersions and scattering matrix elements as input (they can be either analytic estimations or ab-initio data read from file, or computed on the go). It then solves the time-dependent scattering term of the Boltzmann equation (also known as the quantum Fokker-Planck equation) with no close to equilibrium approximations: this means that all populations are propagated, no baths are required (but can be included), and full proper thermalisation can be described. 

It also conserves particles, energy and momentum exactly. Such property, which might seem only a technical feature, is fundamental in far-from-equilibrium time propagation, and is one of the two key features that allow TORTOISE to go beyong close-to-equilibrium and avoid the use of baths (like for instance phonon bath, which instead can be fully calculated in TORTOISE).


const int               nDim = 2;    // Dimensionality of the Material

const realValueType     protonCharge = 1.;

    

Point<nDim>             originBZ({0.0, 0.}), 

  sideBZ0({1.0, 0.0}), 

  sideBZ1({-.5, std::sqrt(3.0)/2});

Region<nDim>            brillouinZone (originBZ,{sideBZ0,sideBZ1});

Material<nDim>          graphene ("graph", brillouinZone);

 

const int               resolution = 10;

Mesh<nDim>              meshK0 (brillouinZone, {0.1,0.1}, {0.3,0.3}, {resolution, resolution});

Mesh<nDim>              meshK1 (brillouinZone, {0.6,0.6}, {0.3,0.3}, {resolution, resolution});


Point<nDim>             diracPoint0(originBZ + 0.25 * sideBZ0 + 0.25 * sideBZ1);

Point<nDim>             diracPoint1(originBZ + 0.75 * sideBZ0 + 0.75 * sideBZ1);

graphene.addBand("elC0", -protonCharge, -1.0, meshK0, [diracPoint0](Point<nDim> k){return std::sqrt(std::pow((k(0)-diracPoint0(0)),2.0)+ std::pow((k(1)-diracPoint0(1)),2.0));});

    

graphene.addBand("elC1", -protonCharge, -1.0, meshK1, [diracPoint1](Point<nDim> k){return std::sqrt(std::pow((k(0)-diracPoint1(0)),2.0)+ std::pow((k(1)-diracPoint1(1)),2.0));});

    

graphene.addBand("elV0", -protonCharge, -1.0, meshK0, [diracPoint0](Point<nDim> k){return -std::sqrt(std::pow((k(0)-diracPoint0(0)),2.0)+ std::pow((k(1)-diracPoint0(1)),2.0));});

    

graphene.addBand("elV1", -protonCharge, -1.0, meshK1, [diracPoint1](Point<nDim> k){return -std::sqrt(std::pow((k(0)-diracPoint1(0)),2.0)+ std::pow((k(1)-diracPoint1(1)),2.0));});


graphene.plot();