Academics

This page is essentially an extended Curriculum Vitae, with details on my activities that would be beyond the scope of a usual CV.


Education

University of Toronto Ph.D. 2026 - Current
  Astronomy and Astrophysics

I began my graduate studies at UofT in September 2026, working with Prof. Hanno Rein on algorithms for N-body codes for the fall and winter terms. Afterwards I will be looking for another supervisor for a summer project before deciding on my thesis supervisor next fall.

University of Toronto H.B.Sc. June 2026
  Astronomy & Physics Specialist, Mathematics Major GPA: 3.98/4.00

As an undergraduate student I attended the University of Toronto in the Astronomy & Physics Specialist program as well as the Mathematics Major program. Below are some of the courses I've taken/am taking that I found interesting, challenging or notable:

Interesting Courses

Awards


Optically Thick Mirror Stars

This is a research project that I've been working on since January 2024. Professors Chris Matzner and David Curtin have been supervising, and I've been working with Franco Cabral, another undergraduate at UofT.
You can find our paper on ArXiv here!
The code for this project is available here on GitHub, in the optically_thick folder.
The project as a whole is an extension of this paper by the previous pair of students under Chris and David's supervison, Isabella and Berkin. They were looking at specifically optically thin mirror stars while Franco and I look at optically thick ones. The first two sections of the optically thin paper provides a good introduction to mirror stars, but I will also give my own simplified version.

A mirror star is essentially just a dense clump of dark matter.
Many explanations of dark matter include introducing new particles, and some of these predict an interaction between multiple dark matter particles in a manner similar to familiar electromagnetism, complete with 'dark photons'. This means that this dark matter can dissipate energy and gravitationally collapse, much like how normal stars form from sparse clouds of gas, entirely invisible to us.
Another part of these theories of dark matter is that there is probably a very very small chance for dark photons and regular matter to interact, as well as regular photons and dark matter. This results in two things:

The way a mirror star aquires matter is maybe like a ghost with a featherduster, theres a very low chance that the mirror star will interact with the sparse dust in space, but once it does, the deep gravitational well of the heavy mirror star traps it.
In our work, we predict what electromagnetic radiation is emitted by the gas and dust inside a mirror star (we call this gas/dust ball a 'nugget'), describing what we would see if we were looking at one. This sets up future work to look in large catalogues of stars and find if we might have detected any already without knowing.
This rest of this section of my website will be about my part of this project: modelling the nugget's structure, and not about Franco's part: turning the nuggets into an observable light spectrum and then comparing with regular stars which you'll have to consult the paper for.

As I mentioned earlier, Isabella and Berkin's project focused on mirror stars that are optically thin while mine and Franco's is about optically thick ones. This distinction is not an incredibly concrete line, but comes from how easy it is for light to travel through the object. In an optically thin object, an individual photon originating at the center is likely to make it all the way out into space without ever bumping into anything. In contrast, such a photon in an optically thick object is almost certain to bounce around many many times before escaping. We quantify this with a number called the optical depth $\tau$, which is distance measured in 'mean free paths' or how far a photon can go on average before scattering. Measuring from far away into the center of an object, $\tau \gg 1$ means optically thick, and $\tau \ll 1$ means optically thin. The optical depth will also be useful later on for deciding where the 'surface' of the nugget is.

We represent the dark-normal matter interaction by how strong the heating is, with the 'heating rate' parameter $\xi$. Physically, $\xi$ is the power delivered to a hydrogen atom in watts (J/s), when surrounded by a mirror star with density equal to the sun's. In our work the value of $\xi$ ranges from $\sim 10^{-15}$ down to $\sim 10^{-26}$.
To simplify things, we assume that the mirror star is much larger than the nugget it surrounds. This allows for the approximation that, as far as the nugget is concerned, the mirror star density is constant and equal to the density at it's center: $\rho_c^\mathrm{MS}$.
We also assume spherical symmetry so we can just focus on radial structure rather than do a full 3d treatment.

The first step in creating a nugget is choosing a mirror star density $\rho_c^\mathrm{MS}$ and heating rate $\xi$ to set up the environment. Then we can the conditions in the center: the temperature and density $T_c$ and $\rho_c$.
The next step is to solve the 'stellar structure equations', which can take many forms. For us they look like $\frac{dP}{dr} = -g\rho$ and $\frac{dP_\mathrm{rad}}{dr}= -4g\rho\frac{P_{\mathrm{rad}}}{P}\nabla_{\mathrm{ad}}$(convective) or $\frac{dP_\mathrm{rad}}{dr}=-\bar\kappa_R\rho\frac{L}{4\pi r^2c}$ (radiative). There are a lot of symbols here which I'll explain somewhat, but the main thing to notice is the two different equations for the derivative of $P_{\mathrm{rad}}$.
$P_{\mathrm{rad}} \propto T^4$ is the radiation pressure and tracks the flow of energy through the nugget. Since each particle in the nugget is being heated slightly by the mirror star, in a stable nugget all that energy has to somehow make its way out into space.
The equation labeled convective is what we use when the dominant form of energy flow is convection. This works very similar to convection in plate tectonics or in a hot pot: hot blobs of stuff rise and bring their energy with them, then they cool and sink back down.
The equation labeled radiative is what we use when light is the dominant energy flow. This is pretty simple: more light is produced closer to the center since its hotter there, and so on average more light goes outwards and takes energy with it.
As for all of the symbols, all of which, other than the speed of light $c$, are functions of the radius $r$: $P$ is the standard pressure, equal to the sum of ideal gas pressure and radiation pressure $P_{\mathrm{rad}}$, which is the pressure specifically due to photons. $g$ is the local gravitational acceleration, for us this is mostly due to the mirror star. $\rho$ is the local density. $\nabla_\mathrm{ad}$ is the 'adabatic temperature gradient' and abstractly, describes the change in temperature of a blob of gas under compression. $\bar\kappa_R$ is the Rossland mean opacity, which is an average opacity over all wavelengths of light and has a complicated equation I won't go into. $L$ is the amount of energy being put into the nugget within a given radius, here due entirely to the mirror star heating but usually from nuclear fusion.
To get a nugget from these, we also need a condition on which equation to use for $\frac{dP_\mathrm{rad}}{dr}$. We use the convective equation when $\nabla_{\mathrm{ad}} \lt \nabla_{\mathrm{rad}}$ and the radiative one otherwise, where $\nabla_{\mathrm{rad}}$ is related to the temperature variation with pressure. This condition is sometimes called the Schwarzschild criterion.
With all this in hand, and the mass conservation equation $dm/dr=4\pi r^2 \rho$, we can convert our initial conditions into $P_c$ and $P_{c,\mathrm{rad}}$ and use a finite difference method to get $P(r),P_\mathrm{rad}(r),m(r)$, stopping when anything gets very close to zero. The result is a radial profile like what I've plotted below. I converted the pressures back into $T$ and $\rho$ since those are more familiar to us and coloured the profiles red or black according to whether it is convective or radiative.

T and rho profiles for a nugget

The dashed blue line in the profile above is labelled 'photosphere', and finding it is the next step in modelling a nugget. The photosphere is roughly the point where the energy of the object, star or nugget, is released. We define it as the radius at which the optical depth starting from space is $\tau \simeq 2/3$, so basically all of the photons emitted at the photosphere escape without scattering. This allows us to approximate the radiation output by the nugget as a blackbody and use the Stefan-Boltzmann law $L_\mathrm{photo}=4\pi\sigma r_\mathrm{photo}^2T_\mathrm{photo}^4.

From energy conservation, we know that the total heating from the mirror star and $L_\mathrm{photo}$ should be equal, but it turns out that this is not the case in general! The plot below shows for a range of $T_c$ and $\rho_c$ the ratio $L_\mathrm{photo}/L_\mathrm{heating}$.

Lphoto/Lheating for rho_c,T_c

Each point in this image is a full nugget solution like shown in the profiles earlier. Notice the large region on the left with no points. There are nuggets at these central conditions, but the photosphere model we use can't find a point with $\tau = 2/3$, even when you go to the very center. In other words, they are opticallly thin! The other thing to notice from this plot is that there's a pretty clear line where $\log_{10}(L_\mathrm{photo}/L_\mathrm{heating})=0$ (I'll call this quantity $L_r$ for (log) luminosity ratio from now on). This corresponds to when the two luminosities are equal which is what we want for energy conservation. So now our job is to find where this line is and we have out physical nuggets.

The first thing you might try is a contour finding library, like ContourPy which is what matplotlib.pyplot.contour() uses. This approach runs into an issue with the part of the contour where $L_r$ jumps straight from very negative (dark blue) to very positive (dark red). This makes the contouring algorithm just skirt around each point, making what should be a straight(ish) line very wiggly. At one point we thought this issue could be fixed by better interpolation, but, at least as far as we could tell, that is not a good solution. Contouring/interpolating also has the downside of only giving you some properties of the nuggets that you can package into a number, not the entire nugget with $P(r),\rho(r), T(r)$ etc.

What we found sucessful was to use a bisection-method root finder on $L_r$ as a function of $\rho_c$. Here we fix $xi, \rho_c^\mathrm{MS}, T_c$ and set a wide range on what $\rho_c$ could be that definitely includes where $L_r=0$. We make use of the fact that $L_r(\rho_c)$ is an increasing function and find the zero crossing with the following process:

  1. Generate a nugget at the center of the $\rho_c$ range and find $L_r$.
  2. If $L_r \lt 0$, set the center of the range to be the new left edge, or if $L_r \gt 0$ instead set it as the new right edge.
  3. Generate another nugget at the center of the new $\rho_c$ range and repeat step 2 until $L_r\approx 0$ to desired accuracy.
There is an additional rule that we have to add: if we can't find the photosphere for a nugget, and so are in the blank area of the $\rho_c, T_c$ plot where $L_r$ is undefined, then treat this as $L_r\lt 0$. As in the plot, the blank region is always to the left of the $L_r=0$ contour, so we want to move to the right if we find ourselves there.
Another caveat: For some values of $T_c$ we may not be able to find an $L_r=0$ solution at all, for example you can see that particularly low $T_c$ nuggets have only $L_r>0$ nuggets. So we must implement another stopping condition to prevent the program from running forever. If the $\rho_c$ range is very small (within about machine epsilon) then we say that there is no solution.

With the bisection method, we can get good, physical nuggets that make sense (The profiles I showed earlier are one of these, where the bold L in the title is in fact $L_r$). For the project we needed nuggets across 7 different $\rho_c^\mathrm{MS}$ and a wide range of $\xi$ and $M$ (corresponding to the points on the $L_r=0$ contour). So, after a lot of computing time, I could present the below plot, where each point is a fully self-consistent nugget!

A big plot of nugget properties across rho_c^MS, xi, M

The color bars at the top apply to each column of subplots, and the $\rho_c^{MS}$ value in the corner of the first column apply to each row. Also plotted in little stars are the optically thin solutions from Isabella and Berkin's work for some comparison.

This is mostly the end of my part of the work, at this point Franco can take all of those nuggets and turn them into spectra, HR diagrams, etc.
If you'd like to follow along somewhat, most of the code I used in this project along with an example Jupyter notebook is available on the Mirror Star Emissions GitHub page.


Quantum Chemistry

This was a summer research position with Prof. Artur Izmaylov through the 2025 CQIQC Summer Undergraduate Research program. I was featured on a CQIQC internal article about the program, which you can read here. I was working on quantum computing for the electronic structure problem. More specifically, my project was to combine the quantum-hardware efficient Q-SENSE method with transcorrelated hamiltonians. Transcorrelated hamiltonians differ from normal quantum mechanics hamiltonians in that they are non-hermetian and have three body terms. The non-hermitian part means that they don't follow the variational principle, which Q-SENSE relies on. This was the main challenge of the project. The 3-body terms mostly just means they make computations longer. Although we did not find an efficient solution by the end of September, I learned a lot about the foundations of quantum computing a variety of optimization techniques for both classical and quantum algorithms, and how to use SSH to run compute-heavy jobs on remote machines.


Gravitational Wave Polarizations ((((WIP))))

This is an active reseach project with Prof. Reed Essick and Jewel Cao. Most of my work was done through UofT's AST425 course: Research Topic in Astronomy. As a result I made, for the culminating examination, a short report describing the motivation, background physics, methods, and results of the project.

The project is titled ''Distinguishing polarizations with the next generation of gravitational wave detectors'' which needs some unpacking:
Current detectors like LIGO have arms that are about 4km long, while those in planning, the 'next generation', are much larger. The 40km Cosmic Explorer or the triangular 10km Einstein Telescope are such proposed detectors.

Polarization is usually thought of in terms of electromagnetic waves/light, but also applies to gravitational waves in a similar way. You can imagine the different GW polarizations in terms of their effect on a stationary ring of masses as they pass through. This is shown in the figure on the left, with the dashed and solid lines representing two different phases of the wave, seperated by half a cycle. As labelled, only the so called 'tensor-plus' and 'tensor-cross' polarizations are permitted by Einsten's theory of general relativity. However, more generic descriptions of gravity, 'beyond-GR' theories, allow for an extra four distinct polarizations. This means that any detection of the non-GR polarizations, usually labelled $x,y,b,\ell$ for c,d,e, and f in the diagram, would prove the existance of physics beyond Einstein's theory, very exciting! Of course the converse is also true, we can constrain these beyond-GR theories by showing that we don't see any extra polarizations where they would predict them. This is to say that the ability to detect GW polarizations, moreso to distinguish between them, will teach us more about the fundamental physics of reality.

Current generation detectors typically operate in the low-frequency regime. For a GW of frequency $f$ and a detector of arm length L, the low-frequency limit applies when $f \ll c/2L := f_{FSR}$. When this is true, the GW amplitude is ≈ constant during the time it takes light to travel down the interferometer arm and back ($2L/c$). This can be seen in the blue dashed-line in the drawing below. Interferometer-based GW detectors like LIGO measure the phase difference between light reflected up and down each detector arm. In the low-frequency limit then, the light experiences the length of the detector arm as about constant. The phase difference between arms can thus be directly taken as an instantaneous measurement of the differential arm length. The GW amplitude follows simply from that. LIGO's 4km arms have $f_{FSR} \sim 37.5$kHz. For typical astrophysical signals of $f \sim 2$kHz or less this is well within the low-frequency regime (Essick et al. 2017).
However, with next generation detectors, their $f_{\rm FSR}$ is comparable to astrophysical signal sources. A detector with 40km arms has $f_{\rm FSR} = 3.75\rm kHz$. As you can see by the red dashed-line in the below drawing, the GW amplitude changes significantly over the time it takes light to travel through the arm. Because of this, we must model the detection process with more care, and hopefully this more complex behaviour allows us to extract polarization information from the GW. Indeed, previous work by Prof. Essick and Maximiliano Isi had found exactly this, including the $b$ and $\ell$ modes which are most difficult to detect.

Essick, R., Vitale, S., & Evans, M. 2017, Physical Review D, 96, doi: 10.1103/physrevd.96.084004



Thanks very much to Douglas R. Woodall for the LaTeXMathML javascript tool used to render MathML equations on this page using LaTeX commands.