From f00cf43d14c9a4bc75ed4d506ca182b30bf023c9 Mon Sep 17 00:00:00 2001 From: Craig Warren Date: Thu, 4 Aug 2016 15:59:34 +0100 Subject: [PATCH] Added error check for when model could use more RAM than available. --- gprMax/input_cmds_singleuse.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/gprMax/input_cmds_singleuse.py b/gprMax/input_cmds_singleuse.py index 100dec48..f41a59c5 100644 --- a/gprMax/input_cmds_singleuse.py +++ b/gprMax/input_cmds_singleuse.py @@ -19,11 +19,12 @@ import os import psutil import decimal as d +import sys import numpy as np from gprMax.constants import c, floattype -from gprMax.exceptions import CmdInputError +from gprMax.exceptions import CmdInputError, GeneralError from gprMax.utilities import round_value, human_size from gprMax.waveforms import Waveform @@ -112,33 +113,38 @@ def process_singlecmds(singlecmds, G): raise CmdInputError(cmd + ' requires at least one cell in every dimension') if G.messages: print('Domain size: {:g} x {:g} x {:g}m ({:d} x {:d} x {:d} = {:g} cells)'.format(tmp[0], tmp[1], tmp[2], G.nx, G.ny, G.nz, (G.nx * G.ny * G.nz))) - # Guesstimate at memory usage - mem = (((G.nx + 1) * (G.ny + 1) * (G.nz + 1) * 13 * np.dtype(floattype).itemsize + (G.nx + 1) * (G.ny + 1) * (G.nz + 1) * 18) * 1.1) + 30e6 - print('Memory (RAM) usage: ~{} required, {} available'.format(human_size(mem), human_size(psutil.virtual_memory().total))) + + # Estimate memory (RAM) usage + if G.messages: + # Currently this is a pretty loose estimate but seems to match reasonably with memory usage reported when model completes. + memestimate = (((G.nx + 1) * (G.ny + 1) * (G.nz + 1) * 13 * np.dtype(floattype).itemsize + (G.nx + 1) * (G.ny + 1) * (G.nz + 1) * 18) * 1.1) + 30e6 + print('Memory (RAM) usage: ~{} required, {} available'.format(human_size(memestimate), human_size(psutil.virtual_memory().total))) + if memestimate > psutil.virtual_memory().total: + raise GeneralError('Estimated memory (RAM) required ~{} exceeds {} available!\n'.format(human_size(memestimate), human_size(psutil.virtual_memory().total))) # Time step CFL limit (use either 2D or 3D) and default PML thickness if G.nx == 1: G.dt = 1 / (c * np.sqrt((1 / G.dy) * (1 / G.dy) + (1 / G.dz) * (1 / G.dz))) - G.dtlimit = '2D' + gridtype = '2D' G.pmlthickness = (0, G.pmlthickness, G.pmlthickness, 0, G.pmlthickness, G.pmlthickness) elif G.ny == 1: G.dt = 1 / (c * np.sqrt((1 / G.dx) * (1 / G.dx) + (1 / G.dz) * (1 / G.dz))) - G.dtlimit = '2D' + gridtype = '2D' G.pmlthickness = (G.pmlthickness, 0, G.pmlthickness, G.pmlthickness, 0, G.pmlthickness) elif G.nz == 1: G.dt = 1 / (c * np.sqrt((1 / G.dx) * (1 / G.dx) + (1 / G.dy) * (1 / G.dy))) - G.dtlimit = '2D' + gridtype = '2D' G.pmlthickness = (G.pmlthickness, G.pmlthickness, 0, G.pmlthickness, G.pmlthickness, 0) else: G.dt = 1 / (c * np.sqrt((1 / G.dx) * (1 / G.dx) + (1 / G.dy) * (1 / G.dy) + (1 / G.dz) * (1 / G.dz))) - G.dtlimit = '3D' + gridtype = '3D' G.pmlthickness = (G.pmlthickness, G.pmlthickness, G.pmlthickness, G.pmlthickness, G.pmlthickness, G.pmlthickness) # Round down time step to nearest float with precision one less than hardware maximum. Avoids inadvertently exceeding the CFL due to binary representation of floating point number. G.dt = round_value(G.dt, decimalplaces=d.getcontext().prec - 1) if G.messages: - print('Time step (at {} CFL limit): {:g} secs'.format(G.dtlimit, G.dt)) + print('Time step (at {} CFL limit): {:g} secs'.format(gridtype, G.dt)) # Time step stability factor cmd = '#time_step_stability_factor'