def extract_deformation_curve_solver(folder, x): # get simulation parameters with open(folder + '/parameters.txt', 'r') as f: lines = f.readlines() parameters = {} for line in lines: try: key, value = line.split('= ') value = value.split(' ')[0] parameters[key.strip()] = float(value.strip()) except: pass # load coordinates M = saenopy.load(folder + "/solver.npz") coords = M.R # load displacements displ = M.U # compute binned normed displacements and normed coordinates u = np.sqrt(np.sum(coords**2., axis=1)) / (parameters['INNER_RADIUS'] * 10**-6) v = np.sqrt(np.sum(displ**2., axis=1)) / (parameters['INNER_RADIUS'] * 10**-6) y = np.array([ np.nanmedian(v[(u >= x[i]) & (u < x[i + 1])]) for i in range(len(x) - 1) ]) # save results results = { 'pressure': parameters['PRESSURE'], 'bins': x, 'displacements': y } return results
def distribute_solver(func, const_args, var_arg='pressure', start=0.1, end=1000, n=120, log_scaling=True, n_cores=None, get_initial=True, max_iter=600, step=0.0033, conv_crit=0.01, callback=None): # get_intial = True takes the deformationfield from previous simulation as start values for the next simulations, which reduces computation time # by default use spherical contraction as function func = spherical_contraction_solver if n_cores is None: n_cores = os.cpu_count() if log_scaling: values = np.logspace(np.log10(start), np.log10(end), n, endpoint=True) else: values = np.linspace(np.log10(start), np.log10(end), n, endpoint=True) outfolder = const_args['outfolder'] del const_args['outfolder'] if not os.path.exists(outfolder): os.makedirs(outfolder) np.savetxt(outfolder + '/' + var_arg + '-values.txt', values) values = list(values) if n_cores == 1: U = None for index, v in enumerate(values): func(const_args["meshfile"], outfolder + '/simulation' + str(index).zfill(6), v, const_args["material"], None, None, False, U, max_iter, step, conv_crit) # get the last displacement name = outfolder + '/simulation' + str(index).zfill( 6) + "/solver.npz" if os.path.exists(name): M = saenopy.load(name) U = M.U # optionally call the callback if callback is not None: callback(index, len(values)) else: index = 0 processes = [] import multiprocessing while True: processes = [p for p in processes if p.is_alive()] if len(processes) < n_cores and index < len(values): v = values[index] U = None if get_initial == True: for i in range(index - 3, -1, -1): name = outfolder + '/simulation' + str(i).zfill( 6) + "/solver.npz" if os.path.exists(name): M = saenopy.load(name) U = M.U break p = multiprocessing.Process( target=func, args=(const_args["meshfile"], outfolder + '/simulation' + str(index).zfill(6), v, const_args["material"], None, None, False, U, max_iter, step, conv_crit)) p.start() processes.append(p) if callback is not None: callback(index, len(values)) index += 1 sleep(1.) if len(processes) == 0: break if callback is not None: callback(index, len(values)) return