Python Forum
Program exits with error, but can't discover which
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Program exits with error, but can't discover which
#1
Hello everyone,

I have written a program in python that calculates the gravitational force of 2 objects on eachother. To do this I divide the object in a lot of smaller point masses. I thus need a very large list of objects. For some reason I can't figure out, my program crashes when I use too many objects. However, I don't get any error messages except for 'exited with non zero status'. I tried explicitly catching errors in my code, but I get no message whatsoever. The program simply shuts down.

Then I thought maybe my program was using too much memory, so I tried to check for memory usage.  The program crashes when a little over 2% of the total available memory is used... Those are about 600.000 objects using ~ 316 MB.

Right now I can't think of anything else that could cause this problem or how to find it. You can find the relevant part of my code on repl[dot]it/EwS1/555 (anti-spam won't let me post links yet)

The problem is caused by the calculateElements function of the HollowSphere class. The number of objects created is defined by N_r, N_phi and N_theta, the total  amount will be N_r * N_phi * N_theta.

Any ideas on how to tackle this problem are greatly appreciated!

BTW: the program works just fine when I use fewer objects.
Reply
#2
Can you determine at what point the code is crashing upon load, or after.
Can you share the code It's mighty difficult to be of any help without it.
Otherwise, my only suggestions would be to insert a lot of print statements
or run a debugger like pdb, or the built in debugger of PyCharm
to start, simple print statements immediately after your def statements will isolate to the method or function
where the problem arises.
Reply
#3
Hey,

I included my code in this post. You can run it here as well: repl.it/EwS1/555

For this project I'm using repl.it because I can easily share my code with someone else without him having to setup python on his machine.

import numpy as np
import scipy.constants
import math
import time



import os
import psutil

from psutil import virtual_memory

mem = virtual_memory().total >> 20
#print("Maximum memory: ", virtual_memory().total/ float(2 ** 20))

def memory_usage_psutil():
    # return the memory usage in MB
    
    process = psutil.Process(os.getpid())
    mem = process.memory_info()[0] >> 20 # / float(2 ** 20)
    return mem

t_start = time.time()

# print update every t_update s
t_update = 2

pi = scipy.constants.pi
G = scipy.constants.G 


class Mass:
	def __init__(self, p_x):
		pass
	
	def calcForceFrom(self, p_mass):
		F_total = np.array([0.0, 0.0, 0.0])
		
		#print("{:=^80}".format(" Running simulation "))
		#print("{:>20}{:>20}{:>20}".format("completed", "step", "runtime"))
		
		t_sim_start = time.time()
		t_prev = time.time()
		N = len(self.elements)
		
		for i, element in enumerate(self.elements):
			p_mass.calcForceOn(element)
			F_total = F_total + element.sum_of_forces
			
			t_now = time.time()
			
			#if t_now - t_prev > t_update:
			#	print("{: 19.2f}%{: 11d} of {: 5d}{:>19.1f}s".format(i/N*100,i, N, t_now - t_sim_start))
			#	t_prev = t_now
		
		#t_now = time.time()
		#print("{: 19.2f}%{: 11d} of {: 5d}{:>19.1f}s".format(100, N, N, t_now - t_sim_start))
		return F_total * G
		
	
	
	def calcForceOn(self, p_target):
		# calculates the force from this Mass on some point mass
		
		for element in self.elements:
			p_target.addForce(Mass.F(p_target, element))
		#map(lambda e: p_target.addForce(Mass.F(p_target, e)), self.elements)
	
	@staticmethod
	def F(p_target, p_element):
		# difference vector
		r = p_element.x - p_target.x
		
		# calculate length squared
		rr = r.dot(r)
		
		#normalize r
		r = r/math.sqrt(rr)
		
		# calculate force
		return p_element.m * p_target.m / rr * r
		
class MassElement:
	
	def __init__(self, p_x, p_m):
		self.x = p_x
		self.m= p_m
		
		self.resetForces()
		
	def addForce(self, p_force):
		self.sum_of_forces  = self.sum_of_forces + p_force
		
	def resetForces(self):
		self.sum_of_forces = np.array([0,0,0])

class HollowSphere(Mass):
	
	N_r = 300
	N_phi = 100
	N_theta = 200
	
	dtheta = 2*pi / N_theta
	dphi = pi/ N_phi
	
	def __init__(self, p_x, p_r1, p_r2, p_m):
		# position
		self.x = p_x
		# radius
		self.r = p_r2
		# mass
		self.m = p_m
		
		#inner radius 
		self.r_in = p_r1
		
		#density
		self.rho = self.m / (4/3 * pi * (self.r**3 - self.r_in**3))
		
		# for calculating integrals
		self.dr = (self.r - self.r_in) / ( self.N_r)
		
		self.total_mass = 0
		self.elements = self.calculateElements()
		
		mem_cur =  memory_usage_psutil()
		mem_max = virtual_memory().total >> 20 #/ float(2 ** 20)
		
		print ("Done: {:>6.1f} / {:>6.1f} MiB used ({:>3.2f}%); {:>8d} objects".format(mem_cur, mem_max, mem_cur/mem_max*100, len(self.elements)))
		
		
		print("{:=^80}".format(" Sphere created "))
		print("{:<30}({:> 8.5f},{:> 8.5f},{:> 8.5f}) [m]".format('Position', *self.x))
		print("{:<30}{:>28.5f} [m]".format('Radius', self.r))
		print("{:<30}{:>28.5f} [kg]".format('Mass', self.m))
		print("{:<30}{:>28.5f} [kg]".format('Total mass of elements', self.m))
		print("{:<30}{:>28.5f} [kg/m^3]".format('density', self.rho))
		print(" ")
	
	
	def calculateElements(self):
		elements = []
		
		for i in range(0, self.N_theta):
			
			try:
				theta_i = i * self.dtheta
			except e:
				print(e)
			
			mem_cur =  memory_usage_psutil()
			mem_max = virtual_memory().total >> 20
			
			n_obj = len(elements)
			
			
			print ("{:> 4d}: {:>6.1f} / {:>6.1f} MiB used ({:>3.2f}%); {:>8d} objects".format(i, mem_cur, mem_max, mem_cur/mem_max*100, n_obj))
			
			for j in range(0, self.N_r):
				try:
					r_j = (j + 0.5) * self.dr + self.r_in
				except e:
					print(e)
				
				try:
					for k in range(0, self.N_phi):
						
						try:
							phi_k = (k + 0.5) * self.dphi
						except e:
							print(e)
						
						try:
							x_el = self.x + np.array([r_j * math.cos(theta_i) * math.sin(phi_k), r_j * math.sin(theta_i) * math.sin(phi_k), r_j *  math.cos(phi_k)])
						except e:
							print(e)
							
						try:
							m_el = self.rho * r_j**2 * math.sin(phi_k) * self.dr * self.dtheta * self.dphi
						except e:
							print(e)
						
						try:
							el = MassElement(x_el, m_el)
						except e:
							print(e)
						try:
							elements.append(el)
						except e:
							print(e)
							
						try:
							self.total_mass += el.m
						except e:
							print(e)
				
				except e:
					print(e)
					
		return tuple(elements)

m3 = 100                    # massa [kg]
r3 = 1                     # straal [m]
x3 = np.array([0,0,0])     # positie [m]

sphere1 = HollowSphere(x3, 0.5*r3, r3, m3)
sphere2 = HollowSphere(x3, 0.5*r3, r3, m3)
sphere3 = HollowSphere(x3, 0.5*r3, r3, m3)
Here is the last part of the output of my script:
Output:
[...]  58:  305.0 / 15039.0 MiB used (2.03%);   580000 objects  59:  310.0 / 15039.0 MiB used (2.06%);   590000 objects  60:  314.0 / 15039.0 MiB used (2.09%);   600000 objects
After this it just stops. No errors. Sometimes I get the message: 'exited with non zero status', other times the console 'reboots' (for lack of a better term.) Other than that I can't find anything..

Edit: somehow the forum software removed all indentation from my code...? I had to paste it again to fix it.
Reply
#4
Works for me, the last lines are:
Output:
195: 8437.0 / 32010.0 MiB used (26.36%); 5850000 objects 196: 8451.0 / 32010.0 MiB used (26.40%); 5880000 objects 197: 8465.0 / 32010.0 MiB used (26.44%); 5910000 objects 198: 8480.0 / 32010.0 MiB used (26.49%); 5940000 objects 199: 8494.0 / 32010.0 MiB used (26.54%); 5970000 objects Done: 8508.0 / 32010.0 MiB used (26.58%); 6000000 objects ================================ Sphere created ================================ Position ( 0.00000, 0.00000, 0.00000) [m] Radius 1.00000 [m] Mass 100.00000 [kg] Total mass of elements 100.00000 [kg] density 27.28370 [kg/m^3]
Operating systems work like airlines, they overbook (over-allocate) memory because many processes don't really use all the memory they ask for. But when a process insists in getting the promised memory, while the OS cannot fulfill the promise, the process is summarily killed (because it"s too late to give it a return code). Airlines aren't there yet :)
Unless noted otherwise, code in my posts should be understood as "coding suggestions", and its use may require more neurones than the two necessary for Ctrl-C/Ctrl-V.
Your one-stop place for all your GIMP needs: gimp-forum.net
Reply
#5
Well, I guess I can't rely on repl.it for this task. Too bad. I'll just run my simulations locally then.

Thanks for your help!
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020