--- title: "Indexing conventions" date: "`r format(Sys.time(), '%d %B, %Y')`" output: rmarkdown::html_vignette: toc: true toc_depth: 2 fig_width: 7 fig_height: 3 fig_caption: true vignette: > %\VignetteEngine{knitr::rmarkdown} %\VignetteIndexEntry{Indexing conventions} %\VignetteEncoding{UTF-8} --- ```{r setup, warning=FALSE,echo=FALSE, message=FALSE} suppressPackageStartupMessages(require(terms)) library(dplyr) library(DT) ``` ## Single particle T-matrix The convention is to use - m: multipole order, -n:n - n: multipole degree 1:nmax - q: multipole type, 1 or 2 so for a T-matrix with Nmax=3, we have ```{r tmat, warning=FALSE,echo=FALSE, message=FALSE} indices <- function(Nmax=3, part=1){ un <- seq(1,Nmax) n = do.call(c, lapply(un, function(.n)rep(.n, 2*.n+1))) m = do.call(c, lapply(un, function(.n)seq(-.n,.n))) nn <- expand.grid(n = n, np = n) mm <- expand.grid(m = m, mp = m) d <- rbind(cbind(nn, mm, q=1,qp=1), cbind(nn, mm, q=1,qp=2), cbind(nn, mm, q=2,qp=1), cbind(nn, mm, q=2,qp=2)) dplyr::mutate(d, p = n*(n+1)+m, l = (q - 1)* max(p) + p, i = (part-1) * max(l) + l, pp = np*(np+1)+mp, lp = (qp - 1)* max(pp) + pp, j = (part-1) * max(lp) + lp) } tmat <- indices(3, 1) cat(sprintf("n: %s\nm: %s\nq: %s\n%s elements", paste(range(tmat$n), collapse = '..'), paste(range(tmat$m), collapse = '..'), paste(range(tmat$q), collapse = '..'), nrow(tmat))) tmat$Tr <- 0 tmat$Ti <- 0 terms::display_tmat(tmat) ``` for each block we introduce a combined p-index such that, $$ p(n,m) = n(n+1)+m $$ which here varies as `r sprintf("p: %s", paste(range(tmat$p), collapse = '..'))`, as each block is of dimension `pmax = nmax(nmax+1)+nmax = 3(3+1)+3 = 15`. The whole T-matrix is indexed with a combined l-index such that, $$ l(q,p) = (q-1)p_{max} + p $$ which here gives us, `r sprintf("l: %s", paste(range(tmat$l), collapse = '..'))`. The total T-matrix dimension (along rows/columns) is thus $l_{max}=2\times(nmax(nmax+1)+nmax)=30$. In summary, for a given $N_{max}$ the indices are given by: - $n=1:N_{max}$ - $m=-n:n$ for each n - $q=1:2$ for each pair of (n,m) - $p(n,m) = n(n+1)+m$ - $l(q,p) = (q-1)p_{max} + p$ Given $l$ and $N_{max}$ we can invert these indices as follows, - $p = l - (q-1)l_{max}/2$, giving here, `r (p=1:30 - (rep(1:2, each=15)-1)*30/2)` - $n = \lfloor\sqrt{p}\rfloor$, giving here `r (n = floor(sqrt(p)))` - $m = p - n(n+1)$, giving here `r (m = p-n*(n+1))` ```{r summary, warning=FALSE,echo=FALSE, message=FALSE} show_indices <- subset(tmat, np==1 & mp==0 & qp==1)[c("l","p", "n","m")] display <- t(show_indices[,-1]) colnames(display) <- show_indices$l knitr::kable(display, format = "markdown", padding = 2) ``` ## Multi-particle matrices When combining multiple particles we introduce an additional index $j=1:j_{max}$ tracking the particle number, and a combined index $i$, $$ i = (j-1) l_{max} + l. $$ Knowing the number of particles, $j_{max}$, and the maximum order $n_{max}$, we can unpack the full set of indices with the following formulas, - $j = (i-1) / (i_{max}/j_{max}) + 1$ (integer division) - $l = i - (j-1)\times i_{max}/j_{max}$ (integer division) - $q = 2(l-1)/l_{max} + 1$ (integer division) - $p = l - (q-1)l_{max}/2$ - $n = \lfloor\sqrt{p}\rfloor$ - $m = p - n(n+1)$ ```{r all, warning=FALSE,echo=FALSE, message=FALSE} unpack_indices <- function(nmax=3, jmax=2){ lmax <- 2*(nmax*(nmax+1)+nmax) imax <- jmax*lmax dplyr::mutate(data.frame(i=seq(1, imax)), j = (i-1) %/% (imax/jmax) + 1, l = i - (j-1)*imax %/% jmax, q = (2*(l-1))%/%lmax + 1, p=l - (q-1)*lmax/2, n = floor(sqrt(p)), m = p - n*(n+1) ) } nmax <- 3 display <- unpack_indices(nmax, 2) DT::datatable(display[,c("i",'j','q','l','p','n','m')], rownames = FALSE,filter = 'top', options = list( pageLength = nrow(display), autoWidth = TRUE ) ) %>% formatStyle( 'q',backgroundColor = styleInterval(1, grey(c(0.9,0.8))) ) %>% formatStyle( 'j',backgroundColor = styleInterval(1, blues9[1:2]) ) %>% formatStyle( 'n',backgroundColor = styleInterval(seq_len(nmax-1), hcl(360*seq_len(nmax)/nmax)) ) ```