import numpy as np from os import mkdir, remove, system from os.path import join, exists from subprocess import call from math import log # changes the parameter file such that gridfile is used def writeINI(gridfile): # storage for file content lines = None # new line to write newline = "gridfile = " + gridfile # indicates whether the parameter gridfile already exists hasGridlineParameter = False # read file content and replace gridfile parameter if existent with open("parameterMMDG.ini", "r") as file: lines = file.read().splitlines() for i in range(len(lines)): if (lines[i].startswith("gridfile")): lines[i] = newline hasGridlineParameter = True break # add parameter gridfile if not already existent if (not hasGridlineParameter): lines.append(newline) # write parameters to file with open("parameterMMDG.ini", "w") as file: file.write("\n".join(lines)) # reads error, run time and maximum edge length, i.e. the output from the # excuted discontinuous Galerkin scheme def readData(): file = open("convergenceData", "r") # read data errorBulk = float(file.readline()) errorInterface = float(file.readline()) errorTotal = float(file.readline()) hMax = float(file.readline()) hMaxInterface = float(file.readline()) timeTotal = float(file.readline()) file.close() # return data return np.array([errorBulk, errorInterface, errorTotal, hMax, \ hMaxInterface, timeTotal]) # determines the problem type and the parameter "fastEOC" from the ini file def getProblemType (): # storage for problem type (1 to 6) problemType = None # boolean that determines whether to exclude computationally expensive grids fastEOC = False # read file content and get problem type with open("parameterMMDG.ini", "r") as file: lines = file.read().splitlines() for i in range(len(lines)): if (lines[i].startswith("problem")): problemType = int(lines[i].rstrip()[-1]) elif (lines[i].startswith("fastEOC") and \ lines[i].rstrip().lower().endswith("true")): fastEOC = True return problemType, fastEOC # determines experimental order of convergence (EOC), # data is assumed to be a numpy array with # first column: error, # second column: maximum edge length def EOCloop (data): EOC = np.empty(data.shape[0] - 1) for i in range(len(EOC)): if data[i, 0] != 0: EOC[i] = log(data[i, 0] / data[i+1, 0]) / \ log(data[i, 1] / data[i+1, 1]) else: EOC[i] = -1.0 * float('inf') # end for i return EOC # === main === # create directory for the plots if necessary if not exists("plots"): mkdir("plots") # number of runs from which the run times are taken as mean value numberOfMeans = 1 # names of the grid files sorted by refinement # 2d characteristic lengths: np.reciprocal(np.logspace(0,2.7,12)) # 3d characteristic lengths: np.reciprocal(np.logspace(0,1.55,7)) gridfiles_2d = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"] gridfiles_3d = ["A", "B", "C", "D", "E", "F", "G"] # get problem type (integer from 1 to 6) from ini file problemType, fastEOC = getProblemType() if problemType in [1, 4, 6, 7]: # these problems use the same grids problemType = 2 if fastEOC: # exclude computationally expensive grids gridfiles_2d = gridfiles_2d[:-3] gridfiles_3d = gridfiles_3d[:-2] else: print("fastEOC = false. This may take some minutes.\n") gridfiles_2d = ["mmdg" + str(problemType) + "_" + s for s in gridfiles_2d] gridfiles_3d = ["mmdg" + str(problemType) + "_" + s for s in gridfiles_3d] for dim in [2, 3]: gridfiles = gridfiles_2d if (dim == 2) else gridfiles_3d # storage for errors, run times and largestEdgeLength # column 0: bulk error # column 1: interface error # column 2: total error # column 3: maximum edge length (bulk) # column 4: maximum edge length (interface) # column 5: total run time # different rows correspond to different numbers of grid elements data = np.zeros((len(gridfiles), 6)) for i in range(len(gridfiles)): # write dgf file writeINI(gridfiles[i]) # take mean value over numberOfMeans runs for j in range(numberOfMeans): # run executable call(join(".", "mmdg-" + str(dim) + "d")) # store data data[i, :] += readData() # end for j # end for i # divide by numberOfMeans data /= numberOfMeans # determine experimental order of convergence (EOC) EOCbulk = EOCloop(data[:, [0,3]]) EOCinterface = EOCloop(data[:, [1,4]]) EOCtotal = \ EOCloop(np.column_stack([data[:,2], np.maximum(data[:,3], data[:,4])])) # print EOCs print("\n-------------------------------------------------------------\n") print("EOCs (" + str(dim) + "d):") print("\nbulk:") print(EOCbulk) print("\ninterface:") print(EOCinterface) print("\ntotal:") print(EOCtotal) print("\n=============================================================\n\n") # write data to file np.savetxt(join("plots", "mmdgAnalysis_" + str(dim) + "d"), data) np.savetxt(join("plots", "mmdgEOC_" + str(dim) + "d"), EOCtotal) # end for dim # remove output files remove("convergenceData")