Potential sampling using Galpy - python

I have builded a code that solves gravity for a N-Body system. I'm currently testing this code using potential generated by Galpy. I've been trying to generate a Plummer distribution and use it as an initial condition for my simulation. However, the distribution always end up collapsing for some reason.
I'm trying to see if this could be due to some unit conversion problem when generating the potential. Here is my code:
N_part = 50000
mp = 1e7*units.Msun
Mtot = N_part*mp
b = 8*units.kpc
G = 4.3*1e-6*units.kpc*(1/units.Msun)*(units.km/units.s)**2
amp = G*Mtot
# Profile et sampling
plummer = pp(amp=amp,b=b)
df_plummer = isotropicPlummerdf(pot=plummer)
sam = df_plummer.sample(n=N_part)
vx,vy,vz = sam.vx(),sam.vy(),sam.vz()
x,y,z = sam.x(),sam.y(),sam.z()
Normally, velocities (vx,vy,vz) and positions (x,y,z) are suppose to be in km/s and kpc. Am I doing this right ?
Thanks by advance!

Related

Low brightness in beam visualization

prism with low brightness beam
Never posted a question on stack before, please forgive any question upload mistakes.
As seen in the image above, I'm having trouble visualizing beam propagation in a prism. The source is a GaussianBeamSource. The beam is not bright enough to see. I assume the issue is that normalization and spread of the beam, but I need to see how this beam propagates to create structures in its path. I thought about manipulating the amplitude but don't know how to modify that in this specific source type, or if it would be normalized back to the same state of brightness/visibility. Another guess is that the short wavelength (473nm) combined with the large sim size (50x50um) is leading to low visibility.
Thanks in advance if anyone can offer help or advice. Hope this group is still active.
The code below is just snippets for the simulation parameters. If more is needed I can add later.
# basic simulation parameters
resolution = 50 # pixels/um
cell = mp.Vector3(100, 100, 0)
pml_layers = [mp.PML(1.0)]
fcen = 1/0.473 # pulse center frequency
df = 0.1 # pulse width (in frequency)
sources = [mp.GaussianBeamSource(
src = mp.ContinuousSource(wavelength = 0.473),
center = mp.Vector3(-40,22.5,0),
size = mp.Vector3(0,4.1,0),
component = mp.Hz,
beam_x0 = mp.Vector3(0,0,0),
beam_kdir = mp.Vector3(1,0,0),
beam_w0 = 2.05,
beam_E0 = mp.Vector3(0,0,1)
)]
plt.figure()
sim.plot2D(fields=mp.Ez, eps_parameters={'contour':True})
plt.axis('on')
plt.show()

Python 3d analysis (vedo): find largest spheres that can fit inside of a mesh?

I am using vedo to visualize and work with 3D models taken from a Lidar scan; they are .obj files that I open up.
In my application, I want to find the largest spheres the can 'fit inside' of my scanned object, if that makes sense. Imagine I have a room or hallway - basically I am trying to measure the amount of free space available.
So I want to fit in a bunch of spheres, and then see how big those spheres are. It's important that I can automate this process for whatever .obj file I load in, otherwise I would manually measure things...
Here is an example .obj file I open up, a crudely scanned hallway:
I'm not sure how to go about this with vedo, the closest example I found was 'Fit a Sphere' from the example website, which inspired my solution idea:
https://vedo.embl.es/#quick_start
https://github.com/marcomusy/vedo/blob/master/examples/advanced/fitspheres1.py
But then how would I define constraints on the spheres that they "fit inside" the mesh (hallway / room)?
For reference, here is my starter code, all it really does is read and display the mesh:
import vedo
import numpy as np
# https://vedo.embl.es/#quick_start
mesh_str = 'meshes/mesh1_indoor_scene_1.obj'
# Load a polygonal mesh, make it white and glossy:
scene = vedo.Mesh(mesh_str)
scene.c('white').lighting('glossy')
# Create two points:
p1 = vedo.Point([ 1,0,1], c='yellow')
p2 = vedo.Point([-1,0,2], c='red')
# Add colored light sources at the point positions:
l1 = vedo.Light(p1, c='yellow')
l2 = vedo.Light(p2, c='red')
# Show everything in one go:
vedo.show(scene, l1, l2, p1, p2, mesh_str, axes=True)
Appreciate any help, and open to thinking about other feasible solutions that can be implemented in python code.
If you can reconstruct a surface from the point cloud you can directly use surf.volume() or maybe generate a grid of points and use insidePoints() (instead of fitting spheres), e.g.:
from vedo import *
import numpy as np
surf = Mesh(dataurl+'cow.vtk').wireframe()
printc("true volume: ", surf.volume())
pts = []
step = 0.05
b = surf.bounds()
for x in np.arange(b[0], b[1], step):
for y in np.arange(b[2], b[3], step):
for z in np.arange(b[4], b[5], step):
pts.append([x,y,z])
pts = np.array(pts)
ipts = surf.inside_points(pts)
printc("approx volume:", ipts.npoints*step**3)
show(surf, ipts, N=2, axes=1)
true volume: 0.8346111674784022
approx volume: 0.8287500000000002
You can also post an issue here.

Is there a way to change my ODE inside ODEINT in Python?

I'm trying to simulate an oscillatory system with a little difference: I want it to use a specific equation of motion (an O.D.E.) when the body is moving up, and another equation of motion when the body is moving down. To solve these equations, I'm using the ODEINT from Scypi.
For example, let's consider the classic mass-spring system. I've tried to induce the system to work with the equation of motion for external excitations on the body when it's moving up, and with the simple equation when it's moving down.
def function (x,t):
F0 = 10.00
w = 1.00
m = 2.00
c = 1.00
k = 20.00
s = x[0]
dsdt = x[1]
if x[1] >= 0:
d2sdt2 = (F0*np.sin(w*t)-c*dsdt-k*s)/m
else:
d2sdt2 = (-c*dsdt-k*s)/m
result = [dsdt,d2sdt2]
return result
initial = [3.00,0.00]
t = np.linspace(0.00,10.00,101)
y = odeint(function, initial, t)
The results obtained show that only the second equation of motion is working on the body (Results Obtained). I was expecting a more chaotic pattern of movement when the body is moving up, due the external force.
Is there a better way to implement this?
Just adding some parameters to increase the density of internal steps and the density of the output
t = np.linspace(0.00,10.00,301)
y = odeint(function, initial, t, hmax=0.1, atol = 1e-8, rtol=1e-10)
and not using dashed lines gives the plot
where the kinks in the second half are clearly visible.
So your code is correct, but you need to take into account that the ODE solvers are constructed for smooth right sides, starting with the mathematical methods and up to and especially for the predictors for the optimal step size. As here there are locally unpredictable non-smooth changes in the right side, one has to tell the solver not to use very large step sizes as that may jump over a change of the model phase and back.
As an aside, for smooth plots an output density of 100 points on the whole horizontal axis is usually too small. Use 200 to 600 points depending on the final "in-print" size of the plot.

pymc3 likelihood math with non-theano function

I'm new to doing Bayesian inference. I'm trying to adapt a grid search code I wrote to Bayesian Monte Carlo Markov Chain approach, and I'm using PyMC3. My problem is that the code has to call a function that can't be rewritten in theano syntax. (The function relies on a piece of Fortran code in an f2py wrapper.)
Here's the code I'm working with:
with pm.Model() as model:
# Independent parameters
x = pm.Normal('x', sx, sd=incx*float(nrangex)/2.0)
y = pm.Normal('y', sy, sd=incy*float(nrangey)/2.0)
depth = pm.Normal('depth', sdepth, sd=incdepth*float(nrangedepth)/2.0)
length = pm.Normal('length', slength, sd=inclength*float(nrangelength)/2.0)
width = pm.Normal('width', swidth, sd=incwidth*float(nrangewidth)/2.0)
strike = pm.Normal('strike', sstrike, sd=incstrike*float(nrangestrike)/2.0)
dip = pm.Normal('dip', sdip, sd=incdip*float(nrangedip)/2.0)
rake = pm.Normal('rake', srake, sd=incrake*float(nrangerake)/2.0)
# Model (This is the part that doesn't work.)
los_disp = zne2los(getdisp(lon2km(dsidata['lon'], x), lat2km(dsidata['lat'], y), depth, length, width, strike, dip, rake))
# Likelihood
odisp = pymc3.Normal('los_disp', mu = los_disp, sd = 0.5, observed = dsidata['disp'])
# Sampling
trace = pm.sample(100)
What this code is trying to do is invert for earthquake source parameters from ground displacement data. The dsidata data frame contains ground displacement data as a function of latitude and longitude. I'm trying to solve for the eight earthquake source parameters that produce the best fit to this ground surface displacement.
The getdisp function simply cannot be rewritten for theano because it calls a piece of Fortran that forward models ground surface displacement from earthquake source parameters. Is there a way to compile non-theano code into a theano form? Is there another way do this?
Since I'm new to this, and I can't find many great examples to look at, there may well be other errors in the code. Are there other mistakes I'm making?

Electromagnetic force harmonics in time and space in Python

I have to calculate radial force harmonics of an electrical motor and represent them in time and space. The method used to find radial forces is Maxwell Stress Tensor (the method is implemented in a FEM solver: Gmsh and from there I obtained the values for radial and tangential flux density). I imported in Python all datas and here I wrote the expression for radial force, something like this:
def integrateForces (Axiallength,dtheta,Rad,br,bt):
integral_rad =0
for i in range(len(br)):
integral_rad += (1/(2*mu0)*(br[i]*br[i]-bt[i]*bt[i])*Axiallength*Rad*dtheta)
return integral_rad
And now I want to represent fft of radial force in time and space, but I don't know how. All I got is fft in time, and the code is this:
Fs = 100 #sampling frequency
n = 145 #number of samples
t = np.linspace(0,n/Fs,n) # time vector
y = fradial
def plotFFT(t,y,Fs,n):
fft_v = np.fft.fft(y)
fft_pow = np.abs(fft_v)/t.shape[-1]
freq = np.fft.fftfreq(t.shape[-1],d=t[2]-t[1])
# basically fftfreq returns the frequencies
pl.figure(figsize=(8,5))
pl.xlabel('Frequency [Hz]',fontsize =13)
pl.ylabel('Power spectrum',fontsize =13)
baseline = pl.stem(freq,fft_pow)
pl.axis([-0.1,100,0,45])
pl.xscale('symlog', linthreshx=0.1)
pl.yscale('symlog', linthreshx=0.1)
pl.setp(baseline, 'color','b', 'linewidth', 2)
pl.grid()
pl.show()
plotFFT(t,y,Fs,n)
Any idea will be helpful. Thank you !

Categories

Resources