diff --git a/Examples/Physics_applications/pulsar/Pulsar_scale_RstarPhysical.ipynb b/Examples/Physics_applications/pulsar/Pulsar_scale_RstarPhysical.ipynb
new file mode 100644
index 00000000000..f87d443abb6
--- /dev/null
+++ b/Examples/Physics_applications/pulsar/Pulsar_scale_RstarPhysical.ipynb
@@ -0,0 +1,1392 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Overview\n",
+ "\n",
+ "This a notebook that inspects the results of a WarpX simulation.\n",
+ "\n",
+ "# Instruction\n",
+ "\n",
+ "Enter the path of the data you wish to visualize below. Then execute the cells one by one, by selecting them with your mouse and typing `Shift + Enter`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Import statements\n",
+ "import yt ; yt.funcs.mylog.setLevel(50)\n",
+ "import numpy as np\n",
+ "import scipy.constants as scc\n",
+ "import matplotlib.pyplot as plt\n",
+ "%matplotlib notebook"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#Define the Physical Constants, normalizations, and the scale-down parameter, r_scale, for the pulsar. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [],
+ "source": [
+ "######################\n",
+ "# physical constants #\n",
+ "######################\n",
+ "c = 299792458.0 # speed of light \n",
+ "q_e = 1.602176634e-19 # elementary charge\n",
+ "me=9.10938356*np.power(10.,-31) # electron mass\n",
+ "epsilon=8.8541878128*np.power(10.,-12) # permittivity of free space\n",
+ "mu_o = 4*3.14*1e-7 # permeability\n",
+ "pi = 3.14159265358979323846\n",
+ "SolarMass = 2e30\n",
+ "G = 6.674e-11 # gravitational constant\n",
+ "\n",
+ "#############################################################################\n",
+ "# Parameters for a real Pulsar #\n",
+ "# (Table 7 of J.Petri's article on Theory of Pulsar Magnetosphere and Wind) #\n",
+ "#############################################################################\n",
+ "Omega_real = 6283\n",
+ "B_real = 7.4E4\n",
+ "R_real = 12000\n",
+ "n_real = 6.9e16\n",
+ "omega_pe_real = (n_real*q_e*q_e/(me*epsilon))**0.5 #plasma frequency\n",
+ "SkinDepth_real = c/omega_pe_real \n",
+ "Mstar = 1.4*SolarMass\n",
+ "Rstar_skinDepth_real = 6e5\n",
+ "\n",
+ "##################\n",
+ "# Normalizations #\n",
+ "##################\n",
+ "Rstar_skinDepth = 6e0 # Ratio of radius of star to the skin Depth \n",
+ " # For a real star, this ratio is 6e5\n",
+ "exponent = np.arange(0,6,1) \n",
+ "Factor = np.array(10**exponent)\n",
+ "Rstar_skinDepth = np.array(6*Factor) \n",
+ "\n",
+ "RLC_Rstar = 4 # Ratio of light cylinder (where the particle speed ~ c) to Rstar\n",
+ " # For a pulsar with 1ms period, this ratio is 4. \n",
+ " # i.e., This ratio sets the omega value, since Omega*RLC = c\n",
+ "\n",
+ "# Choose skindepth as the free parameter for a choice of normalizations given above\n",
+ "# The skin depth below is computed from the number density for a real pulsar\n",
+ "# Keeping the SkinDepth constant across all the scales in our scaling study\n",
+ "#SkinDepth = 0.02\n",
+ "\n",
+ "# Since skin depth is maintained across the scales, and RLC/Rstar is also maintained \n",
+ "# lets define the decrease in the scale by comparing the value of \n",
+ "# (Rstar/skinDepth)/(Rstar_real/skinDepth_real)\n",
+ "#r_scale = Rstar_skinDepth/Rstar_skinDepth_real\n",
+ "\n",
+ "Rstar = np.ones(6)*12000\n",
+ "SkinDepth = Rstar/Rstar_skinDepth\n",
+ "r_scale = Rstar_skinDepth_real/Rstar_skinDepth"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "##################################################################\n",
+ "# Derive other physical parameters from the above normalizations #\n",
+ "##################################################################\n",
+ "\n",
+ "# 1. Lorentz Boost (dimensionless) #\n",
+ "# Note that in Alex Chen's paper, gamma_o ~ (1/4)*normalized_values.\n",
+ "# Instead here we have pi/2, since that leads to the closes gamma_o \n",
+ "# value for a real 1ms pulsar. \n",
+ "gamma_o = (pi/2)*(Rstar_skinDepth)**2/RLC_Rstar \n",
+ "\n",
+ "\n",
+ "gamma_real = (pi/2)*6e5**2/RLC_Rstar;\n",
+ "gamma_scaling = gamma_o/(gamma_real) # This is to see how the gamma value \n",
+ " # decreases due to decrease in the ratio of R_star to skin depth\n",
+ "\n",
+ "\n",
+ "\n",
+ "# 3. Light cylinder location (m)\n",
+ "RLC = Rstar*RLC_Rstar\n",
+ "# 4. Angular Frequency (rad/s)\n",
+ "# Omega remains constant\n",
+ "Omega = c/RLC\n",
+ "# 5. Period (s)\n",
+ "# Period remains constant\n",
+ "Period = 2*3.14/Omega\n",
+ "# Moment of inertia for a sphere = (2/5)MR^2 (kg.m^2)\n",
+ "# Note that when the Rstar is scaled by r_scale, \n",
+ "# Mstar decreases as r_scale^3. Thus Mstar*r_scale**3 is the \n",
+ "# mass of the scaled down star.\n",
+ "# I remains constant across all scales\n",
+ "I = (2/5)*(Mstar)*Rstar**2\n",
+ "# 6. Rotation induced potential drop from pote to equator (V)\n",
+ "# Reference: Alex Chen's 2014 paper\n",
+ "# Scales as 1/r_scale**2\n",
+ "phi_o = gamma_o * (me/q_e) * c**2\n",
+ "\n",
+ "# Braking is the rate of slow-down of the spin. \n",
+ "# It is not relevant for the scaling. \n",
+ "# However, 1e-15 is the P_dot for a pulsar with P=1s\n",
+ "# and the rate of slowdown decreases proportional to the period. \n",
+ "# So we were to compare two stars with same radius, but different Omega\n",
+ "# then we can use Braking to determine the magnetic field strength at the surface as follows\n",
+ "# Bo = (3*mu_o*c*c*c/(32*pi*pi*pi))**0.5 * (I*Braking*Period)**0.5/(Rstar**3) \n",
+ "# (Reference : Table 7 of Jetri's article)\n",
+ "# Remains constant across all scales\n",
+ "Braking = 1e-15*Period\n",
+ "\n",
+ "# 7. Magnetic field strength (Tesla)\n",
+ "# Bo decreases as ~ 1/r_scale**2\n",
+ "Bo = phi_o/(Rstar*Rstar*Omega)\n",
+ "\n",
+ "# 8. Volume charge density (C/m^3) for uniform magnetization insize the star \n",
+ "# Refer to Table 7 of Petri's article \n",
+ "# Since Omega increases as r_scale and Bo decreases as r_scale\n",
+ "# The product of Omega*Bo remains constant across all scales. \n",
+ "# Thus, rho_e decreases as (1/r_scale**2)\n",
+ "rho_e = 2*epsilon*Omega*Bo #(Not adding the negative sign here)\n",
+ "\n",
+ "# 9. Electron number density (#/m^3)\n",
+ "# ne decreases as (1/r_scale**2)\n",
+ "ne = rho_e/q_e\n",
+ "# 9a. plasma frequency \n",
+ "# decreases as (1/r_scale)\n",
+ "omega_pe = (ne*q_e*q_e/(me*epsilon))**0.5 #plasma frequency\n",
+ "# 10. Magnetic moment (Am^2)\n",
+ "# decreases as (1/r_scale**2)\n",
+ "magnetic_moment = Bo*Rstar*Rstar*Rstar*4*pi/(mu_o)\n",
+ "# 11. E-field (V/m)\n",
+ "# Efield decreases as (1/r_scale**2)\n",
+ "E = Omega*Bo*Rstar\n",
+ "\n",
+ "\n",
+ "#########################################\n",
+ "# How do the energies and forces scale? #\n",
+ "#########################################\n",
+ "# 12. Magnetic Energy (J)\n",
+ "# Magnetic energy decreases as (1/r_scale**4)\n",
+ "magnetic_energy = (4*pi/3)*Bo**2*Rstar**3/(2*mu_o)\n",
+ "\n",
+ "# 13. Gravitational Potential Energy (J)\n",
+ "# G.pot energy remains constant \n",
+ "GP_energy = (3/5)*G*Mstar*Mstar/(Rstar)\n",
+ "\n",
+ "# 14. Gravitational to Electric force (dimensionless)\n",
+ "# This ratio increases as r_scale**2\n",
+ "G_EForce = G*Mstar*me/(Rstar*Rstar*q_e*E)\n",
+ "\n",
+ "# 15. Rotational kinetic energy \n",
+ "# Rot. KE remains constant\n",
+ "rotational_KE = (1/2)*I*Omega**2\n",
+ "\n",
+ "# 16. From (12) and (13), we know the B.energy scales as (1/r_scale**4) and GP energy is constant \n",
+ "# Thus the ratio of GP_energy and B_energy increases as r_scale**4\n",
+ "GB_energy_ratio = GP_energy/magnetic_energy\n",
+ "\n",
+ "# 17. Rate of change of Omega, or angular acceleration decreases as 1/r_scale**4\n",
+ "Omega_dot = Bo*Bo*Rstar**6*Omega**3/(I) * (32*pi/(3*mu_o*c**3))* (1/(4*pi*pi))\n",
+ "\n",
+ "# 18. Torque decreases as 1/r_scale**4\n",
+ "Torque = I * Omega_dot\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Input parameters for WarpX for geometry scaled down by r_scale = [1.e-05 1.e-04 1.e-03 1.e-02 1.e-01 1.e+00]\n",
+ "Lorentz factor, (gamma_o) = [1.41371669e+01 1.41371669e+03 1.41371669e+05 1.41371669e+07\n",
+ " 1.41371669e+09 1.41371669e+11]\n",
+ "Rstar (m) [12000. 12000. 12000. 12000. 12000. 12000.]\n",
+ "Omega (rad/s) [6245.67620833 6245.67620833 6245.67620833 6245.67620833 6245.67620833\n",
+ " 6245.67620833]\n",
+ "Bo (Tesla) [8.03230942e-06 8.03230942e-04 8.03230942e-02 8.03230942e+00\n",
+ " 8.03230942e+02 8.03230942e+04]\n",
+ "ne (/m^3) [5.54482989e+06 5.54482989e+08 5.54482989e+10 5.54482989e+12\n",
+ " 5.54482989e+14 5.54482989e+16]\n",
+ "Size of the domain, (m) [360000. 360000. 360000. 360000. 360000. 360000.]\n",
+ "Minimum cell size (m) [2.e+03 2.e+02 2.e+01 2.e+00 2.e-01 2.e-02]\n",
+ "timestep (s) [3.76386776e-06 3.76386776e-07 3.76386776e-08 3.76386776e-09\n",
+ " 3.76386776e-10 3.76386776e-11]\n",
+ "Numver of cells assuming unif. grid, [1.8e+02 1.8e+03 1.8e+04 1.8e+05 1.8e+06 1.8e+07]\n"
+ ]
+ }
+ ],
+ "source": [
+ "############################################################\n",
+ "# Print all the values that will be used as input in WarpX #\n",
+ "############################################################\n",
+ "print(\"Input parameters for WarpX for geometry scaled down by r_scale = \", Rstar_skinDepth/Rstar_skinDepth_real)\n",
+ "print(\"Lorentz factor, (gamma_o) = \", gamma_o)\n",
+ "print(\"Rstar (m)\", Rstar)\n",
+ "print(\"Omega (rad/s)\", Omega)\n",
+ "print(\"Bo (Tesla)\", Bo)\n",
+ "print(\"ne (/m^3)\", ne)\n",
+ "print(\"Size of the domain, (m)\", 30*Rstar)\n",
+ "print(\"Minimum cell size (m)\", SkinDepth)\n",
+ "print(\"timestep (s)\", 0.5*omega_pe**-1) # Or may be cfl criterion\n",
+ "print(\"Numver of cells assuming unif. grid, \", 30*Rstar/SkinDepth)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Gravitational force to E-force : [1.22562947e-02 1.22562947e-04 1.22562947e-06 1.22562947e-08\n",
+ " 1.22562947e-10 1.22562947e-12]\n",
+ "Gravitational energy to B-energy : [1.40727411e+38 1.40727411e+34 1.40727411e+30 1.40727411e+26\n",
+ " 1.40727411e+22 1.40727411e+18]\n",
+ "B energy, (J) [1.85906071e+08 1.85906071e+12 1.85906071e+16 1.85906071e+20\n",
+ " 1.85906071e+24 1.85906071e+28]\n",
+ "Gravitational potential energy, (J) [2.616208e+46 2.616208e+46 2.616208e+46 2.616208e+46 2.616208e+46\n",
+ " 2.616208e+46]\n",
+ "Rotational Kinetic Energy (J) [3.14564313e+45 3.14564313e+45 3.14564313e+45 3.14564313e+45\n",
+ " 3.14564313e+45 3.14564313e+45]\n"
+ ]
+ }
+ ],
+ "source": [
+ "#############################################################\n",
+ "# Print ratios of G.Pot.Energy/B_energy and G.Force/E_force #\n",
+ "#############################################################\n",
+ "print(\"Gravitational force to E-force : \", G_EForce)\n",
+ "print(\"Gravitational energy to B-energy : \",GB_energy_ratio)\n",
+ "\n",
+ "\n",
+ "# Print dimensional values of energies\n",
+ "print(\"B energy, (J)\",magnetic_energy);\n",
+ "print(\"Gravitational potential energy, (J)\", GP_energy)\n",
+ "print(\"Rotational Kinetic Energy (J)\", rotational_KE )\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "application/javascript": [
+ "/* Put everything inside the global mpl namespace */\n",
+ "window.mpl = {};\n",
+ "\n",
+ "\n",
+ "mpl.get_websocket_type = function() {\n",
+ " if (typeof(WebSocket) !== 'undefined') {\n",
+ " return WebSocket;\n",
+ " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
+ " return MozWebSocket;\n",
+ " } else {\n",
+ " alert('Your browser does not have WebSocket support. ' +\n",
+ " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
+ " 'Firefox 4 and 5 are also supported but you ' +\n",
+ " 'have to enable WebSockets in about:config.');\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
+ " this.id = figure_id;\n",
+ "\n",
+ " this.ws = websocket;\n",
+ "\n",
+ " this.supports_binary = (this.ws.binaryType != undefined);\n",
+ "\n",
+ " if (!this.supports_binary) {\n",
+ " var warnings = document.getElementById(\"mpl-warnings\");\n",
+ " if (warnings) {\n",
+ " warnings.style.display = 'block';\n",
+ " warnings.textContent = (\n",
+ " \"This browser does not support binary websocket messages. \" +\n",
+ " \"Performance may be slow.\");\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " this.imageObj = new Image();\n",
+ "\n",
+ " this.context = undefined;\n",
+ " this.message = undefined;\n",
+ " this.canvas = undefined;\n",
+ " this.rubberband_canvas = undefined;\n",
+ " this.rubberband_context = undefined;\n",
+ " this.format_dropdown = undefined;\n",
+ "\n",
+ " this.image_mode = 'full';\n",
+ "\n",
+ " this.root = $('
');\n",
+ " this._root_extra_style(this.root)\n",
+ " this.root.attr('style', 'display: inline-block');\n",
+ "\n",
+ " $(parent_element).append(this.root);\n",
+ "\n",
+ " this._init_header(this);\n",
+ " this._init_canvas(this);\n",
+ " this._init_toolbar(this);\n",
+ "\n",
+ " var fig = this;\n",
+ "\n",
+ " this.waiting = false;\n",
+ "\n",
+ " this.ws.onopen = function () {\n",
+ " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
+ " fig.send_message(\"send_image_mode\", {});\n",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " }\n",
+ "\n",
+ " this.imageObj.onload = function() {\n",
+ " if (fig.image_mode == 'full') {\n",
+ " // Full images could contain transparency (where diff images\n",
+ " // almost always do), so we need to clear the canvas so that\n",
+ " // there is no ghosting.\n",
+ " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
+ " }\n",
+ " fig.context.drawImage(fig.imageObj, 0, 0);\n",
+ " };\n",
+ "\n",
+ " this.imageObj.onunload = function() {\n",
+ " fig.ws.close();\n",
+ " }\n",
+ "\n",
+ " this.ws.onmessage = this._make_on_message_function(this);\n",
+ "\n",
+ " this.ondownload = ondownload;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_header = function() {\n",
+ " var titlebar = $(\n",
+ " '');\n",
+ " var titletext = $(\n",
+ " '');\n",
+ " titlebar.append(titletext)\n",
+ " this.root.append(titlebar);\n",
+ " this.header = titletext[0];\n",
+ "}\n",
+ "\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
+ "\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
+ "\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_canvas = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var canvas_div = $('');\n",
+ "\n",
+ " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
+ "\n",
+ " function canvas_keyboard_event(event) {\n",
+ " return fig.key_event(event, event['data']);\n",
+ " }\n",
+ "\n",
+ " canvas_div.keydown('key_press', canvas_keyboard_event);\n",
+ " canvas_div.keyup('key_release', canvas_keyboard_event);\n",
+ " this.canvas_div = canvas_div\n",
+ " this._canvas_extra_style(canvas_div)\n",
+ " this.root.append(canvas_div);\n",
+ "\n",
+ " var canvas = $('');\n",
+ " canvas.addClass('mpl-canvas');\n",
+ " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
+ "\n",
+ " this.canvas = canvas[0];\n",
+ " this.context = canvas[0].getContext(\"2d\");\n",
+ "\n",
+ " var backingStore = this.context.backingStorePixelRatio ||\n",
+ "\tthis.context.webkitBackingStorePixelRatio ||\n",
+ "\tthis.context.mozBackingStorePixelRatio ||\n",
+ "\tthis.context.msBackingStorePixelRatio ||\n",
+ "\tthis.context.oBackingStorePixelRatio ||\n",
+ "\tthis.context.backingStorePixelRatio || 1;\n",
+ "\n",
+ " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
+ "\n",
+ " var rubberband = $('');\n",
+ " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
+ "\n",
+ " var pass_mouse_events = true;\n",
+ "\n",
+ " canvas_div.resizable({\n",
+ " start: function(event, ui) {\n",
+ " pass_mouse_events = false;\n",
+ " },\n",
+ " resize: function(event, ui) {\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " stop: function(event, ui) {\n",
+ " pass_mouse_events = true;\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " });\n",
+ "\n",
+ " function mouse_event_fn(event) {\n",
+ " if (pass_mouse_events)\n",
+ " return fig.mouse_event(event, event['data']);\n",
+ " }\n",
+ "\n",
+ " rubberband.mousedown('button_press', mouse_event_fn);\n",
+ " rubberband.mouseup('button_release', mouse_event_fn);\n",
+ " // Throttle sequential mouse events to 1 every 20ms.\n",
+ " rubberband.mousemove('motion_notify', mouse_event_fn);\n",
+ "\n",
+ " rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
+ " rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
+ "\n",
+ " canvas_div.on(\"wheel\", function (event) {\n",
+ " event = event.originalEvent;\n",
+ " event['data'] = 'scroll'\n",
+ " if (event.deltaY < 0) {\n",
+ " event.step = 1;\n",
+ " } else {\n",
+ " event.step = -1;\n",
+ " }\n",
+ " mouse_event_fn(event);\n",
+ " });\n",
+ "\n",
+ " canvas_div.append(canvas);\n",
+ " canvas_div.append(rubberband);\n",
+ "\n",
+ " this.rubberband = rubberband;\n",
+ " this.rubberband_canvas = rubberband[0];\n",
+ " this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
+ " this.rubberband_context.strokeStyle = \"#000000\";\n",
+ "\n",
+ " this._resize_canvas = function(width, height) {\n",
+ " // Keep the size of the canvas, canvas container, and rubber band\n",
+ " // canvas in synch.\n",
+ " canvas_div.css('width', width)\n",
+ " canvas_div.css('height', height)\n",
+ "\n",
+ " canvas.attr('width', width * mpl.ratio);\n",
+ " canvas.attr('height', height * mpl.ratio);\n",
+ " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
+ "\n",
+ " rubberband.attr('width', width);\n",
+ " rubberband.attr('height', height);\n",
+ " }\n",
+ "\n",
+ " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
+ " // upon first draw.\n",
+ " this._resize_canvas(600, 600);\n",
+ "\n",
+ " // Disable right mouse context menu.\n",
+ " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
+ " return false;\n",
+ " });\n",
+ "\n",
+ " function set_focus () {\n",
+ " canvas.focus();\n",
+ " canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " window.setTimeout(set_focus, 100);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_toolbar = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var nav_element = $('');\n",
+ " nav_element.attr('style', 'width: 100%');\n",
+ " this.root.append(nav_element);\n",
+ "\n",
+ " // Define a callback function for later on.\n",
+ " function toolbar_event(event) {\n",
+ " return fig.toolbar_button_onclick(event['data']);\n",
+ " }\n",
+ " function toolbar_mouse_event(event) {\n",
+ " return fig.toolbar_button_onmouseover(event['data']);\n",
+ " }\n",
+ "\n",
+ " for(var toolbar_ind in mpl.toolbar_items) {\n",
+ " var name = mpl.toolbar_items[toolbar_ind][0];\n",
+ " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
+ " var image = mpl.toolbar_items[toolbar_ind][2];\n",
+ " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
+ "\n",
+ " if (!name) {\n",
+ " // put a spacer in here.\n",
+ " continue;\n",
+ " }\n",
+ " var button = $('');\n",
+ " button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
+ " 'ui-button-icon-only');\n",
+ " button.attr('role', 'button');\n",
+ " button.attr('aria-disabled', 'false');\n",
+ " button.click(method_name, toolbar_event);\n",
+ " button.mouseover(tooltip, toolbar_mouse_event);\n",
+ "\n",
+ " var icon_img = $('');\n",
+ " icon_img.addClass('ui-button-icon-primary ui-icon');\n",
+ " icon_img.addClass(image);\n",
+ " icon_img.addClass('ui-corner-all');\n",
+ "\n",
+ " var tooltip_span = $('');\n",
+ " tooltip_span.addClass('ui-button-text');\n",
+ " tooltip_span.html(tooltip);\n",
+ "\n",
+ " button.append(icon_img);\n",
+ " button.append(tooltip_span);\n",
+ "\n",
+ " nav_element.append(button);\n",
+ " }\n",
+ "\n",
+ " var fmt_picker_span = $('');\n",
+ "\n",
+ " var fmt_picker = $('');\n",
+ " fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
+ " fmt_picker_span.append(fmt_picker);\n",
+ " nav_element.append(fmt_picker_span);\n",
+ " this.format_dropdown = fmt_picker[0];\n",
+ "\n",
+ " for (var ind in mpl.extensions) {\n",
+ " var fmt = mpl.extensions[ind];\n",
+ " var option = $(\n",
+ " '', {selected: fmt === mpl.default_extension}).html(fmt);\n",
+ " fmt_picker.append(option);\n",
+ " }\n",
+ "\n",
+ " // Add hover states to the ui-buttons\n",
+ " $( \".ui-button\" ).hover(\n",
+ " function() { $(this).addClass(\"ui-state-hover\");},\n",
+ " function() { $(this).removeClass(\"ui-state-hover\");}\n",
+ " );\n",
+ "\n",
+ " var status_bar = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
+ " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
+ " // which will in turn request a refresh of the image.\n",
+ " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_message = function(type, properties) {\n",
+ " properties['type'] = type;\n",
+ " properties['figure_id'] = this.id;\n",
+ " this.ws.send(JSON.stringify(properties));\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_draw_message = function() {\n",
+ " if (!this.waiting) {\n",
+ " this.waiting = true;\n",
+ " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " var format_dropdown = fig.format_dropdown;\n",
+ " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
+ " fig.ondownload(fig, format);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
+ " var size = msg['size'];\n",
+ " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
+ " fig._resize_canvas(size[0], size[1]);\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
+ " var x0 = msg['x0'] / mpl.ratio;\n",
+ " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
+ " var x1 = msg['x1'] / mpl.ratio;\n",
+ " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
+ " x0 = Math.floor(x0) + 0.5;\n",
+ " y0 = Math.floor(y0) + 0.5;\n",
+ " x1 = Math.floor(x1) + 0.5;\n",
+ " y1 = Math.floor(y1) + 0.5;\n",
+ " var min_x = Math.min(x0, x1);\n",
+ " var min_y = Math.min(y0, y1);\n",
+ " var width = Math.abs(x1 - x0);\n",
+ " var height = Math.abs(y1 - y0);\n",
+ "\n",
+ " fig.rubberband_context.clearRect(\n",
+ " 0, 0, fig.canvas.width / mpl.ratio, fig.canvas.height / mpl.ratio);\n",
+ "\n",
+ " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
+ " // Updates the figure title.\n",
+ " fig.header.textContent = msg['label'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
+ " var cursor = msg['cursor'];\n",
+ " switch(cursor)\n",
+ " {\n",
+ " case 0:\n",
+ " cursor = 'pointer';\n",
+ " break;\n",
+ " case 1:\n",
+ " cursor = 'default';\n",
+ " break;\n",
+ " case 2:\n",
+ " cursor = 'crosshair';\n",
+ " break;\n",
+ " case 3:\n",
+ " cursor = 'move';\n",
+ " break;\n",
+ " }\n",
+ " fig.rubberband_canvas.style.cursor = cursor;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
+ " fig.message.textContent = msg['message'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
+ " // Request the server to send over a new figure.\n",
+ " fig.send_draw_message();\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
+ " fig.image_mode = msg['mode'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.updated_canvas_event = function() {\n",
+ " // Called whenever the canvas gets updated.\n",
+ " this.send_message(\"ack\", {});\n",
+ "}\n",
+ "\n",
+ "// A function to construct a web socket function for onmessage handling.\n",
+ "// Called in the figure constructor.\n",
+ "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
+ " return function socket_on_message(evt) {\n",
+ " if (evt.data instanceof Blob) {\n",
+ " /* FIXME: We get \"Resource interpreted as Image but\n",
+ " * transferred with MIME type text/plain:\" errors on\n",
+ " * Chrome. But how to set the MIME type? It doesn't seem\n",
+ " * to be part of the websocket stream */\n",
+ " evt.data.type = \"image/png\";\n",
+ "\n",
+ " /* Free the memory for the previous frames */\n",
+ " if (fig.imageObj.src) {\n",
+ " (window.URL || window.webkitURL).revokeObjectURL(\n",
+ " fig.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
+ " evt.data);\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
+ " fig.imageObj.src = evt.data;\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var msg = JSON.parse(evt.data);\n",
+ " var msg_type = msg['type'];\n",
+ "\n",
+ " // Call the \"handle_{type}\" callback, which takes\n",
+ " // the figure and JSON message as its only arguments.\n",
+ " try {\n",
+ " var callback = fig[\"handle_\" + msg_type];\n",
+ " } catch (e) {\n",
+ " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " if (callback) {\n",
+ " try {\n",
+ " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
+ " callback(fig, msg);\n",
+ " } catch (e) {\n",
+ " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
+ " }\n",
+ " }\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
+ "mpl.findpos = function(e) {\n",
+ " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
+ " var targ;\n",
+ " if (!e)\n",
+ " e = window.event;\n",
+ " if (e.target)\n",
+ " targ = e.target;\n",
+ " else if (e.srcElement)\n",
+ " targ = e.srcElement;\n",
+ " if (targ.nodeType == 3) // defeat Safari bug\n",
+ " targ = targ.parentNode;\n",
+ "\n",
+ " // jQuery normalizes the pageX and pageY\n",
+ " // pageX,Y are the mouse positions relative to the document\n",
+ " // offset() returns the position of the element relative to the document\n",
+ " var x = e.pageX - $(targ).offset().left;\n",
+ " var y = e.pageY - $(targ).offset().top;\n",
+ "\n",
+ " return {\"x\": x, \"y\": y};\n",
+ "};\n",
+ "\n",
+ "/*\n",
+ " * return a copy of an object with only non-object keys\n",
+ " * we need this to avoid circular references\n",
+ " * http://stackoverflow.com/a/24161582/3208463\n",
+ " */\n",
+ "function simpleKeys (original) {\n",
+ " return Object.keys(original).reduce(function (obj, key) {\n",
+ " if (typeof original[key] !== 'object')\n",
+ " obj[key] = original[key]\n",
+ " return obj;\n",
+ " }, {});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.mouse_event = function(event, name) {\n",
+ " var canvas_pos = mpl.findpos(event)\n",
+ "\n",
+ " if (name === 'button_press')\n",
+ " {\n",
+ " this.canvas.focus();\n",
+ " this.canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " var x = canvas_pos.x * mpl.ratio;\n",
+ " var y = canvas_pos.y * mpl.ratio;\n",
+ "\n",
+ " this.send_message(name, {x: x, y: y, button: event.button,\n",
+ " step: event.step,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ "\n",
+ " /* This prevents the web browser from automatically changing to\n",
+ " * the text insertion cursor when the button is pressed. We want\n",
+ " * to control all of the cursor setting manually through the\n",
+ " * 'cursor' event from matplotlib */\n",
+ " event.preventDefault();\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " // Handle any extra behaviour associated with a key event\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.key_event = function(event, name) {\n",
+ "\n",
+ " // Prevent repeat events\n",
+ " if (name == 'key_press')\n",
+ " {\n",
+ " if (event.which === this._key)\n",
+ " return;\n",
+ " else\n",
+ " this._key = event.which;\n",
+ " }\n",
+ " if (name == 'key_release')\n",
+ " this._key = null;\n",
+ "\n",
+ " var value = '';\n",
+ " if (event.ctrlKey && event.which != 17)\n",
+ " value += \"ctrl+\";\n",
+ " if (event.altKey && event.which != 18)\n",
+ " value += \"alt+\";\n",
+ " if (event.shiftKey && event.which != 16)\n",
+ " value += \"shift+\";\n",
+ "\n",
+ " value += 'k';\n",
+ " value += event.which.toString();\n",
+ "\n",
+ " this._key_event_extra(event, name);\n",
+ "\n",
+ " this.send_message(name, {key: value,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
+ " if (name == 'download') {\n",
+ " this.handle_save(this, null);\n",
+ " } else {\n",
+ " this.send_message(\"toolbar_button\", {name: name});\n",
+ " }\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
+ " this.message.textContent = tooltip;\n",
+ "};\n",
+ "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
+ "\n",
+ "mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n",
+ "\n",
+ "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
+ " // Create a \"websocket\"-like object which calls the given IPython comm\n",
+ " // object with the appropriate methods. Currently this is a non binary\n",
+ " // socket, so there is still some room for performance tuning.\n",
+ " var ws = {};\n",
+ "\n",
+ " ws.close = function() {\n",
+ " comm.close()\n",
+ " };\n",
+ " ws.send = function(m) {\n",
+ " //console.log('sending', m);\n",
+ " comm.send(m);\n",
+ " };\n",
+ " // Register the callback with on_msg.\n",
+ " comm.on_msg(function(msg) {\n",
+ " //console.log('receiving', msg['content']['data'], msg);\n",
+ " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
+ " ws.onmessage(msg['content']['data'])\n",
+ " });\n",
+ " return ws;\n",
+ "}\n",
+ "\n",
+ "mpl.mpl_figure_comm = function(comm, msg) {\n",
+ " // This is the function which gets called when the mpl process\n",
+ " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
+ "\n",
+ " var id = msg.content.data.id;\n",
+ " // Get hold of the div created by the display call when the Comm\n",
+ " // socket was opened in Python.\n",
+ " var element = $(\"#\" + id);\n",
+ " var ws_proxy = comm_websocket_adapter(comm)\n",
+ "\n",
+ " function ondownload(figure, format) {\n",
+ " window.open(figure.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " var fig = new mpl.figure(id, ws_proxy,\n",
+ " ondownload,\n",
+ " element.get(0));\n",
+ "\n",
+ " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
+ " // web socket which is closed, not our websocket->open comm proxy.\n",
+ " ws_proxy.onopen();\n",
+ "\n",
+ " fig.parent_element = element.get(0);\n",
+ " fig.cell_info = mpl.find_output_cell(\"\");\n",
+ " if (!fig.cell_info) {\n",
+ " console.error(\"Failed to find cell for figure\", id, fig);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var output_index = fig.cell_info[2]\n",
+ " var cell = fig.cell_info[0];\n",
+ "\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.handle_close = function(fig, msg) {\n",
+ " var width = fig.canvas.width/mpl.ratio\n",
+ " fig.root.unbind('remove')\n",
+ "\n",
+ " // Update the output cell to use the data from the current canvas.\n",
+ " fig.push_to_output();\n",
+ " var dataURL = fig.canvas.toDataURL();\n",
+ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
+ " // the notebook keyboard shortcuts fail.\n",
+ " IPython.keyboard_manager.enable()\n",
+ " $(fig.parent_element).html('
');\n",
+ " fig.close_ws(fig, msg);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.close_ws = function(fig, msg){\n",
+ " fig.send_message('closing', msg);\n",
+ " // fig.ws.close()\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
+ " // Turn the data on the canvas into data in the output cell.\n",
+ " var width = this.canvas.width/mpl.ratio\n",
+ " var dataURL = this.canvas.toDataURL();\n",
+ " this.cell_info[1]['text/html'] = '
';\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.updated_canvas_event = function() {\n",
+ " // Tell IPython that the notebook contents must change.\n",
+ " IPython.notebook.set_dirty(true);\n",
+ " this.send_message(\"ack\", {});\n",
+ " var fig = this;\n",
+ " // Wait a second, then push the new image to the DOM so\n",
+ " // that it is saved nicely (might be nice to debounce this).\n",
+ " setTimeout(function () { fig.push_to_output() }, 1000);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_toolbar = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var nav_element = $('');\n",
+ " nav_element.attr('style', 'width: 100%');\n",
+ " this.root.append(nav_element);\n",
+ "\n",
+ " // Define a callback function for later on.\n",
+ " function toolbar_event(event) {\n",
+ " return fig.toolbar_button_onclick(event['data']);\n",
+ " }\n",
+ " function toolbar_mouse_event(event) {\n",
+ " return fig.toolbar_button_onmouseover(event['data']);\n",
+ " }\n",
+ "\n",
+ " for(var toolbar_ind in mpl.toolbar_items){\n",
+ " var name = mpl.toolbar_items[toolbar_ind][0];\n",
+ " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
+ " var image = mpl.toolbar_items[toolbar_ind][2];\n",
+ " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
+ "\n",
+ " if (!name) { continue; };\n",
+ "\n",
+ " var button = $('');\n",
+ " button.click(method_name, toolbar_event);\n",
+ " button.mouseover(tooltip, toolbar_mouse_event);\n",
+ " nav_element.append(button);\n",
+ " }\n",
+ "\n",
+ " // Add the status bar.\n",
+ " var status_bar = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "\n",
+ " // Add the close button to the window.\n",
+ " var buttongrp = $('');\n",
+ " var button = $('');\n",
+ " button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
+ " button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
+ " buttongrp.append(button);\n",
+ " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
+ " titlebar.prepend(buttongrp);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._root_extra_style = function(el){\n",
+ " var fig = this\n",
+ " el.on(\"remove\", function(){\n",
+ "\tfig.close_ws(fig, {});\n",
+ " });\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._canvas_extra_style = function(el){\n",
+ " // this is important to make the div 'focusable\n",
+ " el.attr('tabindex', 0)\n",
+ " // reach out to IPython and tell the keyboard manager to turn it's self\n",
+ " // off when our div gets focus\n",
+ "\n",
+ " // location in version 3\n",
+ " if (IPython.notebook.keyboard_manager) {\n",
+ " IPython.notebook.keyboard_manager.register_events(el);\n",
+ " }\n",
+ " else {\n",
+ " // location in version 2\n",
+ " IPython.keyboard_manager.register_events(el);\n",
+ " }\n",
+ "\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " var manager = IPython.notebook.keyboard_manager;\n",
+ " if (!manager)\n",
+ " manager = IPython.keyboard_manager;\n",
+ "\n",
+ " // Check for shift+enter\n",
+ " if (event.shiftKey && event.which == 13) {\n",
+ " this.canvas_div.blur();\n",
+ " // select the cell after this one\n",
+ " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
+ " IPython.notebook.select(index + 1);\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " fig.ondownload(fig, null);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.find_output_cell = function(html_output) {\n",
+ " // Return the cell and output element which can be found *uniquely* in the notebook.\n",
+ " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
+ " // IPython event is triggered only after the cells have been serialised, which for\n",
+ " // our purposes (turning an active figure into a static one), is too late.\n",
+ " var cells = IPython.notebook.get_cells();\n",
+ " var ncells = cells.length;\n",
+ " for (var i=0; i= 3 moved mimebundle to data attribute of output\n",
+ " data = data.data;\n",
+ " }\n",
+ " if (data['text/html'] == html_output) {\n",
+ " return [cell, data, j];\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "// Register the function which deals with the matplotlib target/channel.\n",
+ "// The kernel may be null if the page has been refreshed.\n",
+ "if (IPython.notebook.kernel != null) {\n",
+ " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
+ "}\n"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "
"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# plot Gravitational force to electric force -- should be constant across all scales\n",
+ "\n",
+ "plt.plot(Rstar_skinDepth/6e5,G_EForce,'ro')\n",
+ "plt.xlabel(\"Log( Normalized (Rstar/Lambda) ) Scaling\")\n",
+ "plt.ylabel(\"G.Force/E.Force\")\n",
+ "plt.xscale(\"log\")\n",
+ "plt.yscale(\"log\")\n",
+ "plt.savefig(\"G_Eforce_scaling.png\",bbox_inches='tight')\n",
+ "#plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# plot Gravitational to magnetic energy -- should be constant across all scales\n",
+ "\n",
+ "plt.plot(Rstar_skinDepth/6e5,GB_energy_ratio,'ro')\n",
+ "plt.rcParams.update({'font.size': 18, 'font.family': 'serif'})\n",
+ "plt.xlabel(\"Log( Normalized (Rstar/Lambda) ) Scaling\")\n",
+ "plt.ylabel(\"G.Energy/B.energy\")\n",
+ "plt.xscale(\"log\")\n",
+ "plt.yscale(\"log\")\n",
+ "plt.savefig(\"G_Benergy_scaling.png\",bbox_inches='tight')\n",
+ "#plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Trends of all energies\n",
+ "plt.plot(Rstar_skinDepth/6e5,magnetic_energy,color=\"red\",ls='--',lw=2,marker=\"^\",markersize=8)\n",
+ "plt.plot(Rstar_skinDepth/6e5,GP_energy,color=\"blue\",lw=2,marker='o',markersize=8,markerfacecolor='blue')\n",
+ "plt.plot(Rstar_skinDepth/6e5,rotational_KE,color=\"purple\",lw=2,marker='s',markersize=8,markeredgecolor='purple')\n",
+ "plt.plot(Rstar_skinDepth/6e5,Torque,color=\"cyan\",lw=2,marker='>',markersize=8,markeredgecolor='purple')\n",
+ "plt.rcParams.update({'font.size': 18, 'font.family': 'serif'})\n",
+ "plt.xlabel(\"Log( Normalized (Rstar/Lambda) ) Scaling\")\n",
+ "plt.ylabel(\"Energy (J)\")\n",
+ "plt.xscale(\"log\")\n",
+ "plt.yscale(\"log\")\n",
+ "plt.rcParams.update({'font.size': 18, 'font.family': 'serif'})\n",
+ "plt.legend([\"Magnetic\",\"G. Potential\",\"Rotational KE\",\"Torque\"],loc=2,fontsize='small',frameon=\"false\",borderpad=0.1)\n",
+ "plt.ylim([1e0,1e90])\n",
+ "plt.savefig(\"Energy_scaling.png\",bbox_inches='tight')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# plot Gravitational to magnetic energy -- should be constant across all scales\n",
+ "plt.plot(Rstar_skinDepth/6e5,Bo/Bo[5],color=\"blue\",lw=2,marker='s',markersize=8)\n",
+ "plt.ylabel(\"Normalized B. field\",color=\"blue\")\n",
+ "plt.xlabel(\"Log( Normalized (Rstar/Lambda) ) Scaling\")\n",
+ "plt.yticks(color=\"blue\")\n",
+ "plt.xscale(\"log\")\n",
+ "plt.yscale(\"log\")\n",
+ "plt.twinx()\n",
+ "plt.plot(Rstar_skinDepth/6e5,Omega/Omega[5],color=\"red\",lw=2,marker='o',markersize=8)\n",
+ "plt.ylabel(\"Normalized \\u03A9\",color=\"red\")\n",
+ "plt.yticks(color=\"red\")\n",
+ "plt.xscale(\"log\")\n",
+ "plt.ylim([0,2])\n",
+ "plt.savefig(\"Normalized_B_Omega.png\",bbox_inches='tight')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.plot(Rstar_skinDepth/6e5,gamma_o,'ro')\n",
+ "plt.rcParams.update({'font.size': 18, 'font.family': 'serif'})\n",
+ "plt.xlabel(\"Log( Normalized (Rstar/Lambda) ) Scaling\")\n",
+ "plt.ylabel(\"Normalized G.Energy/B.energy\")\n",
+ "plt.xscale(\"log\")\n",
+ "plt.yscale(\"log\")\n",
+ "plt.savefig(\"G_Benergy_scaling.png\",bbox_inches='tight')\n",
+ "#plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.plot(Rstar_skinDepth/6e5,Omega_dot,'ro')\n",
+ "plt.rcParams.update({'font.size': 18, 'font.family': 'serif'})\n",
+ "plt.xlabel(\"Log( Normalized (Rstar/Lambda) ) Scaling\")\n",
+ "plt.ylabel(\"Omega_dot\")\n",
+ "plt.xscale(\"log\")\n",
+ "plt.yscale(\"log\")\n",
+ "plt.savefig(\"G_Benergy_scaling.png\",bbox_inches='tight')\n",
+ "#plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.plot(Rstar_skinDepth/6e5,Torque,'ro')\n",
+ "plt.rcParams.update({'font.size': 18, 'font.family': 'serif'})\n",
+ "plt.xlabel(\"Log( Normalized (Rstar/Lambda) ) Scaling\")\n",
+ "plt.ylabel(\"Torque\")\n",
+ "plt.xscale(\"log\")\n",
+ "plt.yscale(\"log\")\n",
+ "plt.savefig(\"Torque.png\",bbox_inches='tight')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plt.plot(Rstar_skinDepth/6e5,phi_o,'ro')\n",
+ "plt.rcParams.update({'font.size': 18, 'font.family': 'serif'})\n",
+ "plt.xlabel(\"Log( Normalized (Rstar/Lambda) ) Scaling\")\n",
+ "plt.ylabel(\"Normalized G.Energy/B.energy\")\n",
+ "plt.xscale(\"log\")\n",
+ "plt.yscale(\"log\")\n",
+ "plt.savefig(\"phi_o.png\",bbox_inches='tight')\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0.020230407144897423"
+ ]
+ },
+ "execution_count": 14,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "SkinDepth_real"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "array([48000., 48000., 48000., 48000., 48000., 48000.])"
+ ]
+ },
+ "execution_count": 15,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "RLC\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "140.625"
+ ]
+ },
+ "execution_count": 16,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "36000/256"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "particle_weight = 140.625**3*5.544e6/64"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "240896701812.74414"
+ ]
+ },
+ "execution_count": 18,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "particle_weight"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "array([0.0010055, 0.0010055, 0.0010055, 0.0010055, 0.0010055, 0.0010055])"
+ ]
+ },
+ "execution_count": 19,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "Period"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "array([48000., 48000., 48000., 48000., 48000., 48000.])"
+ ]
+ },
+ "execution_count": 20,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "RLC\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "anaconda-cloud": {},
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.7.9"
+ },
+ "widgets": {
+ "state": {
+ "11d243e9f5074fe1b115949d174d59de": {
+ "views": [
+ {
+ "cell_index": 6
+ }
+ ]
+ }
+ },
+ "version": "1.2.0"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 1
+}
diff --git a/Examples/Physics_applications/pulsar/inputs.corotating.3d.PM b/Examples/Physics_applications/pulsar/inputs.corotating.3d.PM
index 4785f42cc0c..c7368c4421d 100644
--- a/Examples/Physics_applications/pulsar/inputs.corotating.3d.PM
+++ b/Examples/Physics_applications/pulsar/inputs.corotating.3d.PM
@@ -15,8 +15,8 @@
#################################
max_step = 50000
amr.n_cell = 128 128 128
-amr.max_grid_size = 64
-amr.blocking_factor = 64
+amr.max_grid_size = 128
+amr.blocking_factor = 128
amr.max_level = 0
geometry.coord_sys = 0 # 0: Cartesian
geometry.is_periodic = 0 0 0 # Is periodic?
@@ -26,11 +26,12 @@ geometry.prob_hi = 180000 180000 180000
#################################
############ NUMERICS ###########
#################################
-algo.maxwell_fdtd_solver = yee
+#algo.maxwell_fdtd_solver = yee
warpx.verbose = 1
warpx.do_dive_cleaning = 0
warpx.use_filter = 1
-warpx.cfl = .5
+warpx.cfl = .95
+warpx.do_pml = 1
my_constants.pi = 3.141592653589793
my_constants.dens = 5.544e6
my_constants.xc = 90000
@@ -40,20 +41,12 @@ my_constants.r_star = 12000
my_constants.omega = 6245.676
my_constants.c = 299792458.
my_constants.B_star = 8.0323e-6 # magnetic field of NS (T)
-my_constants.dR = 1.4e3
-my_constants.to = 2e-4
+my_constants.dR = 1400
+my_constants.to = 2.e-4
interpolation.nox = 3
interpolation.noy = 3
interpolation.noz = 3
-#warpx.E_ext_grid_init_style = "parse_E_ext_grid_function"
-#warpx.Ex_external_grid_function(x,y,z) = "((x-xc)*(x-xc)+(y-yc)*(y-yc) + (z-zc)*(z-zc))^0.5"
-#warpx.Ey_external_grid_function(x,y,z) = "((x-xc)*(x-xc)+(y-yc)*(y-yc) + (z-zc)*(z-zc))^0.5"
-#warpx.Ez_external_grid_function(x,y,z) = "((x-xc)*(x-xc)+(y-yc)*(y-yc) + (z-zc)*(z-zc))^0.5"
-
-
-
-
#################################
############ PLASMA #############
@@ -65,30 +58,15 @@ plasma_e.charge = -q_e
plasma_e.mass = m_e
plasma_e.injection_style = "NUniformPerCell"
plasma_e.profile = parse_density_function
-plasma_e.density_function(x,y,z) = "( ((( (z-zc)*(z-zc) + (y-yc)*(y-yc) + (x-xc)*(x-xc) )^(0.5))<=(r_star+dR)) * ((( (z-zc)*(z-zc) + (y-yc)*(y-yc) + (x-xc)*(x-xc) )^(0.5))>=(r_star)) )*dens"
-plasma_e.num_particles_per_cell_each_dim = 3 3 3
+plasma_e.density_function(x,y,z) = "( ((( (z-zc)*(z-zc) + (y-yc)*(y-yc) + (x-xc)*(x-xc) )^(0.5))<=(r_star)) * ((( (z-zc)*(z-zc) + (y-yc)*(y-yc) + (x-xc)*(x-xc) )^(0.5))>=(r_star-dR)) )*dens"
+plasma_e.num_particles_per_cell_each_dim = 4 4 4
plasma_e.momentum_distribution_type = parse_momentum_function
-## Inject pairs rotating at omega(t) x r velocity
-#plasma_e.momentum_function_ux(x,y,z) = "( (( (z-zc)*(z-zc) + (y-yc)*(y-yc) + (x-xc)*(x-xc) )^(0.5))>=r_star)*(-( (t=to)*omega )*(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5))/((1.0-( ( (t=to)*omega) *(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5))/c)^2)^(0.5)) * (y-yc)/(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5)))"
-#plasma_e.momentum_function_uy(x,y,z) = "( (( (z-zc)*(z-zc) + (y-yc)*(y-yc) + (x-xc)*(x-xc) )^(0.5))>=r_star)*( ( (t=to)*omega ) *(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5))/((1.0-( ( (t=to)*omega )*(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5))/c)^2)^(0.5)) * (x-xc)/(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5)))"
-
-## Inject pairs rotating at omega x r velocity
-#plasma_e.momentum_function_ux(x,y,z) = "( (( (z-zc)*(z-zc) + (y-yc)*(y-yc) + (x-xc)*(x-xc) )^(0.5))<=r_star)*(-omega*(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5))/((1.0-(omega*(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5))/c)^2)^(0.5)) * (y-yc)/(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5)))"
-#plasma_e.momentum_function_uy(x,y,z) = "( (( (z-zc)*(z-zc) + (y-yc)*(y-yc) + (x-xc)*(x-xc) )^(0.5))<=r_star)*(omega*(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5))/((1.0-(omega*(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5))/c)^2)^(0.5)) * (x-xc)/(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5)))"
-
## Inject stationary pairs
plasma_e.momentum_function_ux(x,y,z) = "0.0"
plasma_e.momentum_function_uy(x,y,z) = "0.0"
-
## uz is always 0 for the injection methods above
plasma_e.momentum_function_uz(x,y,z) = "0.0"
-
-#plasma_e.momentum_distribution_type = "constant"
-#plasma_e.ux = 0.0
-#plasma_e.uy = 0.0
-#plasma_e.uz = 0.0
-
plasma_e.do_continuous_injection = 0
plasma_e.density_min = 1E0
@@ -96,62 +74,67 @@ plasma_p.charge = q_e
plasma_p.mass = m_e
plasma_p.injection_style = "NUniformPerCell"
plasma_p.profile = parse_density_function
-#plasma_p.density_function(x,y,z) = "( ((( (z-zc)*(z-zc) + (y-yc)*(y-yc) + (x-xc)*(x-xc) )^(0.5))>=r_star)* ((( (z-zc)*(z-zc) + (y-yc)*(y-yc) + (x-xc)*(x-xc) )^(0.5))<(r_star+dR)))*dens"
-plasma_p.density_function(x,y,z) = "( ((( (z-zc)*(z-zc) + (y-yc)*(y-yc) + (x-xc)*(x-xc) )^(0.5))<=(r_star+dR)) * ((( (z-zc)*(z-zc) + (y-yc)*(y-yc) + (x-xc)*(x-xc) )^(0.5))>=(r_star)) )*dens"
-plasma_p.num_particles_per_cell_each_dim = 3 3 3
+plasma_p.density_function(x,y,z) = "( ((( (z-zc)*(z-zc) + (y-yc)*(y-yc) + (x-xc)*(x-xc) )^(0.5))<=(r_star)) * ((( (z-zc)*(z-zc) + (y-yc)*(y-yc) + (x-xc)*(x-xc) )^(0.5))>=(r_star-dR)) )*dens"
+plasma_p.num_particles_per_cell_each_dim = 4 4 4
plasma_p.momentum_distribution_type = parse_momentum_function
-## Inject pairs rotating at omega(t) x r velocity
-#plasma_p.momentum_function_ux(x,y,z) = "( (( (z-zc)*(z-zc) + (y-yc)*(y-yc) + (x-xc)*(x-xc) )^(0.5))>=r_star)*(-( (t=to)*omega )*(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5))/((1.0-( ( (t=to)*omega) *(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5))/c)^2)^(0.5)) * (y-yc)/(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5)))"
-#plasma_p.momentum_function_uy(x,y,z) = "( (( (z-zc)*(z-zc) + (y-yc)*(y-yc) + (x-xc)*(x-xc) )^(0.5))>=r_star)*( ( (t=to)*omega ) *(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5))/((1.0-( ( (t=to)*omega )*(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5))/c)^2)^(0.5)) * (x-xc)/(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5)))"
-
-## Inject pairs rotating at omega x r velocity
-#plasma_p.momentum_function_ux(x,y,z) = "( (( (z-zc)*(z-zc) + (y-yc)*(y-yc) + (x-xc)*(x-xc) )^(0.5))<=r_star)*(-omega*(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5))/((1.0-(omega*(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5))/c)^2)^(0.5)) * (y-yc)/(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5)))"
-#plasma_p.momentum_function_uy(x,y,z) = "( (( (z-zc)*(z-zc) + (y-yc)*(y-yc) + (x-xc)*(x-xc) )^(0.5))<=r_star)*(omega*(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5))/((1.0-(omega*(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5))/c)^2)^(0.5)) * (x-xc)/(((x-xc)*(x-xc) + (y-yc)*(y-yc))^(0.5)))"
-
## Inject stationary pairs
plasma_p.momentum_function_ux(x,y,z) = "0.0"
plasma_p.momentum_function_uy(x,y,z) = "0.0"
-
## uz is always 0 for the injection methods above
plasma_p.momentum_function_uz(x,y,z) = "0.0"
-
-#plasma_p.momentum_distribution_type = "constant"
-#plasma_p.ux = 0.0
-#plasma_p.uy = 0.0
-#plasma_p.uz = 0.0
-
plasma_p.do_continuous_injection = 0
plasma_p.density_min = 1E0
-diagnostics.diags_names = plt
+diagnostics.diags_names = plt chk
plt.diag_type = Full
-plt.period = 200
+plt.period = 20
plt.fields_to_plot = Ex Ey Ez Bx By Bz jx jy jz part_per_cell rho divE
+chk.format = checkpoint
+chk.diag_type = Full
+chk.period = 1000
#################################
######### PULSAR SETUP ##########
#################################
pulsar.pulsarType = "dead" # [dead/active]: sets particle injection type
pulsar.omega_star = 6245.676 # angular velocity of NS (rad/s)
-<<<<<<< HEAD
-pulsar.ramp_omega_time = 0.0 # time over which to ramp up NS angular velocity (s)
-#pulsar.ramp_omega_time = 2e-4 # time over which to ramp up NS angular velocity (s)
-=======
-pulsar.ramp_omega_time = 0.e-5 # time over which to ramp up NS angular velocity (s)
->>>>>>> 2756eb86 (recent input file)
+pulsar.ramp_omega_time = 0.0 # time over which to ramp up NS angular velocity (s)
# if ramp_omega_time < 0, omega = omega_star for any t
# consistency requires ramp_omega_time = my_constants.to
pulsar.center_star = 90000 90000 90000
pulsar.R_star = 12032 # radius of NS (m)
pulsar.B_star = 8.0323e-6 # magnetic field of NS (T)
-pulsar.dR = 1075
+pulsar.dR = 1400 # thickness on the surface of the pulsar
+ # consistency requires dR = my_constants.dR
pulsar.verbose = 0 # [0/1]: turn on verbosity for debugging print statements
pulsar.EB_external = 1 # [0/1]: to apply external E and B
pulsar.E_external_monopole = 0 # [0/1]
+pulsar.EB_corotating_maxradius = 12032 # The radius where E-field changes from corotating
+ # inside the star to quadrapole outside.
+ # Default is R_star. (r<=cor_radius) i.e. the includes
+ # the r specified in the input
pulsar.max_ndens = 5.54e6 # max ndens == ndens used in initializing density
-pulsar.Ninj_fraction = 0.1 # fraction of sigma injected
+pulsar.Ninj_fraction = 0.2 # fraction of sigma injected
+pulsar.ModifyParticleWeight = 1 # (0/1) the fractional injection is achieved
+ # by modifying particle weight if 1
+ # by modifying num_ppc if 0
+pulsar.particle_inj_rmin = 10632 # default is Rstar-dR (consistent with density function above)
+pulsar.particle_inj_rmax = 12032 # default is Rstar (consistent with density function)
+pulsar.max_particle_absorption_radius = 12032 # Maximum radius within which particles are
+ # deleted every timestep.
+ # Default is Rstar
pulsar.rhoGJ_scale = 1e0 # scaling down of rho_GJ
pulsar.damp_EB_internal = 1 # Damp internal electric field
-pulsar.damping_scale = 10.0 # Damping scale factor for internal electric field
+pulsar.damp_EB_radius = 12032 # The radius within which EB should be damped.
+ # default is r_star (damping will include this radius)
+pulsar.damping_scale = 1000.0 # Damping scale factor for internal electric field
+pulsar.turnoffdeposition = 0 # (0/1) 0 for depositing (default)
+ # 1 for no deposition
+pulsar.max_nodepos_radius = 0. # radius within which particle deposition for j/rho
+ # is turned off. (r<=max_radius)
+pulsar.turnoff_plasmaEB_gather = 0 # (0/1) 0 is default. always gather
+ # 1 for no gather of self-consistent fields
+pulsar.max_nogather_radius = 0. # radius within which self-consistent field gather
+ # is turned off
diff --git a/Examples/Physics_applications/pulsar/pulsar_viz.ipynb b/Examples/Physics_applications/pulsar/pulsar_viz.ipynb
new file mode 100644
index 00000000000..57ef79c1599
--- /dev/null
+++ b/Examples/Physics_applications/pulsar/pulsar_viz.ipynb
@@ -0,0 +1,690 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Overview\n",
+ "\n",
+ "This a notebook that inspects the results of a WarpX simulation.\n",
+ "\n",
+ "# Instruction\n",
+ "\n",
+ "Enter the path of the data you wish to visualize below. Then execute the cells one by one, by selecting them with your mouse and typing `Shift + Enter`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Import statements\n",
+ "import yt ; yt.funcs.mylog.setLevel(50)\n",
+ "import numpy as np\n",
+ "import scipy.constants as scc\n",
+ "import matplotlib.pyplot as plt\n",
+ "%matplotlib notebook"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Read data in the simulation frame"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Plot data with yt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 149,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "\n",
+ "ds = yt.load( './plotfiles/plt00090/' ) # Create a dataset object\n",
+ "filenum = 10\n",
+ "#ds.field_list"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 150,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/usr/local/lib/python3.5/dist-packages/yt-3.6.dev0-py3.5-linux-x86_64.egg/yt/units/yt_array.py:1400: RuntimeWarning: invalid value encountered in true_divide\n",
+ " out=out, **kwargs)\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "
"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "\n",
+ "sl = yt.SlicePlot(ds, 0, 'Ez', aspect=1) # Create a sliceplot object\n",
+ "sl.annotate_particles(width=(2.e3, 'm'),ptype=\"plasma_p\",col='b',p_size=5.0)\n",
+ "sl.annotate_particles(width=(2.e3, 'm'),ptype=\"plasma_e\",col='r',p_size=5.0)\n",
+ "sl.annotate_streamlines(\"Ey\", \"Ez\", plot_args={\"color\": \"black\"})\n",
+ "sl.annotate_grids() # Show grids\n",
+ "sl.annotate_sphere([90000.0, 90000.0, 90000.0], radius=12000.0,\n",
+ " circle_args={'color':'white', 'linewidth':2})\n",
+ "sl.show() # Show the plot\n",
+ "#sl.save('./particle_in_ring_plt'+str(filenum)+'.png')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 147,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "['positron_plt10.png']"
+ ]
+ },
+ "execution_count": 147,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "p = yt.ParticlePlot(ds,('plasma_p', 'particle_position_x'),('plasma_p', 'particle_position_y'),('plasma_p', 'particle_momentum_x'))\n",
+ "p.show()\n",
+ "p.save(\"positron_plt\"+str(filenum)+\".png\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 148,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "['electrons_plt10.png']"
+ ]
+ },
+ "execution_count": 148,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "p = yt.ParticlePlot(ds,('plasma_e', 'particle_position_y'),('plasma_e', 'particle_position_z'),('plasma_e', 'particle_momentum_z'))\n",
+ "#p = yt.ParticlePlot(ds,('plasma_p', 'particle_position_y'),('plasma_p', 'particle_position_z'),('plasma_p', 'particle_momentum_x'))\n",
+ "p.show()\n",
+ "p.save(\"electrons_plt\"+str(filenum)+\".png\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from yt.units.yt_array import YTQuantity\n",
+ "from yt.units import kboltz\n",
+ "from numpy.random import random\n",
+ "import numpy as np\n",
+ "from yt.utilities.exceptions import YTUnitOperationError\n",
+ "def r_cl(field,data):\n",
+ " xc = YTQuantity(90000, 'm')\n",
+ " yc = YTQuantity(90000, 'm')\n",
+ " zc = YTQuantity(90000, 'm')\n",
+ "\n",
+ " r = ((data[\"y\"]-yc)*(data[\"y\"]-yc) + (data[\"x\"]-xc)*(data[\"x\"]-xc))**0.5\n",
+ "\n",
+ " return r"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ds.add_field((\"index\",\"r_cl\"),function=r_cl,units='m',sampling_type=\"cell\")\n",
+ "#yt.SlicePlot(ds,'z','r_cl')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from yt.units.yt_array import YTQuantity\n",
+ "from yt.units import kboltz\n",
+ "from numpy.random import random\n",
+ "import numpy as np\n",
+ "from yt.utilities.exceptions import YTUnitOperationError\n",
+ "def rad(field,data):\n",
+ " xc = YTQuantity(90000, 'm')\n",
+ " yc = YTQuantity(90000, 'm')\n",
+ " zc = YTQuantity(90000, 'm')\n",
+ "\n",
+ " r = ((data[\"y\"]-yc)*(data[\"y\"]-yc) + (data[\"x\"]-xc)*(data[\"x\"]-xc) + (data[\"z\"]-zc)*(data[\"z\"]-zc))**0.5\n",
+ "\n",
+ " return r"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ds.add_field((\"index\",\"rad\"),function=rad,units='m',sampling_type=\"cell\")\n",
+ "#yt.SlicePlot(ds,'z','rad')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Store quantities in numpy arrays, and plot with matplotlib"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from yt.units.yt_array import YTQuantity\n",
+ "from yt.units import kboltz\n",
+ "from numpy.random import random\n",
+ "import numpy as np\n",
+ "from yt.utilities.exceptions import YTUnitOperationError\n",
+ "def Ex_external(field,data):\n",
+ " xc = YTQuantity(90000, 'm')\n",
+ " yc = YTQuantity(90000, 'm')\n",
+ " zc = YTQuantity(90000, 'm')\n",
+ " r_star = YTQuantity(12000, 'm')\n",
+ " omega = 6245.8\n",
+ " B = 8.03e-6\n",
+ " r = ((data[\"y\"]-yc)*(data[\"y\"]-yc) + (data[\"x\"]-xc)*(data[\"x\"]-xc) + (data[\"z\"]-zc)*(data[\"z\"]-zc))**0.5\n",
+ " c_theta = (data[\"z\"]-zc)/r\n",
+ " s_theta = data[\"r_cl\"]/r\n",
+ " c_phi = (data[\"x\"]-xc)/data[\"r_cl\"]\n",
+ " s_phi = (data[\"y\"]-yc)/data[\"r_cl\"]\n",
+ " r_ratio = r_star/r\n",
+ " r3 = r_ratio*r_ratio*r_ratio\n",
+ " Er = omega*r_star*B*r3*r_ratio*(1.0-3.0*c_theta*c_theta) \n",
+ " + (2.0/3.0)*omega*B*r_star*r_ratio*r_ratio\n",
+ " E_theta = (-1)*omega*B*r_star*r3*r_ratio*(c_theta*s_theta*2.0)\n",
+ " Ex_ext = Er*c_phi*s_theta + E_theta*c_phi*c_theta\n",
+ "\n",
+ " outside = np.zeros_like(data[\"r_cl\"])\n",
+ " outside[data[\"rad\"] > 12000] = 1.0\n",
+ "\n",
+ " \n",
+ " return outside.d*Ex_ext.d"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from yt.units.yt_array import YTQuantity\n",
+ "from yt.units import kboltz\n",
+ "from numpy.random import random\n",
+ "import numpy as np\n",
+ "from yt.utilities.exceptions import YTUnitOperationError\n",
+ "def Ex_internal(field,data):\n",
+ " xc = YTQuantity(90000, 'm')\n",
+ " yc = YTQuantity(90000, 'm')\n",
+ " zc = YTQuantity(90000, 'm')\n",
+ " r_star = YTQuantity(12000, 'm')\n",
+ " omega = 6245.8\n",
+ " B = 8.03e-6\n",
+ " r = ((data[\"y\"]-yc)*(data[\"y\"]-yc) + (data[\"x\"]-xc)*(data[\"x\"]-xc) + (data[\"z\"]-zc)*(data[\"z\"]-zc))**0.5\n",
+ " c_theta = (data[\"z\"]-zc)/r\n",
+ " s_theta = data[\"r_cl\"]/r\n",
+ " c_phi = (data[\"x\"]-xc)/data[\"r_cl\"]\n",
+ " s_phi = (data[\"y\"]-yc)/data[\"r_cl\"]\n",
+ " r_ratio = r_star/r\n",
+ " r3 = r_ratio*r_ratio*r_ratio\n",
+ " Er = omega*r*r3*B*s_theta*s_theta\n",
+ " E_theta = (-1)*omega*B*r*r3*(c_theta*s_theta*2.0)\n",
+ " Ex_ext = Er*c_phi*s_theta + E_theta*c_phi*c_theta\n",
+ "\n",
+ " outside = np.zeros_like(data[\"r_cl\"])\n",
+ " outside[data[\"rad\"] <= 12000] = 1.0\n",
+ "\n",
+ " \n",
+ " return outside.d*Ex_ext.d"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from yt.units.yt_array import YTQuantity\n",
+ "from yt.units import kboltz\n",
+ "from numpy.random import random\n",
+ "import numpy as np\n",
+ "from yt.utilities.exceptions import YTUnitOperationError\n",
+ "def Ey_external(field,data):\n",
+ " xc = YTQuantity(90000, 'm')\n",
+ " yc = YTQuantity(90000, 'm')\n",
+ " zc = YTQuantity(90000, 'm')\n",
+ " r_star = YTQuantity(12000, 'm')\n",
+ " omega = 6245.8\n",
+ " B = 8.03e-6\n",
+ "\n",
+ " r = ((data[\"y\"]-yc)*(data[\"y\"]-yc) + (data[\"x\"]-xc)*(data[\"x\"]-xc) + (data[\"z\"]-zc)*(data[\"z\"]-zc))**0.5\n",
+ " c_theta = (data[\"z\"]-zc)/r\n",
+ " s_theta = data[\"r_cl\"]/r\n",
+ " c_phi = (data[\"x\"]-xc)/data[\"r_cl\"]\n",
+ " s_phi = (data[\"y\"]-yc)/data[\"r_cl\"]\n",
+ " r_ratio = r_star/r\n",
+ " r3 = r_ratio*r_ratio*r_ratio\n",
+ " Er = omega*r_star*B*r3*r_ratio*(1.0-3.0*c_theta*c_theta) \n",
+ " + (2.0/3.0)*omega*B*r_star*r_ratio*r_ratio\n",
+ " E_theta = (-1)*omega*B*r_star*r3*r_ratio*(c_theta*s_theta*2.0)\n",
+ " Ey_ext = Er*s_phi*s_theta + E_theta*s_phi*c_theta\n",
+ "\n",
+ " outside = np.zeros_like(data[\"r_cl\"])\n",
+ " outside[data[\"rad\"] > 12000] = 1.0\n",
+ "\n",
+ " \n",
+ " return outside.d*Ey_ext.d"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from yt.units.yt_array import YTQuantity\n",
+ "from yt.units import kboltz\n",
+ "from numpy.random import random\n",
+ "import numpy as np\n",
+ "from yt.utilities.exceptions import YTUnitOperationError\n",
+ "def Ey_internal(field,data):\n",
+ " xc = YTQuantity(90000, 'm')\n",
+ " yc = YTQuantity(90000, 'm')\n",
+ " zc = YTQuantity(90000, 'm')\n",
+ " r_star = YTQuantity(12000, 'm')\n",
+ " omega = 6245.8\n",
+ " B = 8.03e-6\n",
+ " r = ((data[\"y\"]-yc)*(data[\"y\"]-yc) + (data[\"x\"]-xc)*(data[\"x\"]-xc) + (data[\"z\"]-zc)*(data[\"z\"]-zc))**0.5\n",
+ " c_theta = (data[\"z\"]-zc)/r\n",
+ " s_theta = data[\"r_cl\"]/r\n",
+ " c_phi = (data[\"x\"]-xc)/data[\"r_cl\"]\n",
+ " s_phi = (data[\"y\"]-yc)/data[\"r_cl\"]\n",
+ " r_ratio = r_star/r\n",
+ " r3 = r_ratio*r_ratio*r_ratio\n",
+ " Er = omega*r*r3*B*s_theta*s_theta\n",
+ " E_theta = (-1)*omega*B*r*r3*(c_theta*s_theta*2.0)\n",
+ " Ey_ext = Er*s_phi*s_theta + E_theta*s_phi*c_theta\n",
+ " outside = np.zeros_like(data[\"r_cl\"])\n",
+ " outside[data[\"rad\"] <= 12000] = 1.0\n",
+ "\n",
+ " \n",
+ " return outside.d*Ey_ext.d"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from yt.units.yt_array import YTQuantity\n",
+ "from yt.units import kboltz\n",
+ "from numpy.random import random\n",
+ "import numpy as np\n",
+ "from yt.utilities.exceptions import YTUnitOperationError\n",
+ "def Ez_external(field,data):\n",
+ " xc = YTQuantity(90000, 'm')\n",
+ " yc = YTQuantity(90000, 'm')\n",
+ " zc = YTQuantity(90000, 'm')\n",
+ " r_star = YTQuantity(12000, 'm')\n",
+ " omega = 6245.8\n",
+ " B = 8.03e-6\n",
+ " r = ((data[\"y\"]-yc)*(data[\"y\"]-yc) + (data[\"x\"]-xc)*(data[\"x\"]-xc) + (data[\"z\"]-zc)*(data[\"z\"]-zc))**0.5\n",
+ " c_theta = (data[\"z\"]-zc)/r\n",
+ " s_theta = data[\"r_cl\"]/r\n",
+ " c_phi = (data[\"x\"]-xc)/data[\"r_cl\"]\n",
+ " s_phi = (data[\"y\"]-yc)/data[\"r_cl\"]\n",
+ " r_ratio = r_star/r\n",
+ " r3 = r_ratio*r_ratio*r_ratio\n",
+ " Er = omega*r_star*B*r3*r_ratio*(1.0-3.0*c_theta*c_theta) \n",
+ " + (2.0/3.0)*omega*B*r_star*r_ratio*r_ratio\n",
+ " E_theta = (-1)*omega*B*r_star*r3*r_ratio*(c_theta*s_theta*2.0)\n",
+ " Ez_ext = Er*c_theta - E_theta*s_theta\n",
+ "\n",
+ " outside = np.zeros_like(data[\"r_cl\"])\n",
+ " outside[data[\"rad\"] > 12000] = 1.0\n",
+ "\n",
+ " \n",
+ " return outside.d*Ez_ext.d \n",
+ " #return outside.d*Er.d"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from yt.units.yt_array import YTQuantity\n",
+ "from yt.units import kboltz\n",
+ "from numpy.random import random\n",
+ "import numpy as np\n",
+ "from yt.utilities.exceptions import YTUnitOperationError\n",
+ "def Ez_internal(field,data):\n",
+ " xc = YTQuantity(90000, 'm')\n",
+ " yc = YTQuantity(90000, 'm')\n",
+ " zc = YTQuantity(90000, 'm')\n",
+ " r_star = YTQuantity(12000, 'm')\n",
+ " omega = 6245.8\n",
+ " B = 8.03e-6\n",
+ " r = ((data[\"y\"]-yc)*(data[\"y\"]-yc) + (data[\"x\"]-xc)*(data[\"x\"]-xc) + (data[\"z\"]-zc)*(data[\"z\"]-zc))**0.5\n",
+ " c_theta = (data[\"z\"]-zc)/r\n",
+ " s_theta = data[\"r_cl\"]/r\n",
+ " c_phi = (data[\"x\"]-xc)/data[\"r_cl\"]\n",
+ " s_phi = (data[\"y\"]-yc)/data[\"r_cl\"]\n",
+ " r_ratio = r_star/r\n",
+ " r3 = r_ratio*r_ratio*r_ratio\n",
+ " Er = omega*r*r3*B*s_theta*s_theta\n",
+ " E_theta = (-1)*omega*B*r*r3*(c_theta*s_theta*2.0)\n",
+ " Ez_ext = Er*c_theta - E_theta*s_theta\n",
+ "\n",
+ " outside = np.zeros_like(data[\"r_cl\"])\n",
+ " outside[data[\"rad\"] <= 12000] = 1.0\n",
+ "\n",
+ " \n",
+ " #return outside.d*Ez_ext.d\n",
+ " return outside.d*Er.d"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from yt.units.yt_array import YTQuantity\n",
+ "from yt.units import kboltz\n",
+ "from numpy.random import random\n",
+ "import numpy as np\n",
+ "from yt.utilities.exceptions import YTUnitOperationError\n",
+ "def Ex_total_ext(field,data):\n",
+ "\n",
+ " return data[\"Ex_internal\"] + data[\"Ex_external\"]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from yt.units.yt_array import YTQuantity\n",
+ "from yt.units import kboltz\n",
+ "from numpy.random import random\n",
+ "import numpy as np\n",
+ "from yt.utilities.exceptions import YTUnitOperationError\n",
+ "def Ey_total_ext(field,data):\n",
+ "\n",
+ " return data[\"Ey_internal\"] + data[\"Ey_external\"]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from yt.units.yt_array import YTQuantity\n",
+ "from yt.units import kboltz\n",
+ "from numpy.random import random\n",
+ "import numpy as np\n",
+ "from yt.utilities.exceptions import YTUnitOperationError\n",
+ "def Ez_total_ext(field,data):\n",
+ "\n",
+ " return data[\"Ez_internal\"] + data[\"Ez_external\"]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [],
+ "source": [
+ "ds.add_field((\"Ex_external\"),function=Ex_external,units='',sampling_type=\"cell\")\n",
+ "ds.add_field((\"Ey_external\"),function=Ey_external,units='',sampling_type=\"cell\")\n",
+ "ds.add_field((\"Ez_external\"),function=Ez_external,units='',sampling_type=\"cell\")\n",
+ "ds.add_field((\"Ex_internal\"),function=Ex_internal,units='',sampling_type=\"cell\")\n",
+ "ds.add_field((\"Ey_internal\"),function=Ey_internal,units='',sampling_type=\"cell\")\n",
+ "ds.add_field((\"Ez_internal\"),function=Ez_internal,units='',sampling_type=\"cell\")\n",
+ "ds.add_field((\"Ex_total_ext\"),function=Ex_total_ext,units='',sampling_type=\"cell\")\n",
+ "ds.add_field((\"Ey_total_ext\"),function=Ey_total_ext,units='',sampling_type=\"cell\")\n",
+ "ds.add_field((\"Ez_total_ext\"),function=Ez_total_ext,units='',sampling_type=\"cell\")\n",
+ "\n",
+ "p = yt.SlicePlot(ds,'x','Ez_external')\n",
+ "p.annotate_streamlines(\"Ex_external\", \"Ez_external\", \n",
+ " plot_args={\"color\": \"black\"})\n",
+ "#p.annotate_particles(width=(2.e3, 'm'),ptype=\"plasma_p\",col='b',p_size=5.0)\n",
+ "#p.annotate_particles(width=(2.e3, 'm'),ptype=\"plasma_e\",col='r',p_size=5.0)\n",
+ "p.show()\n",
+ "p = yt.SlicePlot(ds,'x','Ez_internal')\n",
+ "p.annotate_streamlines(\"Ex_internal\", \"Ez_internal\", \n",
+ " plot_args={\"color\": \"black\"})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Read data back-transformed to the lab frame when the simulation runs in the boosted frame (example: 2D run)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# read_raw_data.py is located in warpx/Tools.\n",
+ "import os, glob\n",
+ "#import read_raw_data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#species = 'beam'\n",
+ "#iteration = 1\n",
+ "#field = 'Ex'\n",
+ "\n",
+ "#snapshot = './lab_frame_data/' + 'snapshot' + str(iteration).zfill(5)\n",
+ "#header = './lab_frame_data/Header'\n",
+ "#allrd, info = read_raw_data.read_lab_snapshot(snapshot, header) # Read field data\n",
+ "#F = allrd[field]\n",
+ "#print( \"Available info: \", *list(info.keys()) )\n",
+ "#print(\"Available fields: \", info['field_names'])\n",
+ "#nx = info['nx']\n",
+ "#nz = info['nz']\n",
+ "#x = info['x']\n",
+ "#z = info['z']\n",
+ "#xbo = read_raw_data.get_particle_field(snapshot, species, 'x') # Read particle data\n",
+ "#ybo = read_raw_data.get_particle_field(snapshot, species, 'y')\n",
+ "#zbo = read_raw_data.get_particle_field(snapshot, species, 'z')\n",
+ "#uzbo = read_raw_data.get_particle_field(snapshot, species, 'uz')\n",
+ "\n",
+ "#plt.figure(figsize=(6, 3))\n",
+ "#extent = np.array([info['zmin'], info['zmax'], info['xmin'], info['xmax']])\n",
+ "#plt.imshow(F, aspect='auto', extent=extent, cmap='seismic')\n",
+ "#plt.colorbar()\n",
+ "#plt.plot(zbo, xbo, 'g.', markersize=1.)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Read back-transformed data with hdf5 format (example: 3D run)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "5e10*1400*1400"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "5e6*1400*1400"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "685708*1400*1400"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "anaconda-cloud": {},
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.5.2"
+ },
+ "widgets": {
+ "state": {
+ "11d243e9f5074fe1b115949d174d59de": {
+ "views": [
+ {
+ "cell_index": 6
+ }
+ ]
+ }
+ },
+ "version": "1.2.0"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 1
+}
diff --git a/Source/Evolve/WarpXEvolve.cpp b/Source/Evolve/WarpXEvolve.cpp
index cbf2ffaa8e4..164f3a6e7bf 100644
--- a/Source/Evolve/WarpXEvolve.cpp
+++ b/Source/Evolve/WarpXEvolve.cpp
@@ -156,20 +156,15 @@ WarpX::Evolve (int numsteps)
Bx = Bfield_fp[lev][0].get();
By = Bfield_fp[lev][1].get();
Bz = Bfield_fp[lev][2].get();
- Gpu::ManagedVector Ex_stag, Ey_stag, Ez_stag, Bx_stag, By_stag, Bz_stag;
- Ex_stag.resize(3);
- Ey_stag.resize(3);
- Ez_stag.resize(3);
- Bx_stag.resize(3);
- By_stag.resize(3);
- Bz_stag.resize(3);
amrex::IntVect ex_type = Ex->ixType().toIntVect();
amrex::IntVect ey_type = Ey->ixType().toIntVect();
amrex::IntVect ez_type = Ez->ixType().toIntVect();
amrex::IntVect bx_type = Bx->ixType().toIntVect();
amrex::IntVect by_type = By->ixType().toIntVect();
amrex::IntVect bz_type = Bz->ixType().toIntVect();
- for (int idim = 0; idim < AMREX_SPACEDIM-1; ++idim) {
+ amrex::GpuArray Ex_stag, Ey_stag, Ez_stag, Bx_stag, By_stag, Bz_stag;
+ for (int idim = 0; idim < 3; ++idim)
+ {
Ex_stag[idim] = ex_type[idim];
Ey_stag[idim] = ey_type[idim];
Ez_stag[idim] = ez_type[idim];
@@ -177,12 +172,6 @@ WarpX::Evolve (int numsteps)
By_stag[idim] = by_type[idim];
Bz_stag[idim] = bz_type[idim];
}
- int const* const AMREX_RESTRICT Ex_stag_ptr = Ex_stag.data();
- int const* const AMREX_RESTRICT Ey_stag_ptr = Ey_stag.data();
- int const* const AMREX_RESTRICT Ez_stag_ptr = Ez_stag.data();
- int const* const AMREX_RESTRICT Bx_stag_ptr = Bx_stag.data();
- int const* const AMREX_RESTRICT By_stag_ptr = By_stag.data();
- int const* const AMREX_RESTRICT Bz_stag_ptr = Bz_stag.data();
auto geom = Geom(lev).data();
#ifdef _OPENMP
#pragma omp parallel if (Gpu::notInLaunchRegion())
@@ -200,15 +189,15 @@ WarpX::Evolve (int numsteps)
amrex::ParallelFor(tex, tey, tez,
[=] AMREX_GPU_DEVICE (int i, int j, int k)
{
- PulsarParm::DampEField(i, j, k, geom, Exfab, Ex_stag_ptr);
+ PulsarParm::DampField(i, j, k, geom, Exfab, Ex_stag);
},
[=] AMREX_GPU_DEVICE (int i, int j, int k)
{
- PulsarParm::DampEField(i, j, k, geom, Eyfab, Ey_stag_ptr);
+ PulsarParm::DampField(i, j, k, geom, Eyfab, Ey_stag);
},
[=] AMREX_GPU_DEVICE (int i, int j, int k)
{
- PulsarParm::DampEField(i, j, k, geom, Ezfab, Ez_stag_ptr);
+ PulsarParm::DampField(i, j, k, geom, Ezfab, Ez_stag);
});
}
for ( MFIter mfi(*Bx, TilingIfNotGPU()); mfi.isValid(); ++mfi )
@@ -224,19 +213,21 @@ WarpX::Evolve (int numsteps)
amrex::ParallelFor(tex, tey, tez,
[=] AMREX_GPU_DEVICE (int i, int j, int k)
{
- PulsarParm::DampEField(i, j, k, geom, Bxfab, Bx_stag_ptr);
+ PulsarParm::DampField(i, j, k, geom, Bxfab, Bx_stag);
},
[=] AMREX_GPU_DEVICE (int i, int j, int k)
{
- PulsarParm::DampEField(i, j, k, geom, Byfab, By_stag_ptr);
+ PulsarParm::DampField(i, j, k, geom, Byfab, By_stag);
},
[=] AMREX_GPU_DEVICE (int i, int j, int k)
{
- PulsarParm::DampEField(i, j, k, geom, Bzfab, Bz_stag_ptr);
+ PulsarParm::DampField(i, j, k, geom, Bzfab, Bz_stag);
});
}
}
}
+ FillBoundaryE(guard_cells.ng_FieldSolver, IntVect::TheZeroVector());
+ FillBoundaryB(guard_cells.ng_FieldSolver, IntVect::TheZeroVector());
#endif
if (warpx_py_beforeEsolve) warpx_py_beforeEsolve();
diff --git a/Source/Initialization/InjectorPosition.H b/Source/Initialization/InjectorPosition.H
index 6d83c397884..7cd2430dddf 100644
--- a/Source/Initialization/InjectorPosition.H
+++ b/Source/Initialization/InjectorPosition.H
@@ -12,6 +12,10 @@
#include
#include
+#ifdef PULSAR
+ #include "Particles/PulsarParameters.H"
+#endif
+
// struct whose getPositionUnitBox returns x, y and z for a particle with
// random distribution inside a unit cell.
struct InjectorPositionRandom
@@ -41,14 +45,31 @@ struct InjectorPositionRegular
amrex::RandomEngine const&) const noexcept
{
using namespace amrex;
-
+#ifdef PULSAR
+#if (defined WARPX_DIM_3D) || (defined WARPX_DIM_RZ)
+ int nx, ny, nz;
+ if (PulsarParm::ModifyParticleWtAtInjection == 1) {
+ nx = ref_fac*ppc.x;
+ ny = ref_fac*ppc.y;
+ nz = ref_fac*ppc.z;
+ } else if (PulsarParm::ModifyParticleWtAtInjection == 0) {
+ amrex::Real ninj_per_dim = std::cbrt(PulsarParm::Ninj_fraction);
+ nx = ref_fac*ppc.x*ninj_per_dim;
+ ny = ref_fac*ppc.y*ninj_per_dim;
+ nz = ref_fac*ppc.z*ninj_per_dim;
+ }
+#else
+ amrex::Abort("pulsar sim does not support 2d yet");
+#endif // endif for 3D
+#else // else ifndef PULSAR
int const nx = ref_fac*ppc.x;
int const ny = ref_fac*ppc.y;
#if (defined WARPX_DIM_3D) || (defined WARPX_DIM_RZ)
int const nz = ref_fac*ppc.z;
#else
int const nz = 1;
-#endif
+#endif // 3D ifdef
+#endif // PULSAR ifdef
int const ix_part = i_part / (ny*nz); // written this way backward compatibility
int const iz_part = (i_part-ix_part*(ny*nz)) / ny;
int const iy_part = (i_part-ix_part*(ny*nz)) - ny*iz_part;
@@ -58,6 +79,17 @@ struct InjectorPositionRegular
(0.5_rt + iz_part) / nz
};
}
+
+#ifdef PULSAR
+ AMREX_GPU_HOST_DEVICE
+ amrex::XDim3
+ getppcInEachDim () const noexcept
+ {
+ using namespace amrex;
+ return XDim3{ppc.x, ppc.y, ppc.z};
+ }
+#endif
+
private:
amrex::Dim3 ppc;
};
@@ -123,6 +155,25 @@ struct InjectorPosition
};
}
+#ifdef PULSAR
+ AMREX_GPU_HOST_DEVICE
+ amrex::XDim3
+ getppcInEachDim () const noexcept
+ {
+ switch (type)
+ {
+ case Type::regular:
+ {
+ return object.regular.getppcInEachDim();
+ }
+ default:
+ {
+ return object.regular.getppcInEachDim();
+ }
+ };
+ }
+#endif
+
// bool: whether position specified is within bounds.
AMREX_GPU_HOST_DEVICE
bool
@@ -132,15 +183,26 @@ struct InjectorPosition
y < ymax and y >= ymin and
z < zmax and z >= zmin);
}
-
- // bool: whether position specified is withing pulsar injection region
+
#ifdef PULSAR
+ // bool: whether cell-center position specified is within pulsar injection region
+ // So that these cells can inject particles
+ // a buffer factor of 2*dR (2*dx) is used to ensure cells partially cut by sphere
+ // inject particles
+ AMREX_GPU_HOST_DEVICE
+ bool
+ insidePulsarBoundsCC (amrex::Real r, amrex::Real r_min, amrex::Real r_max, amrex::Real dR_factor) const noexcept
+ {
+ return (r<=(r_max + dR_factor) and r>=(r_min-dR_factor));
+ }
+
+ // bool: whether particle position specified is within pulsar injection region
+ // So that these cells can inject particles
AMREX_GPU_HOST_DEVICE
bool
- insidePulsarBounds (amrex::Real r, amrex::Real R_star, amrex::Real dR_star) const noexcept
+ insidePulsarBounds (amrex::Real r, amrex::Real r_min, amrex::Real r_max) const noexcept
{
- //return (r<=R_star and r>=(R_star-dR_star));
- return (r<=(R_star+dR_star) and r>=(R_star-dR_star));
+ return (r<=(r_max) and r>=(r_min));
}
#endif
diff --git a/Source/Particles/Deposition/ChargeDeposition.H b/Source/Particles/Deposition/ChargeDeposition.H
index 02b3badcb7b..48b0c676f79 100644
--- a/Source/Particles/Deposition/ChargeDeposition.H
+++ b/Source/Particles/Deposition/ChargeDeposition.H
@@ -79,6 +79,25 @@ void doChargeDepositionShapeN(const GetParticlePosition& GetPosition,
amrex::ParticleReal xp, yp, zp;
GetPosition(ip, xp, yp, zp);
+#ifdef PULSAR
+ // temporarily adding this to check if turning off j-deposition
+ // within a region that is corotating makes a difference
+ if (PulsarParm::turnoffdeposition == 1) {
+ const amrex::Real xc = PulsarParm::center_star[0];
+ const amrex::Real yc = PulsarParm::center_star[1];
+ const amrex::Real zc = PulsarParm::center_star[2];
+ // find radius of the particle
+ amrex::Real rp = std::sqrt( (xp-xc)*(xp-xc)
+ + (yp-yc)*(yp-yc)
+ + (zp-zc)*(zp-zc) );
+ // change the locally defined particle weight, wq, to 0
+ // within the region defined by r<=max_radius_nodepos
+ if (rp <= PulsarParm::max_nodepos_radius) {
+ wq = 0.;
+ }
+ }
+#endif
+
// --- Compute shape factors
// x direction
// Get particle position in grid coordinates
diff --git a/Source/Particles/Deposition/CurrentDeposition.H b/Source/Particles/Deposition/CurrentDeposition.H
index 196e275d714..585ae72d49d 100644
--- a/Source/Particles/Deposition/CurrentDeposition.H
+++ b/Source/Particles/Deposition/CurrentDeposition.H
@@ -110,6 +110,25 @@ void doDepositionShapeN(const GetParticlePosition& GetPosition,
amrex::ParticleReal xp, yp, zp;
GetPosition(ip, xp, yp, zp);
+#ifdef PULSAR
+ // temporarily adding this to check if turning off j-deposition
+ // within a region that is corotating makes a difference
+ if (PulsarParm::turnoffdeposition == 1) {
+ const amrex::Real xc = PulsarParm::center_star[0];
+ const amrex::Real yc = PulsarParm::center_star[1];
+ const amrex::Real zc = PulsarParm::center_star[2];
+ // find radius of the particle
+ amrex::Real rp = std::sqrt( (xp-xc)*(xp-xc)
+ + (yp-yc)*(yp-yc)
+ + (zp-zc)*(zp-zc) );
+ // change the locally defined particle weight, wq, to 0
+ // within the region defined by r<=max_radius_nodepos
+ if (rp <= PulsarParm::max_nodepos_radius) {
+ wq = 0.;
+ }
+ }
+#endif
+
const amrex::Real vx = uxp[ip]*gaminv;
const amrex::Real vy = uyp[ip]*gaminv;
const amrex::Real vz = uzp[ip]*gaminv;
@@ -377,6 +396,25 @@ void doEsirkepovDepositionShapeN (const GetParticlePosition& GetPosition,
ParticleReal xp, yp, zp;
GetPosition(ip, xp, yp, zp);
+#ifdef PULSAR
+ // temporarily adding this to check if turning off j-deposition
+ // within a region that is corotating makes a difference
+ if (PulsarParm::turnoffdeposition == 1) {
+ const amrex::Real xc = PulsarParm::center_star[0];
+ const amrex::Real yc = PulsarParm::center_star[1];
+ const amrex::Real zc = PulsarParm::center_star[2];
+ // find radius of the particle
+ amrex::Real rp = std::sqrt( (xp-xc)*(xp-xc)
+ + (yp-yc)*(yp-yc)
+ + (zp-zc)*(zp-zc) );
+ // change the locally defined particle weight, wq, to 0
+ // within the region defined by r<=max_radius_nodepos
+ if (rp <= PulsarParm::max_nodepos_radius) {
+ wq = 0.;
+ }
+ }
+#endif
+
Real const wqx = wq*invdtdx;
#if (defined WARPX_DIM_3D)
Real const wqy = wq*invdtdy;
@@ -696,6 +734,25 @@ void doVayDepositionShapeN (const GetParticlePosition& GetPosition,
amrex::ParticleReal xp, yp, zp;
GetPosition(ip, xp, yp, zp);
+#ifdef PULSAR
+ // temporarily adding this to check if turning off j-deposition
+ // within a region that is corotating makes a difference
+ if (PulsarParm::turnoffdeposition == 1) {
+ const amrex::Real xc = PulsarParm::center_star[0];
+ const amrex::Real yc = PulsarParm::center_star[1];
+ const amrex::Real zc = PulsarParm::center_star[2];
+ // find radius of the particle
+ amrex::Real rp = std::sqrt( (xp-xc)*(xp-xc)
+ + (yp-yc)*(yp-yc)
+ + (zp-zc)*(zp-zc) );
+ // change the locally defined particle weight, wq, to 0
+ // within the region defined by r<=max_radius_nodepos
+ if (rp <= PulsarParm::max_nodepos_radius) {
+ wq = 0.;
+ }
+ }
+#endif
+
// Particle velocities
const amrex::Real vx = uxp[ip] * invgam;
const amrex::Real vy = uyp[ip] * invgam;
diff --git a/Source/Particles/Gather/FieldGather.H b/Source/Particles/Gather/FieldGather.H
index 7f3eeda297f..b8b636474ce 100644
--- a/Source/Particles/Gather/FieldGather.H
+++ b/Source/Particles/Gather/FieldGather.H
@@ -439,13 +439,41 @@ void doGatherShapeN(const GetParticlePosition& getPosition,
getExternalE(ip, Exp[ip], Eyp[ip], Ezp[ip]);
getExternalB(ip, Bxp[ip], Byp[ip], Bzp[ip]);
+#ifdef PULSAR
+ // temporarily adding this to check if turning off EB-gather
+ // of self-consistent fields within a region
+ // makes a difference
+ int dogather = 1;
+ if (PulsarParm::turnoff_plasmaEB_gather == 1) {
+ const amrex::Real xc = PulsarParm::center_star[0];
+ const amrex::Real yc = PulsarParm::center_star[1];
+ const amrex::Real zc = PulsarParm::center_star[2];
+ // find radius of the particle
+ amrex::Real rp = std::sqrt( (xp-xc)*(xp-xc)
+ + (yp-yc)*(yp-yc)
+ + (zp-zc)*(zp-zc) );
+ // set dogather to 0 if particle within user-defined nogather radius
+ if (rp <= PulsarParm::max_nogather_radius) {
+ dogather = 0;
+ }
+ }
+ if (dogather == 1) {
+ doGatherShapeN(
+ xp, yp, zp, Exp[ip], Eyp[ip], Ezp[ip], Bxp[ip], Byp[ip], Bzp[ip],
+ ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr,
+ ex_type, ey_type, ez_type, bx_type, by_type, bz_type,
+ dx_arr, xyzmin_arr, lo, n_rz_azimuthal_modes);
+ }
+#else // if not a pulsar simulation
doGatherShapeN(
xp, yp, zp, Exp[ip], Eyp[ip], Ezp[ip], Bxp[ip], Byp[ip], Bzp[ip],
ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr,
ex_type, ey_type, ez_type, bx_type, by_type, bz_type,
dx_arr, xyzmin_arr, lo, n_rz_azimuthal_modes);
+#endif // end if pulsar
}
);
+
}
/**
diff --git a/Source/Particles/Gather/GatherExternalPulsarFieldOnGrid.H b/Source/Particles/Gather/GatherExternalPulsarFieldOnGrid.H
new file mode 100644
index 00000000000..47315c71bb5
--- /dev/null
+++ b/Source/Particles/Gather/GatherExternalPulsarFieldOnGrid.H
@@ -0,0 +1,562 @@
+/* Copyright 2019 Axel Huebl, David Grote, Maxence Thevenet
+ * Revathi Jambunathan, Weiqun Zhang
+ *
+ * This file is part of WarpX.
+ *
+ * License: BSD-3-Clause-LBNL
+ */
+#ifndef GATHEREXTERNALPULSARFIELDONGRID_H_
+#define GATHEREXTERNALPULSARFIELDONGRID_H_
+
+#ifdef PULSAR
+#include "Particles/Pusher/GetAndSetPosition.H"
+#include "Particles/Gather/GetExternalFields.H"
+#include "Particles/ShapeFactors.H"
+#include "Utils/WarpX_Complex.H"
+#include "Particles/PulsarParameters.H"
+#include
+
+
+/**
+ * Returns the x/y/z component of the E/B applied field for pulsar set-up.
+ *
+ * \param ii, jj, kk : indices in x, y, z
+ * \param mf_type : staggered location of the field
+ * \param domain_lo : physical coordinates of the lower corner of the domain
+ * \param domain_hi : physical coordinates of the upper corner of the domain
+ * \param dx : cell size in x, y, z
+ * \param cur_time : the current physical time of the simulation
+ * \param Field : 0 for Bfield, 1 for Efield
+ * \param comp : x(ncomp=0), y(ncomp=1), or z(ncomp=2) component
+*/
+AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
+amrex::Real GetExternalFieldAtCellLocation(int ii, int jj, int kk,
+ amrex::GpuArray const f_type,
+ amrex::GpuArray const domain_lo,
+ amrex::GpuArray const domain_hi,
+ amrex::GpuArray const dx,
+ amrex::Real cur_time, int Field, int comp)
+{
+ amrex::Real xcell, ycell, zcell;
+ amrex::Real r, theta, phi;
+ amrex::Real Fr, Ftheta, Fphi;
+ amrex::Real Fext_comp;
+ // compute cell coordinates, (x,y,z) corresponding to (ii,jj,kk)
+ // based on the staggered Bx location on the yee-grid
+ PulsarParm::ComputeCellCoordinates( ii, jj, kk, f_type, domain_lo,
+ dx, xcell, ycell, zcell );
+ // Convert (x,y,z) to (r,theta,phi)
+ PulsarParm::ConvertCartesianToSphericalCoord( xcell, ycell, zcell,
+ domain_lo, domain_hi,
+ r, theta, phi);
+ if (Field == 0) {
+ // Compute External vacuum fields of the pulsar (Br, Btheta, Bphi)
+ PulsarParm::ExternalBFieldSpherical( r, theta, phi, cur_time,
+ Fr, Ftheta, Fphi);
+ } else if (Field == 1) {
+ // Compute External vacuum fields of the pulsar (Br, Btheta, Bphi)
+ PulsarParm::ExternalEFieldSpherical( r, theta, phi, cur_time,
+ Fr, Ftheta, Fphi);
+ }
+
+ if (comp == 0) {
+ // Convert (Fr, Ftheta, Fphi) to Xcomponent
+ PulsarParm::ConvertSphericalToCartesianXComponent( Fr, Ftheta, Fphi,
+ r, theta, phi, Fext_comp);
+ } else if (comp == 1) {
+ // Convert (Fr, Ftheta, Fphi) to YComponent
+ PulsarParm::ConvertSphericalToCartesianYComponent( Fr, Ftheta, Fphi,
+ r, theta, phi, Fext_comp);
+ } else if (comp == 2) {
+ // Convert (Fr, Ftheta, Fphi) to ZComponent
+ PulsarParm::ConvertSphericalToCartesianZComponent( Fr, Ftheta, Fphi,
+ r, theta, phi, Fext_comp);
+ }
+
+ return Fext_comp;
+}
+
+
+/**
+ * \brief Field gather for a single particle
+ *
+ * \tparam depos_order Particle shape order
+ * \tparam galerkin_interpolation Lower the order of the particle shape by
+ * this value (0/1) for the parallel field component
+ * \param xp, yp, zp Particle position coordinates
+ * \param Exp, Eyp, Ezp Electric field on particles.
+ * \param Bxp, Byp, Bzp Magnetic field on particles.
+ * \param ex_arr ey_arr ez_arr Array4 of the electric field, either full array or tile.
+ * \param bx_arr by_arr bz_arr Array4 of the magnetic field, either full array or tile.
+ * \param ex_type, ey_type, ez_type IndexType of the electric field
+ * \param bx_type, by_type, bz_type IndexType of the magnetic field
+ * \param dx 3D cell spacing
+ * \param xyzmin Physical lower bounds of domain in x, y, z.
+ * \param lo Index lower bounds of domain.
+ * \param n_rz_azimuthal_modes Number of azimuthal modes when using RZ geometry
+ */
+template
+AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
+void doPulsarFieldGatherShapeN (const amrex::ParticleReal xp,
+ const amrex::ParticleReal yp,
+ const amrex::ParticleReal zp,
+ amrex::ParticleReal& Exp,
+ amrex::ParticleReal& Eyp,
+ amrex::ParticleReal& Ezp,
+ amrex::ParticleReal& Bxp,
+ amrex::ParticleReal& Byp,
+ amrex::ParticleReal& Bzp,
+ amrex::Array4 const& ex_arr,
+ amrex::Array4 const& ey_arr,
+ amrex::Array4 const& ez_arr,
+ amrex::Array4 const& bx_arr,
+ amrex::Array4 const& by_arr,
+ amrex::Array4 const& bz_arr,
+ const amrex::IndexType ex_type,
+ const amrex::IndexType ey_type,
+ const amrex::IndexType ez_type,
+ const amrex::IndexType bx_type,
+ const amrex::IndexType by_type,
+ const amrex::IndexType bz_type,
+ const amrex::GpuArray& dx,
+ const amrex::GpuArray& xyzmin,
+ const amrex::Dim3& lo,
+ const long n_rz_azimuthal_modes,
+ amrex::GpuArray const& dom_lo = {},
+ amrex::GpuArray const& dom_hi = {},
+ amrex::Real cur_time = 0._rt )
+{
+ using namespace amrex;
+
+#if defined(WARPX_DIM_XZ)
+ amrex::Abort("pulsar does not work in 2D");
+#endif
+
+#ifndef WARPX_DIM_RZ
+ amrex::Abort("pulsar does not work in RZ");
+#endif
+
+ const amrex::Real dxi = 1.0_rt/dx[0];
+ const amrex::Real dyi = 1.0_rt/dx[1];
+ const amrex::Real dzi = 1.0_rt/dx[2];
+
+ const amrex::Real xmin = xyzmin[0];
+ const amrex::Real ymin = xyzmin[1];
+ const amrex::Real zmin = xyzmin[2];
+
+ constexpr int zdir = (AMREX_SPACEDIM - 1);
+ constexpr int NODE = amrex::IndexType::NODE;
+ constexpr int CELL = amrex::IndexType::CELL;
+
+ // store staggering of ex-bz in GpuArray
+ amrex::GpuArray Ex_stag, Ey_stag, Ez_stag, Bx_stag, By_stag, Bz_stag;
+ for (int idim = 0; idim < 3; ++idim)
+ {
+ Ex_stag[idim] = ex_type[idim];
+ Ey_stag[idim] = ey_type[idim];
+ Ez_stag[idim] = ez_type[idim];
+ Bx_stag[idim] = bx_type[idim];
+ By_stag[idim] = by_type[idim];
+ Bz_stag[idim] = bz_type[idim];
+ }
+ // --- Compute shape factors
+ // x direction
+ // Get particle position
+ const amrex::Real x = (xp-xmin)*dxi;
+
+ // j_[eb][xyz] leftmost grid point in x that the particle touches for the centering of each current
+ // sx_[eb][xyz] shape factor along x for the centering of each current
+ // There are only two possible centerings, node or cell centered, so at most only two shape factor
+ // arrays will be needed.
+ amrex::Real sx_node[depos_order + 1];
+ amrex::Real sx_cell[depos_order + 1];
+ amrex::Real sx_node_galerkin[depos_order + 1 - galerkin_interpolation] = {0._rt};
+ amrex::Real sx_cell_galerkin[depos_order + 1 - galerkin_interpolation] = {0._rt};
+
+ int j_node = 0;
+ int j_cell = 0;
+ int j_node_v = 0;
+ int j_cell_v = 0;
+ Compute_shape_factor< depos_order > const compute_shape_factor;
+ Compute_shape_factor const compute_shape_factor_galerkin;
+ if ((ey_type[0] == NODE) || (ez_type[0] == NODE) || (bx_type[0] == NODE)) {
+ j_node = compute_shape_factor(sx_node, x);
+ }
+ if ((ey_type[0] == CELL) || (ez_type[0] == CELL) || (bx_type[0] == CELL)) {
+ j_cell = compute_shape_factor(sx_cell, x - 0.5_rt);
+ }
+ if ((ex_type[0] == NODE) || (by_type[0] == NODE) || (bz_type[0] == NODE)) {
+ j_node_v = compute_shape_factor_galerkin(sx_node_galerkin, x);
+ }
+ if ((ex_type[0] == CELL) || (by_type[0] == CELL) || (bz_type[0] == CELL)) {
+ j_cell_v = compute_shape_factor_galerkin(sx_cell_galerkin, x - 0.5_rt);
+ }
+ const amrex::Real (&sx_ex)[depos_order + 1 - galerkin_interpolation] = ((ex_type[0] == NODE) ? sx_node_galerkin : sx_cell_galerkin);
+ const amrex::Real (&sx_ey)[depos_order + 1 ] = ((ey_type[0] == NODE) ? sx_node : sx_cell );
+ const amrex::Real (&sx_ez)[depos_order + 1 ] = ((ez_type[0] == NODE) ? sx_node : sx_cell );
+ const amrex::Real (&sx_bx)[depos_order + 1 ] = ((bx_type[0] == NODE) ? sx_node : sx_cell );
+ const amrex::Real (&sx_by)[depos_order + 1 - galerkin_interpolation] = ((by_type[0] == NODE) ? sx_node_galerkin : sx_cell_galerkin);
+ const amrex::Real (&sx_bz)[depos_order + 1 - galerkin_interpolation] = ((bz_type[0] == NODE) ? sx_node_galerkin : sx_cell_galerkin);
+ int const j_ex = ((ex_type[0] == NODE) ? j_node_v : j_cell_v);
+ int const j_ey = ((ey_type[0] == NODE) ? j_node : j_cell );
+ int const j_ez = ((ez_type[0] == NODE) ? j_node : j_cell );
+ int const j_bx = ((bx_type[0] == NODE) ? j_node : j_cell );
+ int const j_by = ((by_type[0] == NODE) ? j_node_v : j_cell_v);
+ int const j_bz = ((bz_type[0] == NODE) ? j_node_v : j_cell_v);
+
+ // y direction
+ const amrex::Real y = (yp-ymin)*dyi;
+ amrex::Real sy_node[depos_order + 1];
+ amrex::Real sy_cell[depos_order + 1];
+ amrex::Real sy_node_v[depos_order + 1 - galerkin_interpolation];
+ amrex::Real sy_cell_v[depos_order + 1 - galerkin_interpolation];
+ int k_node = 0;
+ int k_cell = 0;
+ int k_node_v = 0;
+ int k_cell_v = 0;
+ if ((ex_type[1] == NODE) || (ez_type[1] == NODE) || (by_type[1] == NODE)) {
+ k_node = compute_shape_factor(sy_node, y);
+ }
+ if ((ex_type[1] == CELL) || (ez_type[1] == CELL) || (by_type[1] == CELL)) {
+ k_cell = compute_shape_factor(sy_cell, y - 0.5_rt);
+ }
+ if ((ey_type[1] == NODE) || (bx_type[1] == NODE) || (bz_type[1] == NODE)) {
+ k_node_v = compute_shape_factor_galerkin(sy_node_v, y);
+ }
+ if ((ey_type[1] == CELL) || (bx_type[1] == CELL) || (bz_type[1] == CELL)) {
+ k_cell_v = compute_shape_factor_galerkin(sy_cell_v, y - 0.5_rt);
+ }
+ const amrex::Real (&sy_ex)[depos_order + 1 ] = ((ex_type[1] == NODE) ? sy_node : sy_cell );
+ const amrex::Real (&sy_ey)[depos_order + 1 - galerkin_interpolation] = ((ey_type[1] == NODE) ? sy_node_v : sy_cell_v);
+ const amrex::Real (&sy_ez)[depos_order + 1 ] = ((ez_type[1] == NODE) ? sy_node : sy_cell );
+ const amrex::Real (&sy_bx)[depos_order + 1 - galerkin_interpolation] = ((bx_type[1] == NODE) ? sy_node_v : sy_cell_v);
+ const amrex::Real (&sy_by)[depos_order + 1 ] = ((by_type[1] == NODE) ? sy_node : sy_cell );
+ const amrex::Real (&sy_bz)[depos_order + 1 - galerkin_interpolation] = ((bz_type[1] == NODE) ? sy_node_v : sy_cell_v);
+ int const k_ex = ((ex_type[1] == NODE) ? k_node : k_cell );
+ int const k_ey = ((ey_type[1] == NODE) ? k_node_v : k_cell_v);
+ int const k_ez = ((ez_type[1] == NODE) ? k_node : k_cell );
+ int const k_bx = ((bx_type[1] == NODE) ? k_node_v : k_cell_v);
+ int const k_by = ((by_type[1] == NODE) ? k_node : k_cell );
+ int const k_bz = ((bz_type[1] == NODE) ? k_node_v : k_cell_v);
+
+ // z direction
+ const amrex::Real z = (zp-zmin)*dzi;
+ amrex::Real sz_node[depos_order + 1];
+ amrex::Real sz_cell[depos_order + 1];
+ amrex::Real sz_node_v[depos_order + 1 - galerkin_interpolation];
+ amrex::Real sz_cell_v[depos_order + 1 - galerkin_interpolation];
+ int l_node = 0;
+ int l_cell = 0;
+ int l_node_v = 0;
+ int l_cell_v = 0;
+ if ((ex_type[zdir] == NODE) || (ey_type[zdir] == NODE) || (bz_type[zdir] == NODE)) {
+ l_node = compute_shape_factor(sz_node, z);
+ }
+ if ((ex_type[zdir] == CELL) || (ey_type[zdir] == CELL) || (bz_type[zdir] == CELL)) {
+ l_cell = compute_shape_factor(sz_cell, z - 0.5_rt);
+ }
+ if ((ez_type[zdir] == NODE) || (bx_type[zdir] == NODE) || (by_type[zdir] == NODE)) {
+ l_node_v = compute_shape_factor_galerkin(sz_node_v, z);
+ }
+ if ((ez_type[zdir] == CELL) || (bx_type[zdir] == CELL) || (by_type[zdir] == CELL)) {
+ l_cell_v = compute_shape_factor_galerkin(sz_cell_v, z - 0.5_rt);
+ }
+ const amrex::Real (&sz_ex)[depos_order + 1 ] = ((ex_type[zdir] == NODE) ? sz_node : sz_cell );
+ const amrex::Real (&sz_ey)[depos_order + 1 ] = ((ey_type[zdir] == NODE) ? sz_node : sz_cell );
+ const amrex::Real (&sz_ez)[depos_order + 1 - galerkin_interpolation] = ((ez_type[zdir] == NODE) ? sz_node_v : sz_cell_v);
+ const amrex::Real (&sz_bx)[depos_order + 1 - galerkin_interpolation] = ((bx_type[zdir] == NODE) ? sz_node_v : sz_cell_v);
+ const amrex::Real (&sz_by)[depos_order + 1 - galerkin_interpolation] = ((by_type[zdir] == NODE) ? sz_node_v : sz_cell_v);
+ const amrex::Real (&sz_bz)[depos_order + 1 ] = ((bz_type[zdir] == NODE) ? sz_node : sz_cell );
+ int const l_ex = ((ex_type[zdir] == NODE) ? l_node : l_cell );
+ int const l_ey = ((ey_type[zdir] == NODE) ? l_node : l_cell );
+ int const l_ez = ((ez_type[zdir] == NODE) ? l_node_v : l_cell_v);
+ int const l_bx = ((bx_type[zdir] == NODE) ? l_node_v : l_cell_v);
+ int const l_by = ((by_type[zdir] == NODE) ? l_node_v : l_cell_v);
+ int const l_bz = ((bz_type[zdir] == NODE) ? l_node : l_cell );
+
+
+ // Each field is gathered in a separate block of
+ // AMREX_SPACEDIM nested loops because the deposition
+ // order can differ for each component of each field
+ // when galerkin_interpolation is set to 1
+
+ // Gather Pulsar external field using grid resolution on particle Exp
+ for (int iz=0; iz<=depos_order; iz++){
+ for (int iy=0; iy<=depos_order; iy++){
+ for (int ix=0; ix<= depos_order - galerkin_interpolation; ix++){
+ // Add the external field contribution for pulsar
+ int ii = lo.x + j_ex + ix;
+ int jj = lo.y + k_ex + iy;
+ int kk = lo.z + l_ex + iz;
+ int Field = 1; // 1 for Efield, 0 for Bfield
+ int comp = 0; // 0 for xcomponent
+ amrex::Real ex_ext = GetExternalFieldAtCellLocation( ii, jj, kk,
+ Ex_stag, dom_lo, dom_hi, dx,
+ cur_time, Field, comp);
+ Exp += sx_ex[ix]*sy_ex[iy]*sz_ex[iz]*ex_ext;
+ }
+ }
+ }
+ // Gather Pulsar external field using grid resolution on particle Eyp
+ for (int iz=0; iz<=depos_order; iz++){
+ for (int iy=0; iy<= depos_order - galerkin_interpolation; iy++){
+ for (int ix=0; ix<=depos_order; ix++){
+ // Add the external field contribution for pulsar
+ int ii = lo.x + j_ey + ix;
+ int jj = lo.y + k_ey + iy;
+ int kk = lo.z + l_ey + iz;
+ int Field = 1; // 1 for Efield, 0 for Bfield
+ int comp = 1; // 1 for ycomponent
+ amrex::Real ey_ext = GetExternalFieldAtCellLocation( ii, jj, kk,
+ Ey_stag, dom_lo, dom_hi, dx,
+ cur_time, Field, comp);
+ Eyp += sx_ey[ix]*sy_ey[iy]*sz_ey[iz]*ey_ext;
+ }
+ }
+ }
+ // Gather Pulsar external field using grid resolution on particle Ezp
+ for (int iz=0; iz<= depos_order - galerkin_interpolation; iz++){
+ for (int iy=0; iy<=depos_order; iy++){
+ for (int ix=0; ix<=depos_order; ix++){
+ // Add the external field contribution for pulsar
+ int ii = lo.x + j_ez + ix;
+ int jj = lo.y + k_ez + iy;
+ int kk = lo.z + l_ez + iz;
+ int Field = 1; // 1 for Efield, 0 for Bfield
+ int comp = 2; // 2 for zcomponent
+ amrex::Real ez_ext = GetExternalFieldAtCellLocation( ii, jj, kk,
+ Ez_stag, dom_lo, dom_hi, dx,
+ cur_time, Field, comp);
+ Ezp += sx_ez[ix]*sy_ez[iy]*sz_ez[iz]*ez_ext;
+ }
+ }
+ }
+ // Gather Pulsar external field using grid resolution on particle Bzp
+ for (int iz=0; iz<=depos_order; iz++){
+ for (int iy=0; iy<= depos_order - galerkin_interpolation; iy++){
+ for (int ix=0; ix<= depos_order - galerkin_interpolation; ix++){
+ // Add the external field contribution for pulsar
+ int ii = lo.x + j_bz + ix;
+ int jj = lo.y + k_bz + iy;
+ int kk = lo.z + l_bz + iz;
+ int Field = 0; // 1 for Efield, 0 for Bfield
+ int comp = 2; // 2 for zcomponent
+ amrex::Real bz_ext = GetExternalFieldAtCellLocation( ii, jj, kk,
+ Bz_stag, dom_lo, dom_hi, dx,
+ cur_time, Field, comp);
+ Bzp += sx_bz[ix]*sy_bz[iy]*sz_bz[iz]*bz_ext;
+ }
+ }
+ }
+ // Gather Pulsar external field using grid resolution on particle Byp
+ for (int iz=0; iz<= depos_order - galerkin_interpolation; iz++){
+ for (int iy=0; iy<=depos_order; iy++){
+ for (int ix=0; ix<= depos_order - galerkin_interpolation; ix++){
+ // Add the external field contribution for pulsar
+ int ii = lo.x + j_by + ix;
+ int jj = lo.y + k_by + iy;
+ int kk = lo.z + l_by + iz;
+ int Field = 0; // 1 for Efield, 0 for Bfield
+ int comp = 1; // 1 for ycomponent
+ amrex::Real by_ext = GetExternalFieldAtCellLocation( ii, jj, kk,
+ By_stag, dom_lo, dom_hi, dx,
+ cur_time, Field, comp);
+ Byp += sx_by[ix]*sy_by[iy]*sz_by[iz]*by_ext;
+ }
+ }
+ }
+ // Gather Pulsar external field using grid resolution on particle Bxp
+ for (int iz=0; iz<= depos_order - galerkin_interpolation; iz++){
+ for (int iy=0; iy<= depos_order - galerkin_interpolation; iy++){
+ for (int ix=0; ix<=depos_order; ix++){
+ // Add the external field contribution for pulsar
+ int ii = lo.x + j_bx + ix;
+ int jj = lo.y + k_bx + iy;
+ int kk = lo.z + l_bx + iz;
+ int Field = 0; // 1 for Efield, 0 for Bfield
+ int comp = 0; // 0 for xcomponent
+ amrex::Real bx_ext = GetExternalFieldAtCellLocation( ii, jj, kk,
+ Bx_stag, dom_lo, dom_hi, dx,
+ cur_time, Field, comp);
+ Bxp += sx_bx[ix]*sy_bx[iy]*sz_bx[iz]*bx_ext;
+ }
+ }
+ }
+}
+
+
+
+
+/**
+ * \brief Field gather for particles
+ *
+ * /param getPosition : A functor for returning the particle position.
+ * /param getExternalEField : A functor for assigning the external E field.
+ * /param getExternalBField : A functor for assigning the external B field.
+ * \param Exp, Eyp, Ezp : Pointer to array of electric field on particles.
+ * \param Bxp, Byp, Bzp : Pointer to array of magnetic field on particles.
+ * \param exfab eyfab ezfab : Array4 of the electric field, either full array or tile.
+ * \param ezfab bxfab bzfab : Array4 of the magnetic field, either full array or tile.
+ * \param np_to_gather : Number of particles for which field is gathered.
+ * \param dx : 3D cell size
+ * \param xyzmin : Physical lower bounds of domain.
+ * \param lo : Index lower bounds of domain.
+ * \param n_rz_azimuthal_modes : Number of azimuthal modes when using RZ geometry
+ */
+template
+void doPulsarFieldGatherShapeN(const GetParticlePosition& getPosition,
+ const GetExternalEField& getExternalE, const GetExternalBField& getExternalB,
+ amrex::ParticleReal * const Exp, amrex::ParticleReal * const Eyp,
+ amrex::ParticleReal * const Ezp, amrex::ParticleReal * const Bxp,
+ amrex::ParticleReal * const Byp, amrex::ParticleReal * const Bzp,
+ amrex::FArrayBox const * const exfab,
+ amrex::FArrayBox const * const eyfab,
+ amrex::FArrayBox const * const ezfab,
+ amrex::FArrayBox const * const bxfab,
+ amrex::FArrayBox const * const byfab,
+ amrex::FArrayBox const * const bzfab,
+ const long np_to_gather,
+ const std::array& dx,
+ const std::array& xyzmin,
+ const amrex::Dim3 lo,
+ const long n_rz_azimuthal_modes,
+ amrex::GpuArray const& dom_lo = {},
+ amrex::GpuArray const& dom_hi = {},
+ amrex::Real cur_time = 0._rt )
+{
+
+ amrex::GpuArray dx_arr = {dx[0], dx[1], dx[2]};
+ amrex::GpuArray xyzmin_arr = {xyzmin[0], xyzmin[1], xyzmin[2]};
+
+ amrex::Array4 const& ex_arr = exfab->array();
+ amrex::Array4 const& ey_arr = eyfab->array();
+ amrex::Array4 const& ez_arr = ezfab->array();
+ amrex::Array4 const& bx_arr = bxfab->array();
+ amrex::Array4 const& by_arr = byfab->array();
+ amrex::Array4 const& bz_arr = bzfab->array();
+
+ amrex::IndexType const ex_type = exfab->box().ixType();
+ amrex::IndexType const ey_type = eyfab->box().ixType();
+ amrex::IndexType const ez_type = ezfab->box().ixType();
+ amrex::IndexType const bx_type = bxfab->box().ixType();
+ amrex::IndexType const by_type = byfab->box().ixType();
+ amrex::IndexType const bz_type = bzfab->box().ixType();
+
+ // Loop over particles and gather fields from
+ // {e,b}{x,y,z}_arr to {E,B}{xyz}p.
+ amrex::ParallelFor(
+ np_to_gather,
+ [=] AMREX_GPU_DEVICE (long ip) {
+
+ amrex::ParticleReal xp, yp, zp;
+ getPosition(ip, xp, yp, zp);
+ getExternalE(ip, Exp[ip], Eyp[ip], Ezp[ip]);
+ getExternalB(ip, Bxp[ip], Byp[ip], Bzp[ip]);
+
+ doPulsarFieldGatherShapeN(
+ xp, yp, zp, Exp[ip], Eyp[ip], Ezp[ip], Bxp[ip], Byp[ip], Bzp[ip],
+ ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr,
+ ex_type, ey_type, ez_type, bx_type, by_type, bz_type,
+ dx_arr, xyzmin_arr, lo, n_rz_azimuthal_modes,
+ dom_lo, dom_hi, cur_time);
+ });
+}
+
+/**
+ * \brief Field gather for a single particle
+ *
+ * /param xp, yp, zp : Particle position coordinates
+ * \param Exp, Eyp, Ezp : Electric field on particles.
+ * \param Bxp, Byp, Bzp : Magnetic field on particles.
+ * \param ex_arr ey_arr ez_arr : Array4 of the electric field, either full array or tile.
+ * \param bx_arr by_arr bz_arr : Array4 of the magnetic field, either full array or tile.
+ * \param ex_type, ey_type, ez_type : IndexType of the electric field
+ * \param bx_type, by_type, bz_type : IndexType of the magnetic field
+ * \param dx : 3D cell spacing
+ * \param xyzmin : Physical lower bounds of domain in x, y, z.
+ * \param lo : Index lower bounds of domain.
+ * \param n_rz_azimuthal_modes : Number of azimuthal modes when using RZ geometry
+ * \param nox : order of the particle shape function
+ * \param galerkin_interpolation : whether to use lower order in v
+ */
+AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
+void doPulsarFieldGatherShapeN (const amrex::ParticleReal xp,
+ const amrex::ParticleReal yp,
+ const amrex::ParticleReal zp,
+ amrex::ParticleReal& Exp,
+ amrex::ParticleReal& Eyp,
+ amrex::ParticleReal& Ezp,
+ amrex::ParticleReal& Bxp,
+ amrex::ParticleReal& Byp,
+ amrex::ParticleReal& Bzp,
+ amrex::Array4 const& ex_arr,
+ amrex::Array4 const& ey_arr,
+ amrex::Array4 const& ez_arr,
+ amrex::Array4 const& bx_arr,
+ amrex::Array4 const& by_arr,
+ amrex::Array4 const& bz_arr,
+ const amrex::IndexType ex_type,
+ const amrex::IndexType ey_type,
+ const amrex::IndexType ez_type,
+ const amrex::IndexType bx_type,
+ const amrex::IndexType by_type,
+ const amrex::IndexType bz_type,
+ const amrex::GpuArray& dx_arr,
+ const amrex::GpuArray& xyzmin_arr,
+ const amrex::Dim3& lo,
+ const int n_rz_azimuthal_modes,
+ const int nox,
+ const bool galerkin_interpolation,
+ amrex::GpuArray const& dom_lo = {},
+ amrex::GpuArray const& dom_hi = {},
+ amrex::Real cur_time = 0._rt )
+{
+ if (galerkin_interpolation) {
+ if (nox == 1) {
+ doPulsarFieldGatherShapeN<1,1>(xp, yp, zp, Exp, Eyp, Ezp, Bxp, Byp, Bzp,
+ ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr,
+ ex_type, ey_type, ez_type, bx_type, by_type, bz_type,
+ dx_arr, xyzmin_arr, lo, n_rz_azimuthal_modes,
+ dom_lo, dom_hi, cur_time
+ );
+ } else if (nox == 2) {
+ doPulsarFieldGatherShapeN<2,1>(xp, yp, zp, Exp, Eyp, Ezp, Bxp, Byp, Bzp,
+ ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr,
+ ex_type, ey_type, ez_type, bx_type, by_type, bz_type,
+ dx_arr, xyzmin_arr, lo, n_rz_azimuthal_modes,
+ dom_lo, dom_hi, cur_time
+ );
+ } else if (nox == 3) {
+ doPulsarFieldGatherShapeN<3,1>(xp, yp, zp, Exp, Eyp, Ezp, Bxp, Byp, Bzp,
+ ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr,
+ ex_type, ey_type, ez_type, bx_type, by_type, bz_type,
+ dx_arr, xyzmin_arr, lo, n_rz_azimuthal_modes,
+ dom_lo, dom_hi, cur_time
+ );
+ }
+ } else {
+ if (nox == 1) {
+ doPulsarFieldGatherShapeN<1,0>(xp, yp, zp, Exp, Eyp, Ezp, Bxp, Byp, Bzp,
+ ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr,
+ ex_type, ey_type, ez_type, bx_type, by_type, bz_type,
+ dx_arr, xyzmin_arr, lo, n_rz_azimuthal_modes,
+ dom_lo, dom_hi, cur_time
+ );
+ } else if (nox == 2) {
+ doPulsarFieldGatherShapeN<2,0>(xp, yp, zp, Exp, Eyp, Ezp, Bxp, Byp, Bzp,
+ ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr,
+ ex_type, ey_type, ez_type, bx_type, by_type, bz_type,
+ dx_arr, xyzmin_arr, lo, n_rz_azimuthal_modes,
+ dom_lo, dom_hi, cur_time);
+ } else if (nox == 3) {
+ doPulsarFieldGatherShapeN<3,0>(xp, yp, zp, Exp, Eyp, Ezp, Bxp, Byp, Bzp,
+ ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr,
+ ex_type, ey_type, ez_type, bx_type, by_type, bz_type,
+ dx_arr, xyzmin_arr, lo, n_rz_azimuthal_modes,
+ dom_lo, dom_hi, cur_time);
+ }
+ }
+}
+
+#endif // ifdef pulsar
+#endif // GATHEREXTERNALPULSARFIELDONGRID_H_
diff --git a/Source/Particles/Gather/GetExternalFields.H b/Source/Particles/Gather/GetExternalFields.H
index 91f868b8942..15993d5d579 100644
--- a/Source/Particles/Gather/GetExternalFields.H
+++ b/Source/Particles/Gather/GetExternalFields.H
@@ -3,18 +3,12 @@
#include "Particles/WarpXParticleContainer.H"
#include "Particles/Pusher/GetAndSetPosition.H"
-#ifdef PULSAR
- #include "Particles/PulsarParameters.H"
-#endif
#include
#include
enum ExternalFieldInitType { Constant, Parser
-#ifdef PULSAR
- , Pulsar_Efield, Pulsar_Bfield
-#endif
};
/** \brief Base class for functors that assign external
@@ -52,20 +46,6 @@ struct GetExternalField
field_y += m_yfield_partparser(x, y, z, m_time);
field_z += m_zfield_partparser(x, y, z, m_time);
}
-#ifdef PULSAR
- else if (m_type == Pulsar_Efield)
- {
- amrex::ParticleReal x, y, z;
- m_get_position(i, x, y, z);
- PulsarParm::PulsarEField(x, y, z, field_x, field_y, field_z, m_time);
- }
- else if (m_type == Pulsar_Bfield)
- {
- amrex::ParticleReal x, y, z;
- m_get_position(i, x, y, z);
- PulsarParm::PulsarBField(x, y, z, field_x, field_y, field_z, m_time);
- }
-#endif
else
{
amrex::Abort("ExternalFieldInitType not known!!! \n");
diff --git a/Source/Particles/Gather/GetExternalFields.cpp b/Source/Particles/Gather/GetExternalFields.cpp
index e8fbdd6a82b..c1fbe49daca 100644
--- a/Source/Particles/Gather/GetExternalFields.cpp
+++ b/Source/Particles/Gather/GetExternalFields.cpp
@@ -21,14 +21,6 @@ GetExternalEField::GetExternalEField (const WarpXParIter& a_pti, int a_offset) n
m_yfield_partparser = getParser(mypc.m_Ey_particle_parser);
m_zfield_partparser = getParser(mypc.m_Ez_particle_parser);
}
-#ifdef PULSAR
- if (PulsarParm::EB_external == 1)
- {
- m_type = Pulsar_Efield;
- m_time = warpx.gett_new(a_pti.GetLevel());
- m_get_position = GetParticlePosition(a_pti, a_offset);
- }
-#endif
}
GetExternalBField::GetExternalBField (const WarpXParIter& a_pti, int a_offset) noexcept
@@ -51,12 +43,4 @@ GetExternalBField::GetExternalBField (const WarpXParIter& a_pti, int a_offset) n
m_yfield_partparser = getParser(mypc.m_By_particle_parser);
m_zfield_partparser = getParser(mypc.m_Bz_particle_parser);
}
-#ifdef PULSAR
- if (PulsarParm::EB_external == 1)
- {
- m_type = Pulsar_Bfield;
- m_time = warpx.gett_new(a_pti.GetLevel());
- m_get_position = GetParticlePosition(a_pti, a_offset);
- }
-#endif
}
diff --git a/Source/Particles/MultiParticleContainer.H b/Source/Particles/MultiParticleContainer.H
index cf80106e587..f3395cb0576 100644
--- a/Source/Particles/MultiParticleContainer.H
+++ b/Source/Particles/MultiParticleContainer.H
@@ -273,8 +273,8 @@ public:
#ifdef PULSAR
std::string m_E_ext_particle_coord = "cartesian";
std::string m_B_ext_particle_coord = "cartesian";
- void PulsarParticleInjection();
void PulsarParticleRemoval();
+ void PulsarParticleInjection();
#endif
protected:
diff --git a/Source/Particles/PhysicalParticleContainer.H b/Source/Particles/PhysicalParticleContainer.H
index 036edf6d217..335fbd9f514 100644
--- a/Source/Particles/PhysicalParticleContainer.H
+++ b/Source/Particles/PhysicalParticleContainer.H
@@ -329,8 +329,8 @@ public:
#endif
#ifdef PULSAR
- virtual void PulsarParticleInjection () override;
virtual void PulsarParticleRemoval () override;
+ virtual void PulsarParticleInjection () override;
#endif
protected:
diff --git a/Source/Particles/PhysicalParticleContainer.cpp b/Source/Particles/PhysicalParticleContainer.cpp
index 106ef66e967..0acd3ef4168 100644
--- a/Source/Particles/PhysicalParticleContainer.cpp
+++ b/Source/Particles/PhysicalParticleContainer.cpp
@@ -24,6 +24,7 @@
#include "Utils/WarpXAlgorithmSelection.H"
#ifdef PULSAR
#include "Particles/PulsarParameters.H"
+ #include "Particles/Gather/GatherExternalPulsarFieldOnGrid.H"
#endif
#include
@@ -210,8 +211,10 @@ void PhysicalParticleContainer::InitData ()
// Init ionization module here instead of in the PhysicalParticleContainer
// constructor because dt is required
if (do_field_ionization) {InitIonizationModule();}
+#ifndef PULSAR
AddParticles(0); // Note - add on level 0
Redistribute(); // We then redistribute
+#endif
}
void PhysicalParticleContainer::MapParticletoBoostedFrame (
@@ -546,6 +549,12 @@ PhysicalParticleContainer::AddPlasma (int lev, RealBox part_realbox)
#elif AMREX_SPACEDIM==2
scale_fac = dx[0]*dx[1]/num_ppc;
#endif
+#ifdef PULSAR
+ // modifying particle weight to achieve fractional injection
+ if (PulsarParm::ModifyParticleWtAtInjection == 1) {
+ scale_fac = scale_fac*PulsarParm::Ninj_fraction;
+ }
+#endif
defineAllParticleTiles();
@@ -580,7 +589,6 @@ PhysicalParticleContainer::AddPlasma (int lev, RealBox part_realbox)
const MultiFab& Ex_mf = WarpX::GetInstance().getEfield(lev,0);
const MultiFab& Ey_mf = WarpX::GetInstance().getEfield(lev,1);
const MultiFab& Ez_mf = WarpX::GetInstance().getEfield(lev,2);
- //const MultiFab& rho_mf = WarpX::GetInstance().getRho(lev);
const MultiFab& rho_mf = WarpX::GetInstance().getrho_fp(lev);
const Real dt = WarpX::GetInstance().getdt(0);
#endif
@@ -590,6 +598,8 @@ PhysicalParticleContainer::AddPlasma (int lev, RealBox part_realbox)
bool radially_weighted = plasma_injector->radially_weighted;
#endif
+ int Nmax_particles = 0;
+ int valid_particles_beforeAdd = TotalNumberOfParticles();
MFItInfo info;
if (do_tiling && Gpu::notInLaunchRegion()) {
@@ -600,7 +610,6 @@ PhysicalParticleContainer::AddPlasma (int lev, RealBox part_realbox)
#pragma omp parallel if (not WarpX::serialize_ics)
#endif
-
for (MFIter mfi = MakeMFIter(lev, info); mfi.isValid(); ++mfi)
{
if (cost && WarpX::load_balance_costs_update_algo == LoadBalanceCostsUpdateAlgo::Timers)
@@ -652,7 +661,20 @@ PhysicalParticleContainer::AddPlasma (int lev, RealBox part_realbox)
{AMREX_D_DECL(overlap_realbox.lo(0),
overlap_realbox.lo(1),
overlap_realbox.lo(2))};
-
+#ifdef PULSAR
+ const FArrayBox& Ex_fab = Ex_mf[mfi];
+ const FArrayBox& Ey_fab = Ey_mf[mfi];
+ const FArrayBox& Ez_fab = Ez_mf[mfi];
+ const FArrayBox& rho_fab = rho_mf[mfi];
+ const Dim3 Ex_lo = lbound(mfi.tilebox());
+ const Dim3 Ey_lo = lbound(mfi.tilebox());
+ const Dim3 Ez_lo = lbound(mfi.tilebox());
+ amrex::Array4 const& ex_arr = Ex_fab.array();
+ amrex::Array4 const& ey_arr = Ey_fab.array();
+ amrex::Array4 const& ez_arr = Ez_fab.array();
+ amrex::Array4 const& rho_arr = rho_fab.array();
+ const Real q_pm = this->charge;
+#endif
// count the number of particles that each cell in overlap_box could add
Gpu::DeviceVector counts(overlap_box.numPts(), 0);
Gpu::DeviceVector offset(overlap_box.numPts());
@@ -668,9 +690,40 @@ PhysicalParticleContainer::AddPlasma (int lev, RealBox part_realbox)
lo.z = applyBallisticCorrection(lo, inj_mom, gamma_boost, beta_boost, t);
hi.z = applyBallisticCorrection(hi, inj_mom, gamma_boost, beta_boost, t);
-
- if (inj_pos->overlapsWith(lo, hi))
+#ifdef PULSAR
+ amrex::Real xc = PulsarParm::center_star[0];
+ amrex::Real yc = PulsarParm::center_star[1];
+ amrex::Real zc = PulsarParm::center_star[2];
+ // Find cell-center
+ amrex::Real x, y, z;
+ x = overlap_corner[0] + i*dx[0] + 0.5*dx[0];
+ y = overlap_corner[1] + j*dx[1] + 0.5*dx[1];
+ z = overlap_corner[2] + k*dx[2] + 0.5*dx[2];
+ // radius of the cell-center
+ amrex::Real rad = std::sqrt( (x-xc)*(x-xc) + (y-yc)*(y-yc) + (z-zc)*(z-zc));
+ // Adding buffer-factor to ensure all cells that intersect the ring
+ // inject particles
+ amrex::Real buffer_factor = 2.0;
+ // is cell-center inside the pulsar ring
+ if (inj_pos->insidePulsarBoundsCC( rad, PulsarParm::particle_inject_rmin,
+ PulsarParm::particle_inject_rmax,
+ PulsarParm::dR_star*buffer_factor) );
{
+ auto index = overlap_box.index(iv);
+ const amrex::XDim3 ppc_per_dim = inj_pos->getppcInEachDim();
+ if (PulsarParm::ModifyParticleWtAtInjection == 1) {
+ // instead of modiying number of particles, the weight is changed
+ pcounts[index] = num_ppc;
+ } else if (PulsarParm::ModifyParticleWtAtInjection == 0) {
+ // Modiying number of particles injected
+ // (could lead to round-off errors)
+ pcounts[index] = int(ppc_per_dim.x*std::cbrt(PulsarParm::Ninj_fraction))
+ * int(ppc_per_dim.y*std::cbrt(PulsarParm::Ninj_fraction))
+ * int(ppc_per_dim.z*std::cbrt(PulsarParm::Ninj_fraction));
+ }
+ }
+#else
+ if (inj_pos->overlapsWith(lo, hi)) {
auto index = overlap_box.index(iv);
if (lrefine_injection) {
Box fine_overlap_box = overlap_box & amrex::shift(lfine_box, shifted);
@@ -685,13 +738,14 @@ PhysicalParticleContainer::AddPlasma (int lev, RealBox part_realbox)
}
#if (AMREX_SPACEDIM != 3)
amrex::ignore_unused(k);
-#endif
+#endif // end if amrex space dim
+#endif // End pulsar ifdef
});
// Max number of new particles. All of them are created,
// and invalid ones are then discarded
int max_new_particles = Scan::ExclusiveSum(counts.size(), counts.data(), offset.data());
-
+ Nmax_particles += max_new_particles;
// Update NextID to include particles created in this function
Long pid;
#ifdef AMREX_USE_OMP
@@ -759,31 +813,6 @@ PhysicalParticleContainer::AddPlasma (int lev, RealBox part_realbox)
bool loc_do_field_ionization = do_field_ionization;
int loc_ionization_initial_level = ionization_initial_level;
-#ifdef PULSAR
- // Fab
- const int Ex_nghost = Ex_mf.nGrow();
- const int Ey_nghost = Ey_mf.nGrow();
- const int Ez_nghost = Ez_mf.nGrow();
- const FArrayBox& Ex_fab = Ex_mf[mfi];
- const FArrayBox& Ey_fab = Ey_mf[mfi];
- const FArrayBox& Ez_fab = Ez_mf[mfi];
- const FArrayBox& rho_fab = rho_mf[mfi];
- const Dim3 Ex_lo = lbound(mfi.tilebox());
- const Dim3 Ey_lo = lbound(mfi.tilebox());
- const Dim3 Ez_lo = lbound(mfi.tilebox());
- amrex::Array4 const& ex_arr = Ex_fab.array();
- amrex::Array4 const& ey_arr = Ey_fab.array();
- amrex::Array4 const& ez_arr = Ez_fab.array();
- amrex::Array4 const& rho_arr = rho_fab.array();
- const Real q_pm = this->charge;
- //amrex::Print() << " box " << x_box << "\n";
- //FArrayBox Ey_fab = Ey_mf[mfi];
- //Box Ey_box = Ey_fab.validbox();
- //FArrayBox Ez_fab = Ez_mf[mfi];
- //Box Ez_box = Ez_fab.validbox();
- //amrex::Print() << " Ey box " << Ey_box << "\n";
- //amrex::Print() << " Ez box " << Ez_box << "\n";
-#endif
// Loop over all new particles and inject them (creates too many
// particles, in particular does not consider xmin, xmax etc.).
@@ -847,108 +876,26 @@ PhysicalParticleContainer::AddPlasma (int lev, RealBox part_realbox)
// the next generated particle.
// include ballistic correction for plasma species with bulk motion
- const Real z0 = applyBallisticCorrection(pos, inj_mom, gamma_boost,
+ const amrex::Real z0 = applyBallisticCorrection(pos, inj_mom, gamma_boost,
beta_boost, t);
if (!inj_pos->insideBounds(xb, yb, z0)) {
p.id() = -1;
continue;
}
#ifdef PULSAR
+ //amrex::Print() << " old xyz : " << xb << " " << yb << " " << z0 << "\n";
amrex::Real xc = PulsarParm::center_star[0];
amrex::Real yc = PulsarParm::center_star[1];
amrex::Real zc = PulsarParm::center_star[2];
- amrex::Real rad = std::sqrt( (xb-xc)*(xb-xc)
- + (yb-yc)*(yb-yc) + (zb-zc)*(zb-zc) );
+ amrex::Real rad = std::sqrt( (xb-xc)*(xb-xc) + (yb-yc)*(yb-yc) + (z0-zc)*(z0-zc));
if (!inj_pos->insidePulsarBounds(rad,PulsarParm::R_star,PulsarParm::dR_star)) {
- p.id() = -1;
+ p.id() = -1;
continue;
}
- // get cell center
- amrex::Real cc_x = overlap_corner[0] + iv[0]*dx[0] + 0.5*dx[0] ;
- amrex::Real cc_y = overlap_corner[1] + iv[1]*dx[1] + 0.5*dx[1] ;
- amrex::Real cc_z = overlap_corner[2] + iv[2]*dx[2] + 0.5*dx[2] ;
- // get spherical r, theta, phi
- amrex::Real cc_rad = std::sqrt( (cc_x-xc)*(cc_x-xc)
- + (cc_y-yc)*(cc_y-yc)
- + (cc_z-zc)*(cc_z-zc));
- amrex::Real cc_theta = 0;
- if (cc_rad > 0 ) {
- cc_theta = std::acos((cc_z-xc)/cc_rad);
- }
- amrex::Real cc_phi = std::atan2((cc_y-yc),(cc_x-xc));
- const amrex::Real c_theta = std::cos(cc_theta);
- const amrex::Real s_theta = std::sin(cc_theta);
- amrex::Real c_phi = 0.;
- amrex::Real s_phi = 0.;
- if (r_cl > 0) {
- c_phi = (cc_x-xc)/r_cl;
- s_phi = (cc_y-yc)/r_cl;
- }
- amrex::Real omega = PulsarParm::Omega(t);
- amrex::Real ratio = PulsarParm::R_star/cc_rad;
- amrex::Real r3 = ratio*ratio*ratio;
- amrex::Real Er_cor = PulsarParm::B_star
- *omega
- *cc_rad*s_theta*s_theta;
- //// Er_external is known
- //Real Er_ext = omega*PulsarParm::B_star*cc_rad*(1.0-3.0*c_theta*c_theta);
- //Er_ext += (2.0/3.0)*omega*PulsarParm::B_star*cc_rad;
- //// rho_GJ is known
- amrex::Real rho_GJ = 2*PhysConst::ep0*PulsarParm::B_star*omega*
- (1.0-3.0*c_theta*c_theta)*PulsarParm::rhoGJ_scale;
- int ii = Ex_lo.x + iv[0];
- int jj = Ex_lo.y + iv[1];
- int kk = Ex_lo.z + iv[2];
- Real ex_avg = 0.25*(ex_arr(ii,jj,kk) + ex_arr(ii,jj+1,kk)+ex_arr(ii,jj,kk+1) + ex_arr(ii,jj+1,kk+1));
- Real ey_avg = 0.25*(ey_arr(ii,jj,kk) + ey_arr(ii+1,jj,kk)+ey_arr(ii,jj,kk+1) + ey_arr(ii+1,jj,kk+1));
- Real ez_avg = 0.25*(ez_arr(ii,jj,kk) + ez_arr(ii,jj+1,kk)+ez_arr(ii+1,jj,kk) + ez_arr(ii+1,jj+1,kk));
- Real Er_cell = ex_avg*s_theta*c_phi + ey_avg*s_theta*s_phi + ez_avg*c_theta;
- // analytical surface charge density
- //Real sigma_inj = (( Er_ext - Er_cor));
- Real sigma_inj = (( Er_cell - Er_cor));
- Real max_dens = PulsarParm::max_ndens;
- amrex::Real fraction = PulsarParm::Ninj_fraction;
- // number of particle pairs injected
- Real N_inj = fraction*amrex::Math::abs(sigma_inj) *PhysConst::ep0* dx[0]*dx[0]/(PhysConst::q_e*max_dens*scale_fac);
- if (t > 0) {
- if (N_inj >= 1) {
- if (N_inj < num_ppc) {
- int part_freq = floor(num_ppc / N_inj);
- if (i_part%part_freq!=0) {
- p.id() = -1;
- continue;
- }
- }
- }
- else
- {
- p.id() = -1;
- continue;
- }
- //if (sigma_inj < 0 and q_pm >0) {p.id()=-1; continue;}
- //if (sigma_inj > 0 and q_pm <0) {p.id()=-1; continue;}
- if (sigma_inj < 0 and q_pm >0) {p.id()=-1; continue;}
- if (sigma_inj > 0 and q_pm <0) {p.id()=-1; continue;}
- // if rho is too smal -- we dont inject particles
- if (std::abs(rho_GJ) < 1.0E-20) {
- p.id() = -1;
- continue;
- }
- else {
- Real rel_rho_err = ((rho_arr(ii,jj,kk) - rho_GJ)/rho_GJ);
- // If current rho is much higher than rho_GJ, particles are not introduced.
- if ( amrex::Math::abs(rel_rho_err) > 0.05) {
- p.id() = -1;
- continue;
- }
- }
- }
- }
#endif
u = inj_mom->getMomentum(pos.x, pos.y, z0, engine);
dens = inj_rho->getDensity(pos.x, pos.y, z0);
-
// Remove particle if density below threshold
if ( dens < density_min ){
p.id() = -1;
@@ -1037,26 +984,6 @@ PhysicalParticleContainer::AddPlasma (int lev, RealBox part_realbox)
}
});
-#ifdef PULSAR
- if (PulsarParm::EB_external == 1) {
- const auto GetPosition = GetParticlePosition(pti);
- Real* const AMREX_RESTRICT Exp_data = Exp.dataPtr();
- Real* const AMREX_RESTRICT Eyp_data = Eyp.dataPtr();
- Real* const AMREX_RESTRICT Ezp_data = Ezp.dataPtr();
- Real* const AMREX_RESTRICT Bxp_data = Bxp.dataPtr();
- Real* const AMREX_RESTRICT Byp_data = Byp.dataPtr();
- Real* const AMREX_RESTRICT Bzp_data = Bzp.dataPtr();
- Real time = warpx.gett_new(lev);
- amrex::ParallelFor(pti.numParticles(),
- [=] AMREX_GPU_DEVICE (long i) {
- ParticleReal x, y, z;
- GetPosition(i, x, y, z);
- PulsarParm::PulsarEBField(x, y, z,
- Exp_data[i],Eyp_data[i],Ezp_data[i],
- Bxp_data[i],Byp_data[i],Bzp_data[i],time);
- });
- }
-#endif
amrex::Gpu::synchronize();
if (cost && WarpX::load_balance_costs_update_algo == LoadBalanceCostsUpdateAlgo::Timers)
@@ -1065,7 +992,7 @@ PhysicalParticleContainer::AddPlasma (int lev, RealBox part_realbox)
amrex::HostDevice::Atomic::Add( &(*cost)[mfi.index()], wt);
}
}
-
+ amrex::Print() << " newly added particles : " << TotalNumberOfParticles()-valid_particles_beforeAdd << " total max particles " << Nmax_particles<< "\n";
// The function that calls this is responsible for redistributing particles.
}
@@ -1562,7 +1489,13 @@ PhysicalParticleContainer::PushP (int lev, Real dt,
const std::array& dx = WarpX::CellSize(std::max(lev,0));
-#ifdef AMREX_USE_OMP
+#ifdef PULSAR
+ const auto problo = WarpX::GetInstance().Geom(lev).ProbLoArray();
+ const auto probhi = WarpX::GetInstance().Geom(lev).ProbHiArray();
+ amrex::Real cur_time = WarpX::GetInstance().gett_new(lev);
+#endif
+
+#ifdef _OPENMP
#pragma omp parallel
#endif
{
@@ -1644,6 +1577,13 @@ PhysicalParticleContainer::PushP (int lev, Real dt,
ex_type, ey_type, ez_type, bx_type, by_type, bz_type,
dx_arr, xyzmin_arr, lo, n_rz_azimuthal_modes,
nox, galerkin_interpolation);
+#ifdef PULSAR
+ doPulsarFieldGatherShapeN(xp, yp, zp, Exp, Eyp, Ezp, Bxp, Byp, Bzp,
+ ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr,
+ ex_type, ey_type, ez_type, bx_type, by_type, bz_type,
+ dx_arr, xyzmin_arr, lo, n_rz_azimuthal_modes,
+ nox, galerkin_interpolation, problo, probhi, cur_time);
+#endif
}
// Externally applied E-field in Cartesian co-ordinates
getExternalE(ip, Exp, Eyp, Ezp);
@@ -1951,6 +1891,10 @@ PhysicalParticleContainer::PushPX (WarpXParIter& pti,
const std::array& xyzmin = WarpX::LowerCorner(box, galilean_shift, gather_lev);
const Dim3 lo = lbound(box);
+#ifdef PULSAR
+ const auto problo = WarpX::GetInstance().Geom(lev).ProbLoArray();
+ const auto probhi = WarpX::GetInstance().Geom(lev).ProbHiArray();
+#endif
bool galerkin_interpolation = WarpX::galerkin_interpolation;
int nox = WarpX::nox;
@@ -2025,6 +1969,13 @@ PhysicalParticleContainer::PushPX (WarpXParIter& pti,
ex_type, ey_type, ez_type, bx_type, by_type, bz_type,
dx_arr, xyzmin_arr, lo, n_rz_azimuthal_modes,
nox, galerkin_interpolation);
+#ifdef PULSAR
+ doPulsarFieldGatherShapeN(xp, yp, zp, Exp, Eyp, Ezp, Bxp, Byp, Bzp,
+ ex_arr, ey_arr, ez_arr, bx_arr, by_arr, bz_arr,
+ ex_type, ey_type, ez_type, bx_type, by_type, bz_type,
+ dx_arr, xyzmin_arr, lo, n_rz_azimuthal_modes,
+ nox, galerkin_interpolation, problo, probhi, cur_time);
+#endif
}
// Externally applied E-field in Cartesian co-ordinates
getExternalE(ip, Exp, Eyp, Ezp);
@@ -2249,8 +2200,7 @@ void PhysicalParticleContainer::PulsarParticleRemoval() {
Real r = std::sqrt((x-xc)*(x-xc)
+ (y-yc)*(y-yc)
+ (z-zc)*(z-zc));
- //if (r<=(PulsarParm::R_star-PulsarParm::dR_star)) {
- if (r<=(PulsarParm::R_star)) {
+ if (r <= (PulsarParm::max_particle_absorption_radius)) {
pp[i].id() = -1;
}
});
diff --git a/Source/Particles/PulsarParameters.H b/Source/Particles/PulsarParameters.H
index 185411e41e6..fc7999308be 100644
--- a/Source/Particles/PulsarParameters.H
+++ b/Source/Particles/PulsarParameters.H
@@ -6,6 +6,9 @@
#include
#include
#include
+#include
+
+using namespace amrex;
namespace PulsarParm
{
@@ -23,10 +26,19 @@ namespace PulsarParm
amrex::GpuArray center_star;
extern AMREX_GPU_DEVICE_MANAGED amrex::Real max_ndens;
extern AMREX_GPU_DEVICE_MANAGED amrex::Real Ninj_fraction;
+ extern AMREX_GPU_DEVICE_MANAGED int ModifyParticleWtAtInjection;
extern AMREX_GPU_DEVICE_MANAGED amrex::Real rhoGJ_scale;
extern AMREX_GPU_DEVICE_MANAGED int damp_EB_internal;
-
+ extern AMREX_GPU_DEVICE_MANAGED amrex::Real max_EBcorotating_radius;
+ extern AMREX_GPU_DEVICE_MANAGED amrex::Real max_EBdamping_radius;
+ extern AMREX_GPU_DEVICE_MANAGED int turnoffdeposition;
+ extern AMREX_GPU_DEVICE_MANAGED amrex::Real max_nodepos_radius;
+ extern AMREX_GPU_DEVICE_MANAGED int turnoff_plasmaEB_gather;
+ extern AMREX_GPU_DEVICE_MANAGED amrex::Real max_nogather_radius;
extern AMREX_GPU_DEVICE_MANAGED int verbose;
+ extern AMREX_GPU_DEVICE_MANAGED amrex::Real max_particle_absorption_radius;
+ extern AMREX_GPU_DEVICE_MANAGED amrex::Real particle_inject_rmin;
+ extern AMREX_GPU_DEVICE_MANAGED amrex::Real particle_inject_rmax;
void ReadParameters();
@@ -42,184 +54,61 @@ namespace PulsarParm
return omega;
}
+
AMREX_GPU_HOST_DEVICE AMREX_INLINE
- void PulsarEField(const amrex::ParticleReal xp, const amrex::ParticleReal yp,
- const amrex::ParticleReal zp,
- amrex::ParticleReal &Exp, amrex::ParticleReal &Eyp,
- amrex::ParticleReal &Ezp,
- amrex::Real time)
+ void ExternalEFieldSpherical (amrex::Real const r, amrex::Real const theta,
+ amrex::Real const phi, amrex::Real const time,
+ amrex::Real &Er, amrex::Real &Etheta, amrex::Real &Ephi)
{
- // spherical r, theta, phi
- const amrex::Real xc = center_star[0];
- const amrex::Real yc = center_star[1];
- const amrex::Real zc = center_star[2];
- const amrex::Real r = std::sqrt( (xp-xc)*(xp-xc) + (yp-yc)*(yp-yc) + (zp-zc)*(zp-zc) );
- const amrex::Real phi = std::atan2((yp-yc),(xp-xc));
- amrex::Real theta = 0.0;
- if (r > 0) {
- theta = std::acos((zp-zc)/r);
- }
- const amrex::Real c_theta = std::cos(theta);
- const amrex::Real s_theta = std::sin(theta);
- const amrex::Real c_phi = std::cos(phi);
- const amrex::Real s_phi = std::sin(phi);
- amrex::Real omega = omega_star;
- // ramping up omega
- if (time < ramp_omega_time) {
- omega = omega_star*time/ramp_omega_time;
- }
-
- if (r= R_star ) {
- amrex::Real r_ratio = R_star/r;
- amrex::Real r3 = r_ratio*r_ratio*r_ratio;
+ // outside pulsar
+ if ( r > max_EBcorotating_radius ) {
+ amrex::Real r4 = r_ratio*r_ratio*r_ratio*r_ratio;
// Taking derivative of phi given in eq 30 of Michel and Li
- amrex::Real Er = B_star*omega*R_star*r_ratio*r3*(1.0-3.0*c_theta*c_theta);
+ Er = B_star * omega * R_star * r4 * (1.0-3.0*c_theta*c_theta);
if (E_external_monopole == 1) {
- Er += (2.0/3.0)*omega*B_star*R_star*r_ratio*r_ratio;
+ Er += (2.0/3.0) * omega * B_star * R_star * r_ratio * r_ratio;
}
- amrex::Real Etheta = (-1.0)*B_star*omega*R_star*r_ratio*r3*(2.0*s_theta*c_theta);
-
- Exp = Er*s_theta*c_phi + Etheta*c_theta*c_phi;
- Eyp = Er*s_theta*s_phi + Etheta*c_theta*s_phi;
- Ezp = Er*c_theta - Etheta*s_theta;
- }
+ Etheta = (-1.0) * B_star * omega * R_star * r4 * (2.0*s_theta*c_theta);
+ Ephi = 0.0;
+ }
}
AMREX_GPU_HOST_DEVICE AMREX_INLINE
- void PulsarBField(const amrex::ParticleReal xp, const amrex::ParticleReal yp,
- const amrex::ParticleReal zp,
- amrex::ParticleReal &Bxp, amrex::ParticleReal &Byp,
- amrex::ParticleReal &Bzp,
- amrex::Real time)
+ void ExternalBFieldSpherical (amrex::Real const r, amrex::Real const theta,
+ amrex::Real const phi, amrex::Real const time,
+ amrex::Real &Br, amrex::Real &Btheta, amrex::Real &Bphi)
{
- // spherical r, theta, phi
- const amrex::Real xc = center_star[0];
- const amrex::Real yc = center_star[1];
- const amrex::Real zc = center_star[2];
- const amrex::Real r = std::sqrt( (xp-xc)*(xp-xc) + (yp-yc)*(yp-yc) + (zp-zc)*(zp-zc) );
- const amrex::Real phi = std::atan2((yp-yc),(xp-xc));
- amrex::Real theta = 0.0;
- if (r > 0) {
- theta = std::acos((zp-zc)/r);
- }
- const amrex::Real c_theta = std::cos(theta);
- const amrex::Real s_theta = std::sin(theta);
- const amrex::Real c_phi = std::cos(phi);
- const amrex::Real s_phi = std::sin(phi);
amrex::Real omega = Omega(time);
-
- if (r= R_star ) {
- amrex::Real r_ratio = R_star/r;
- amrex::Real r3 = r_ratio*r_ratio*r_ratio;
- // Taking derivative of phi given in eq 30 of Michel and Li
- amrex::Real Br = 2.0*B_star*r3*c_theta;
- amrex::Real Btheta = B_star*r3*s_theta;
-
- Bxp = Br*s_theta*c_phi + Btheta*c_theta*c_phi;
- Byp = Br*s_theta*s_phi + Btheta*c_theta*s_phi;
- Bzp = Br*c_theta - Btheta*s_theta;
- }
+ amrex::Real c_theta = std::cos(theta);
+ amrex::Real s_theta = std::sin(theta);
+ amrex::Real r_ratio = R_star/r;
+ amrex::Real r3 = r_ratio*r_ratio*r_ratio;
+ // Michel and Li -- eq 14 and 15 from michel and li
+ // dipole B field inside and outside the pulsar
+ Br = 2.0*B_star*r3*c_theta;
+ Btheta = B_star*r3*s_theta;
+ Bphi = 0.0;
}
-// AMREX_GPU_HOST_DEVICE AMREX_INLINE
-// void PulsarEBField(amrex::Real xp, amrex::Real yp, amrex::Real zp,
-// amrex::Real &Exp, amrex::Real &Eyp, amrex::Real &Ezp,
-// amrex::Real &Bxp, amrex::Real &Byp, amrex::Real &Bzp,
-// amrex::Real time)
-// {
-// // spherical r, theta, phi
-// const amrex::Real xc = center_star[0];
-// const amrex::Real yc = center_star[1];
-// const amrex::Real zc = center_star[2];
-// const amrex::Real r = std::sqrt( (xp-xc)*(xp-xc) + (yp-yc)*(yp-yc) + (zp-zc)*(zp-zc) );
-// const amrex::Real phi = std::atan2((yp-yc),(xp-xc));
-// amrex::Real theta = 0.0;
-// if (r > 0) {
-// theta = std::acos((zp-zc)/r);
-// }
-// const amrex::Real c_theta = std::cos(theta);
-// const amrex::Real s_theta = std::sin(theta);
-// const amrex::Real c_phi = std::cos(phi);
-// const amrex::Real s_phi = std::sin(phi);
-// amrex::Real omega = omega_star;
-// // ramping up omega
-// if (time < 2.0e-4) {
-// omega = omega_star*time/2.0e-4;
-// }
-//
-// if (r= R_star ) {
-// amrex::Real r_ratio = R_star/r;
-// amrex::Real r3 = r_ratio*r_ratio*r_ratio;
-// // Taking derivative of phi given in eq 30 of Michel and Li
-// amrex::Real Er = B_star*omega*R_star*r_ratio*r3*(1.0-3.0*c_theta*c_theta);
-// if (E_external_monopole == 1) {
-// Er += (2.0/3.0)*omega*B_star*R_star*r_ratio*r_ratio;
-// }
-// amrex::Real Etheta = (-1.0)*B_star*omega*R_star*r_ratio*r3*(2.0*s_theta*c_theta);
-//
-// Exp = Er*s_theta*c_phi + Etheta*c_theta*c_phi;
-// Eyp = Er*s_theta*s_phi + Etheta*c_theta*s_phi;
-// Ezp = Er*c_theta - Etheta*s_theta;
-//
-// amrex::Real Br = 2.0*B_star*r3*c_theta;
-// amrex::Real Btheta = B_star*r3*s_theta;
-//
-// Bxp = Br*s_theta*c_phi + Btheta*c_theta*c_phi;
-// Byp = Br*s_theta*s_phi + Btheta*c_theta*s_phi;
-// Bzp = Br*c_theta - Btheta*s_theta;
-// }
-// }
-
namespace Spherical
{
AMREX_GPU_HOST_DEVICE AMREX_INLINE
- amrex::Real r(int i, int j, int k, amrex::GeometryData const& geom, int const* const AMREX_RESTRICT mf_ixType)
+ amrex::Real r(int i, int j, int k, amrex::GeometryData const& geom, amrex::GpuArray const mf_ixType)
{
const auto domain_box = geom.Domain();
const auto domain_ilo = amrex::lbound(domain_box);
@@ -227,16 +116,13 @@ namespace PulsarParm
const auto domain_xhi = geom.ProbHi();
const auto domain_dx = geom.CellSize();
- //const amrex::Real x = domain_xlo[0] + (i - domain_ilo.x + 0.5) * domain_dx[0] + (1.0 - mf_ixType[0])*domain_dx[0]*0.5;
- //const amrex::Real y = domain_xlo[1] + (j - domain_ilo.y + 0.5) * domain_dx[1] + (1.0 - mf_ixType[1])*domain_dx[1]*0.5;
- //const amrex::Real z = domain_xlo[2] + (k - domain_ilo.z + 0.5) * domain_dx[2] + (1.0 - mf_ixType[2])*domain_dx[2]*0.5;
const amrex::Real x = domain_xlo[0] + (i ) * domain_dx[0] + (1.0 - mf_ixType[0])*domain_dx[0]*0.5;
const amrex::Real y = domain_xlo[1] + (j ) * domain_dx[1] + (1.0 - mf_ixType[1])*domain_dx[1]*0.5;
const amrex::Real z = domain_xlo[2] + (k ) * domain_dx[2] + (1.0 - mf_ixType[2])*domain_dx[2]*0.5;
- const amrex::Real xc = 0.5 * (domain_xlo[0] + domain_xhi[0]);
- const amrex::Real yc = 0.5 * (domain_xlo[1] + domain_xhi[1]);
- const amrex::Real zc = 0.5 * (domain_xlo[2] + domain_xhi[2]);
+ const amrex::Real xc = PulsarParm::center_star[0];
+ const amrex::Real yc = PulsarParm::center_star[1];
+ const amrex::Real zc = PulsarParm::center_star[2];
const amrex::Real r = std::sqrt((x-xc)*(x-xc) + (y-yc)*(y-yc) + (z-zc)*(z-zc));
@@ -244,18 +130,77 @@ namespace PulsarParm
}
}
+ /** Compute Cartesian components corresponding to i, j, k based on the staggering,
+ ixType, and the domain_lo and cell size, dx.
+ */
+ AMREX_GPU_HOST_DEVICE AMREX_INLINE
+ void ComputeCellCoordinates ( int i, int j, int k,
+ amrex::GpuArray const mf_type,
+ amrex::GpuArray const domain_lo,
+ amrex::GpuArray const dx,
+ amrex::Real &x, amrex::Real &y, amrex::Real &z)
+ {
+ x = domain_lo[0] + i*dx[0] + (1.0_rt - mf_type[0]) * dx[0]*0.5;
+ y = domain_lo[1] + j*dx[1] + (1.0_rt - mf_type[1]) * dx[1]*0.5;
+ z = domain_lo[2] + k*dx[2] + (1.0_rt - mf_type[2]) * dx[2]*0.5;
+ }
AMREX_GPU_HOST_DEVICE AMREX_INLINE
- void DampEField(int i, int j, int k, amrex::GeometryData const& geom, amrex::Array4 const& Efield, int const* const AMREX_RESTRICT mf_ixtype)
+ void ConvertCartesianToSphericalCoord ( amrex::Real const x, amrex::Real const y,
+ amrex::Real const z,
+ amrex::GpuArray const domain_lo,
+ amrex::GpuArray const domain_hi,
+ amrex::Real &r, amrex::Real &theta, amrex::Real &phi)
{
- const amrex::Real r = Spherical::r(i, j, k, geom, mf_ixtype);
+ amrex::Real xc = PulsarParm::center_star[0];
+ amrex::Real yc = PulsarParm::center_star[1];
+ amrex::Real zc = PulsarParm::center_star[2];
+
+ r = std::sqrt( (x-xc)*(x-xc) + (y-yc)*(y-yc) + (z-zc)*(z-zc) );
+ theta = 0.0;
+ if (r > 0) theta = std::acos( (z-zc) / r );
+ phi = std::atan2( (y-yc), (x-xc) );
+ }
- if (r < R_star) {
+ AMREX_GPU_HOST_DEVICE AMREX_INLINE
+ void ConvertSphericalToCartesianXComponent (amrex::Real const F_r,
+ amrex::Real const F_theta, amrex::Real const F_phi,
+ amrex::Real const r, amrex::Real const theta,
+ amrex::Real const phi, amrex::Real & F_x)
+ {
+ F_x = F_r * std::sin(theta) * std::cos(phi)
+ + F_theta * std::cos(theta) * std::cos(phi);
+ }
+
+ AMREX_GPU_HOST_DEVICE AMREX_INLINE
+ void ConvertSphericalToCartesianYComponent (amrex::Real const F_r,
+ amrex::Real const F_theta, amrex::Real const F_phi,
+ amrex::Real const r, amrex::Real const theta,
+ amrex::Real const phi, amrex::Real & F_y)
+ {
+ F_y = F_r * std::sin(theta) * std::sin(phi)
+ + F_theta * std::cos(theta) * std::sin(phi);
+ }
+
+ AMREX_GPU_HOST_DEVICE AMREX_INLINE
+ void ConvertSphericalToCartesianZComponent (amrex::Real const F_r,
+ amrex::Real const F_theta, amrex::Real const F_phi,
+ amrex::Real const r, amrex::Real const theta,
+ amrex::Real const phi, amrex::Real & F_z)
+ {
+ F_z = F_r * std::cos(theta) - F_theta * std::sin(theta);
+ }
+
+
+ AMREX_GPU_HOST_DEVICE AMREX_INLINE
+ void DampField(int i, int j, int k, amrex::GeometryData const& geom, amrex::Array4 const& Efield, amrex::GpuArray const mf_ixtype)
+ {
+ amrex::Real r = Spherical::r(i, j, k, geom, mf_ixtype);
+ if (r <= max_EBdamping_radius) {
// Damping function: Fd = tanh(damping_scale * (r / R_star - 1)) + 1
// for damping_scale >= 10 or so:
// Fd(0) ~ 0
// Fd(R_star) ~ 1
-
const amrex::Real Fd = std::tanh(damping_scale * (r / R_star - 1.0)) + 1.0;
Efield(i, j, k) = Efield(i, j, k) * Fd;
}
diff --git a/Source/Particles/PulsarParameters.cpp b/Source/Particles/PulsarParameters.cpp
index 85d08be6662..06f2abd9ec0 100644
--- a/Source/Particles/PulsarParameters.cpp
+++ b/Source/Particles/PulsarParameters.cpp
@@ -23,7 +23,17 @@ namespace PulsarParm
AMREX_GPU_DEVICE_MANAGED int verbose = 0;
AMREX_GPU_DEVICE_MANAGED amrex::Real max_ndens;
AMREX_GPU_DEVICE_MANAGED amrex::Real Ninj_fraction;
+ AMREX_GPU_DEVICE_MANAGED int ModifyParticleWtAtInjection = 1;
AMREX_GPU_DEVICE_MANAGED amrex::Real rhoGJ_scale;
+ AMREX_GPU_DEVICE_MANAGED amrex::Real max_EBcorotating_radius;
+ AMREX_GPU_DEVICE_MANAGED amrex::Real max_EBdamping_radius;
+ AMREX_GPU_DEVICE_MANAGED int turnoffdeposition = 0;
+ AMREX_GPU_DEVICE_MANAGED amrex::Real max_nodepos_radius;
+ AMREX_GPU_DEVICE_MANAGED int turnoff_plasmaEB_gather = 0;
+ AMREX_GPU_DEVICE_MANAGED amrex::Real max_nogather_radius;
+ AMREX_GPU_DEVICE_MANAGED amrex::Real max_particle_absorption_radius;
+ AMREX_GPU_DEVICE_MANAGED amrex::Real particle_inject_rmin;
+ AMREX_GPU_DEVICE_MANAGED amrex::Real particle_inject_rmax;
void ReadParameters() {
amrex::ParmParse pp("pulsar");
@@ -46,11 +56,53 @@ namespace PulsarParm
amrex::Print() << " Pulsar B_star : " << B_star << "\n";
pp.get("max_ndens", max_ndens);
pp.get("Ninj_fraction",Ninj_fraction);
+
+ particle_inject_rmin = R_star - dR_star;
+ particle_inject_rmax = R_star;
+ pp.query("particle_inj_rmin", particle_inject_rmin);
+ pp.query("particle_inj_rmax", particle_inject_rmax);
+ amrex::Print() << " min radius of particle injection : " << particle_inject_rmin << "\n";
+ amrex::Print() << " max radius of particle injection : " << particle_inject_rmax << "\n";
+
+ pp.query("ModifyParticleWeight", ModifyParticleWtAtInjection);
+ // The maximum radius within which particles are absorbed/deleted every timestep.
+ max_particle_absorption_radius = R_star;
+ pp.query("max_particle_absorption_radius", max_particle_absorption_radius);
pp.get("rhoGJ_scale",rhoGJ_scale);
amrex::Print() << " pulsar max ndens " << max_ndens << "\n";
amrex::Print() << " pulsar ninj fraction " << Ninj_fraction << "\n";
+ amrex::Print() << " pulsar modify particle wt " << ModifyParticleWtAtInjection << "\n";
amrex::Print() << " pulsar rhoGJ scaling " << rhoGJ_scale << "\n";
amrex::Print() << " EB_external : " << EB_external << "\n";
+ if (EB_external == 1) {
+ // Max corotating radius defines the region where the EB field shifts from
+ // corotating (v X B) to quadrapole. default is R_star.
+ max_EBcorotating_radius = R_star;
+ pp.query("EB_corotating_maxradius", max_EBcorotating_radius);
+ amrex::Print() << " EB coratating maxradius : " << max_EBcorotating_radius << "\n";
+ }
+ if (damp_EB_internal == 1) {
+ // Radius of the region within which the EB fields are damped
+ max_EBdamping_radius = R_star;
+ pp.query("damp_EB_radius", max_EBdamping_radius);
+ amrex::Print() << " max EB damping radius : " << max_EBdamping_radius << "\n";
+ }
+ // query to see if particle j,rho deposition should be turned off
+ // within some region interior to the star
+ // default is 0
+ pp.query("turnoffdeposition", turnoffdeposition);
+ amrex::Print() << " is deposition off ? " << turnoffdeposition << "\n";
+ if (turnoffdeposition == 1) {
+ max_nodepos_radius = R_star;
+ pp.query("max_nodepos_radius", max_nodepos_radius);
+ amrex::Print() << " deposition turned off within radius : " << max_nodepos_radius << "\n";
+ }
+ pp.query("turnoff_plamsaEB_gather", turnoff_plasmaEB_gather);
+ amrex::Print() << " is plasma EB gather off ? " << turnoff_plasmaEB_gather << "\n";
+ if (turnoff_plasmaEB_gather == 1) {
+ max_nogather_radius = R_star;
+ pp.query("max_nogather_radius", max_nogather_radius);
+ amrex::Print() << " gather off within radius : " << max_nogather_radius << "\n";
+ }
}
-
}
diff --git a/Source/Particles/RigidInjectedParticleContainer.cpp b/Source/Particles/RigidInjectedParticleContainer.cpp
index d18631ff153..db15b9e7de0 100644
--- a/Source/Particles/RigidInjectedParticleContainer.cpp
+++ b/Source/Particles/RigidInjectedParticleContainer.cpp
@@ -482,6 +482,7 @@ RigidInjectedParticleContainer::PushP (int lev, Real dt,
ex_type, ey_type, ez_type, bx_type, by_type, bz_type,
dx_arr, xyzmin_arr, lo, n_rz_azimuthal_modes,
nox, galerkin_interpolation);
+
getExternalE(ip, Exp, Eyp, Ezp);
getExternalB(ip, Bxp, Byp, Bzp);
diff --git a/Source/Particles/WarpXParticleContainer.H b/Source/Particles/WarpXParticleContainer.H
index c0e76044257..4e77ece573d 100644
--- a/Source/Particles/WarpXParticleContainer.H
+++ b/Source/Particles/WarpXParticleContainer.H
@@ -330,6 +330,7 @@ public:
bool AmIA () const noexcept {return (physical_species == PhysSpec);}
amrex::Array get_v_galilean () {return m_v_galilean;}
+
#ifdef PULSAR
virtual void PulsarParticleInjection () {};
virtual void PulsarParticleRemoval () {};
diff --git a/Source/WarpX.cpp b/Source/WarpX.cpp
index 57bfd4423cd..632b5891794 100644
--- a/Source/WarpX.cpp
+++ b/Source/WarpX.cpp
@@ -1115,7 +1115,11 @@ WarpX::AllocLevelMFs (int lev, const BoxArray& ba, const DistributionMapping& dm
Efield_avg_fp[lev][1] = std::make_unique(amrex::convert(ba,Ey_nodal_flag),dm,ncomps,ngE);
Efield_avg_fp[lev][2] = std::make_unique(amrex::convert(ba,Ez_nodal_flag),dm,ncomps,ngE);
+#ifdef PULSAR
+ bool deposit_charge = do_dive_cleaning || plot_rho;
+#else
bool deposit_charge = do_dive_cleaning || (plot_rho && do_back_transformed_diagnostics);
+#endif // pulsar endif
if (WarpX::maxwell_solver_id == MaxwellSolverAlgo::PSATD) {
deposit_charge = do_dive_cleaning || (plot_rho && do_back_transformed_diagnostics)
|| update_with_rho || current_correction;