def fem_orig_data(fci,fdi,nnf,nne,*args): if len(args)==0: file = open("iterations.txt","r") it = int(file.readline()) file.close filen = "fem_orig_data%s.npy"%it path1 = filepaths("path1") elif len(args)>0: it = 0 filen = "fem_orig_data%s.npy"%it # "fci", "fdi" is saved to this file pat = filepaths("path1") fl = args[0] path1 = os.path.join(pat,fl) filepath = os.path.join(path1,filen) if not os.path.exists(path1): os.makedirs(path1) n_inc = fci.shape[0] fcd = fci.shape[-1] fdc = fdi.shape[-1] col = fcd + fdc femdata = np.empty([n_inc,nnf,col]) femdata[:,:,:fcd] = fci femdata[:,:,fcd:col] = fdi np.save(filepath,femdata) # saves the original FEM data as a .npy file
def expdata(ce,de,fvr,nne,*args): n_inc = ce.shape[0] cc = ce.shape[-1] dc = de.shape[-1] col = cc+dc if len(args)==0: file = open("iterations.txt","r") it = int(file.readline()) file.close exp_data_File = "exp_data%s.npy"%it RBF_data_File = "RBF_data%s.npy"%it path1 = filepaths("path1") elif len(args)>0: it = 0 exp_data_File = "exp_data%s.npy"%it # "ce", "de" and "stot" is saved to this file RBF_data_File = "RBF_data%s.npy"%it # "fvr" is saved to this file pat = filepaths("path1") fl = args[0] path1 = os.path.join(pat,fl) filepath = os.path.join(path1,exp_data_File) filepath1 = os.path.join(path1,RBF_data_File) if not os.path.exists(path1): os.makedirs(path1) expdata = np.empty([n_inc,nne,col]) expdata[:,:,:cc] = ce expdata[:,:,cc:col] = de np.save(filepath,expdata) # save experimental data to this file np.save(filepath1,fvr) # save the numerical interpolated data to this file
def append_val(X,n_iter,n_obj): file = open("iterations.txt","r") # loads the iterations file to determine which starting points data this is it = int(file.readline()) file.close filen = "results%s.py"%it # the file where the final results will be written to, the path1 line below changes # for each NUMERICAL model in the "File_paths" function # // The path1 line below needs to change for each simulation or depending where the files needs to be saved to path1 = filepaths("path1") filepath = os.path.join(path1,filen) if not os.path.exists(path1): os.makedirs(path1) with open(filepath, "a+") as c: c.write("#final values \n") st = "xf = %s \n"%X si = "iterations = %s \n"%n_iter # the results file is a .py file which only stores the begin and end point, sb = "objective = %s \n"%n_obj # the number of iterations, and the objective function at each iteration, c.write(st) # it also plot the results to show the convergence c.write("import matplotlib.pyplot as plt \n") c.write(si) c.write(sb) c.write("plt.plot(iterations,objective,'r-') \n") c.write("plt.xlabel('iteration') \n") c.write("plt.ylabel('Objective') \n") c.write("plt.show() \n") c.close()
def material2d(x): matp = filepaths("mat_app_path") with open('mat.proc', "w") as c: c.write(matp) c.write('\n') c.write('*edit_mater rubber\n') c.write('\n') m4 = '*mater_option structural:type:mooney\n' m1 = '*mater_param structural:mooney_c10 %s\n'%x[0] m2 = '*mater_param structural:mooney_c01 %s\n'%x[1] c.write(m1) c.write(m2) c.write('*submit_job 1 *monitor_job\n') c.write('@popdown(job_properties_pm) @main(results) @popup(modelplot_pm) *post_open_default\n') c.write('*history_collect 0 999999999 1\n') c.write('*prog_option history_plot:data_carrier_type_y:cbody\n') c.write('*set_history_data_carrier_cbody_y\n') c.write('load\n') c.write('*set_history_cbody_variable_y\n') c.write('Pos Y\n') c.write('*history_add_curve\n') c.write('*history_fit\n') c.write('*history_write points1 yes\n') c.write('*post_close\n') c.write('*save_model *quit yes') c.close()
def final_points(X,*args): filen = "final_points.txt" if len(args)==0: path1 = filepaths("path1") elif len(args)>0: pat = filepaths("path1") fl = args[0] path1 = os.path.join(pat,fl) filepath = os.path.join(path1,filen) if not os.path.exists(path1): os.makedirs(path1) with open(filepath, "a+") as c: st = "%s \n"%X c.write(st) c.close()
def objectfunc(obj,ite): file = open("iterations.txt","r") it = int(file.readline()) file.close objf = "objectfunction%s.npy"%it # "obj" is saved to this file iterf = "niter%s.npy"%it # "ite" is saved to this file path1 = filepaths("path1") objpat = os.path.join(path1,objf) iterpat = os.path.join(path1,iterf) if not os.path.exists(path1): os.makedirs(path1) np.save(objpat,obj) np.save(iterpat,ite)
def violated_constr(X,con): file = open("iterations.txt","r") # Calls the iterations file to know during which strating points optimisation # the constraints were violated it = int(file.readline()) file.close filen = "violated%s.txt"%it #// The path1 line needs to change for each simulation, depending where the file is stored path1 = filepaths("path1") filepath = os.path.join(path1,filen) if not os.path.exists(path1): os.makedirs(path1) with open(filepath, "a+") as v: vs = "x = %s \n"%X # the function only open the violated file to store the coefficient # which caused non-convergence vc = "Exit number: %s \n"%con # It also saves the exit number given by Marc v.write("\n") v.write("Material properties \n") v.write(vs) v.write(vc) v.close()
def remesh_proc(x,fm): matp = filepaths("mat_app_path") with open('remesh.proc', "w") as c: c.write(matp) c.write('\n') c.write('*edit_mater rubber\n') c.write('\n') m1 = '*mater_param structural:mooney_c10 %s\n'%x[0] m2 = '*mater_param structural:mooney_c01 %s\n'%x[1] m3 = '*mater_param structural:mooney_c20 %s\n'%x[2] c.write(m1) c.write(m2) c.write(m3) c.write('*edit_adapg adapg1\n') fine = '*adapg_dens_ctrl_param 1 target_edge_length %s\n'%fm fine1 = '*adapg_dens_ctrl_param 2 small_edge_length_cv %s\n'%fm c.write(fine) c.write(fine1) c.write('*edit_job job1\n') c.write('*update_job\n') c.write('*save_model\n') c.write('*submit_job 1 *monitor_job\n') c.write('@popdown(job_properties_pm) @main(results) @popup(modelplot_pm) *post_open_default\n') c.write('*save_model\n') c.write('*history_collect 0 999999999 1\n') c.write('*prog_option history_plot:data_carrier_type_y:cbody\n') c.write('*set_history_data_carrier_cbody_y\n') c.write('load\n') c.write('*set_history_cbody_variable_y\n') c.write('Pos Y\n') c.write('*history_add_curve\n') c.write('*history_fit\n') c.write('*history_write pointfem yes\n') c.write('*post_close\n') c.write('*save_model *quit yes') c.close()
def dotcall(self, x, xl, xu, nCons): # Reset nInit nInit = 0 #Initailize all array types nDvar = x.shape[0] ctDVAR = ct.c_double * nDvar ctCONS = ct.c_double * nCons ctRPRM = ct.c_double * 20 ctIPRM = ct.c_int * 20 #Initialize all arrays RPRM = ctRPRM(*(self.nmRPRM)) #Tells dot to use defaults IPRM = ctIPRM(*(self.nmIPRM)) #Tells dot to use defaults X = ctDVAR(*(x)) #Initial values XL = ctDVAR(*(xl)) #Lower bounds XU = ctDVAR(*(xu)) #Upper bounds G = ctCONS(*([0.0] * nCons)) #Constraints #Initialize constants METHOD = ct.c_int64(self.nMethod) NDV = ct.c_int64(nDvar) NCON = ct.c_int64(nCons) IPRINT = ct.c_int64(self.nPrint) MINMAX = ct.c_int64(self.nMinMax) INFO = ct.c_int64(self.nInfo) OBJ = ct.c_double(0.0) MAXINT = ct.c_int64(self.nMaxInt) # Call DOT510 NRWK = ct.c_int64() NRWKMN = ct.c_int64() NRIWD = ct.c_int64() NRWKMX = ct.c_int64() NRIWK = ct.c_int64() NSTORE = ct.c_int64() NGMAX = ct.c_int64() IERR = ct.c_int64() self.dotlib.DOT510(B(NDV), B(NCON), B(METHOD), B(NRWK), B(NRWKMN), B(NRIWD), B(NRWKMX), B(NRIWK), B(NSTORE), B(NGMAX), B(XL), B(XU), B(MAXINT), B(IERR)) ctRWK = ct.c_double * NRWKMX.value ctIWK = ct.c_int64 * NRIWK.value IWK = ctIWK(*([0] * NRIWK.value)) WK = ctRWK(*([0.0] * NRWKMX.value)) # Call DOT # // Here the original dot.py code was edited for personal use. The code can be adjusted as suited to the user. # // The iterations and objective lists were created as my own counter and is not necessary. These lists were # however used in this pipeline. itera = 0 iterations = [] objective = [] while (True): self.dotlib.DOT(B(INFO), B(METHOD), B(IPRINT), B(NDV), B(NCON), B(X), B(XL), B(XU), B(OBJ), B(MINMAX), B(G), B(RPRM), B(IPRM), B(WK), B(NRWKMX), B(IWK), B(NRIWK)) iterations.append(itera) objective.append(OBJ.value) itera = itera + 1 if (INFO.value == 0): # if the optimisation converged, enter loop import ast # // Open the "iterations" text file to obtain the current design point/ starting point form the list # obtained by the LHC function filec = open("iterations.txt", "r") it = int(filec.readline()) filec.close # // path1 = filepaths("path1") # // Read what the original starting point was of this optimisation run. filen = "starting_points.txt" filp = os.path.join(path1, filen) start = open(filp, 'r') xxx = ast.literal_eval(start.readlines()[it]) start.close() xxx = nm.array(xxx) xc = nm.array(X) print(xxx) print(xc) xa = xc * xxx # the final design point from dot is multiplied with the starting point to obtain the print( xa ) # material coefficient values, since the current values are the unbiased values. from functions import append_val, expdata, fem_orig_data, final_points # call the output functions needed if len(X) == 3: xf = [ xa[0], xa[1], xa[2] ] # store the optimised point in a form easily written to a text file elif len(X) == 2: xf = [xa[0], xa[1]] time.sleep(1) append_val( xf, iterations, objective ) # Writes out the iteration file to show how it converged final_points( xf) # store the optimised point in a separate file time.sleep(1) from functions import material2d, material3d, material3d_ogden if len(X) == 3: material3d( xa ) # Create new procedure file for the optimised point elif len(X) == 2: material2d(xa) time.sleep(1) filem = "mat.proc" p = subprocess.Popen( ["mentat.bat", filem], bufsize=2048) # Start MSC Marc and load the procedure # file which will open the correct NUMERICAL model and change the material properties, start Marc # solver and to save the post file for the current DOT increment, close Marc and continue with the # code below p.wait() time.sleep(5) # Ensure that Marc file converged sts = filepaths("fem_sts") conver = pd.read_csv(sts, header=None, sep=' ', names=list(range(11)), keep_default_na=False) # open sts file of the optimisation NUMERICAL model, it contains the exit code from Marc. time.sleep(1) c = int(conver.iloc[-3, -1]) if c == 3004: g = -1 # 3004 says the FEM converged and the constraint is satisfied else: g = 1 # Any other exit number says the FEM did not converge and therefore the constraint # was not satisfied. This is a fail save to ensure the optimised point does adhere to the constraints. xv = xa time.sleep(1) from functions import violated_constr violated_constr( xv, c ) # This function saves the parameters which caused non-convergence and # also what the exit number was print(g) from RBF import RBF_int # call the RBF function fname1, fname2, fname3, fname4, fnamef, fnamee = filepaths( "fem_out", "pointfem", "exp_out", "pointexp", "fem_dat", "exp_dat") # // All the data after interpolation ce, de, fci, fdi, fvr, nne, nnf, dm = RBF_int( fname1, fname2, fname3, fname4, fnamef, fnamee, g) time.sleep(1) # // expdata( ce, de, fvr, nne) # Store the experimental data for the starting point fem_orig_data( fci, fdi, nnf, nne ) # Store the ouput data for the optimised point's simulation time.sleep(1) from functions import objectfunc objectfunc(objective, iterations) rem = filepaths("mat_proc_path") os.remove(rem) # os.remove('../Cylinder/mat.proc') break else: # if the optimisation procedure haven't converged yet fname1 = filepaths("fem_out") os.remove( fname1 ) #delete the current DOT optimisation increment's NUMERICAL data self.evaluate(X, OBJ, G, self.nmParam) # // rslt = nm.empty(2 + nDvar, float) rslt[0] = OBJ.value rslt[1] = 0.0 if len(G) > 0: rslt[1] = max(G) for i in range(nDvar): rslt[2 + i] = X[i] return rslt
def post_process(dm, *args): print('Start') #--------------------------------------------------------------------------------------- # ---- Unindent the following lines when two optimisation algorithms are used # NB !!!!! - Remember to unindent lines # algpat1 = "SQP Optimisation Algorithm" # algpat2 = "SLP Optimisation Algorithm" #--------------------------------------------------------------------------------------- # plt.close('all') filen = "final_points.txt" if len(args) == 0: path1 = filepaths("path1") path2 = filepaths("path2") filet = open( "iterations.txt", "r" ) # determine how many starting point iterations there were (ex. 10), # The results for each starting point iteration will be plotted. it = int(filet.readline()) filet.close elif len(args) > 0: pat = filepaths("path1") pat2 = filepaths("path2") fl = args[0] path1 = os.path.join(pat, fl) path2 = os.path.join(pat2, fl) it = 0 filepath = os.path.join(path1, filen) if not os.path.exists(path1): os.makedirs(path1) filepath2 = os.path.join(path2, filen) if not os.path.exists(path2): os.makedirs(path2) filere = "Final_results.txt" # Create a text file with the final errors filepathf = os.path.join(path1, filere) filerb = "Best_Final_results.txt" # Create a text file with only the optimisation run with # the best smallest objective function filepathb = os.path.join(path1, filerb) file = open(filepath, 'r') s = ast.literal_eval(file.readlines()[0]) xf = np.empty([it + 1, len(s)]) rms_d = [] for i in range(it + 1): file.seek(0, os.SEEK_SET) x = ast.literal_eval(file.readlines( )[i]) # read from the "final_points.txt" read the optimised parameters for j in range(len(x)): xf[i, j] = x[j] coefshape = xf.shape[1] orig_coef = [0.26056762, 0.09754981, 0.05750069 ] # The original parameters as used by the "EXP" model lower_coef = [0.208454096, 0.078039848, 0.046000552] # Lower bound high_coef = [0.312681144, 0.117059772, 0.069000828] # Upper bound ocdl = [] ocdh = [] # // Determine the difference in the coefficients and bounds for the % calculation for hl in range(len(orig_coef)): ocdl.append(orig_coef[hl] - lower_coef[hl]) ocdh.append(high_coef[hl] - orig_coef[hl]) per_acc = np.empty([it + 1, len(orig_coef)]) # // # // Using the Mooney-Rivlin three parameter equation for a uni-axial tensile case, the engineering stress is # calculated for a given stretch range expsr_e = np.linspace(0.4, 3.0, 106) # Given stretch range expsr_f = np.linspace(0.4, 3.0, 106) stef = np.empty([it + 1, len(expsr_e), 2]) fvrsf = np.empty([it + 1, len(expsr_e), 2]) expse_f = np.empty([it + 1, len(expsr_e), 2 ]) # Empty arrays to store the calculated eng stresses expsf_f = np.empty([it + 1, len(expsr_e), 2]) expsff_f = np.empty([it + 1, len(expsr_e), 2]) rms_stsr = [] for k in range( it + 1 ): # Loop to calculate each optimisation run's results, errors and graphs fname1 = "RBF_data%s.npy" % k # Import the saved "NUM" results, after interpolation fname2 = "exp_data%s.npy" % k # Import the "EXP" results filepath1 = os.path.join(path1, fname1) filepath2 = os.path.join(path1, fname2) RBFdata = np.load(filepath1) expdata = np.load(filepath2) der = expdata[:, :, dm:( dm * 2 )] # The first few columns are the coordinates, the next few are the displacements # which are accessed here obj = RMS_disp( der, RBFdata) # The RMS error in the displacements are calculated rms_d.append(obj[0]) # // Using the MR three parameter equation for uni-axial tensile case, # - the eng stress for the "EXP" model is calculated = expst_e # - the eng stress for the "NUM" model is calculated = expst_f ty = 'Mooney-Rivlin' expst_e = 2 * orig_coef[0] * ( expsr_e - (1 / (expsr_e**2))) + 4 * orig_coef[2] * ( (expsr_e**2) + (2 / expsr_e) - 3) * (expsr_e - (1 / (expsr_e**2))) + 2 * orig_coef[1] * (1 - (1 / (expsr_e**3))) expst_f = 2 * xf[k, 0] * ( expsr_f - (1 / (expsr_f**2))) + 4 * xf[k, 2] * ( (expsr_f**2) + (2 / expsr_f) - 3) * (expsr_f - (1 / (expsr_f**2))) + 2 * xf[k, 1] * (1 - (1 / (expsr_f**3))) # The stretch values in the "NUM" model is calculated using the eng stress results above for the "EXP" model expsr_ff = np.zeros(len(expst_e)) for i in range(len(expst_e)): xc = lambda x: expst_e[i] - (2 * xf[k, 0] * (x - (1 / (x**2))) + 4 * xf[k, 2] * ( (x**2) + (2 / x) - 3) * (x - (1 / (x**2))) + 2 * xf[k, 1] * (1 - (1 / (x**3)))) sol = fsolve(xc, expsr_e[i]) # print(sol) expsr_ff[i] = sol # // ste = np.zeros([len(expsr_e), 2]) fvrs = np.zeros([len(expsr_e), 2]) # // Storing each optimisation run's eng stress and stretch values expse_f[k, :, 0], expse_f[ k, :, 1] = expst_e, expsr_e # Storing the "EXP" model's eng stress with the given stretch range expsf_f[k, :, 0], expsf_f[ k, :, 1] = expst_f, expsr_f # Storing the "NUM" model's eng stress for the same given stretch range expsff_f[k, :, 0], expsff_f[ k, :, 1] = expst_f, expsr_ff # Storing the "NUM" model's eng stress, with the stretch values calculated # at the "EXP" eng stress values, to calculate the error between the stretch results # // Storing only the current optimisation run's eng stress and stretch values for the error calculations ste[:, 0], ste[:, 1] = expst_e, expsr_e fvrs[:, 0], fvrs[:, 1] = expst_f, expsr_ff stef[k, :, :] = ste fvrsf[k, :, :] = fvrs rmsr = RMS_stvssr( ste, fvrs ) # determine the RMS error for the stress and then the stretch rms_stsr.append( sum(rmsr) ) # sum the two RMS errors for a combined RMS error for the stress and stretch # // Determine the % how far the optimised parameter is from the original parameter, # with the bounds being 0 % and the orig_coef parameter 100 % for l in range(len(orig_coef)): if (xf[k, l] <= orig_coef[l]): diff = orig_coef[l] - xf[k, l] per = (abs(diff - ocdl[l]) / ocdl[l]) * 100 per_acc[k, l] = per elif (xf[k, l] > orig_coef[l]): diff = xf[k, l] - orig_coef[l] per = (abs(diff - ocdh[l]) / ocdh[l]) * 100 per_acc[k, l] = per # // # // Determine which optimisation run had the best RMS value for the displacements and set that run as the preliminary "best", # for the optimisation runs which have RMS values within 5 % of the best, the final best optimisation run will be # chosen for the run which have the best combined stress and stretch RMS value. b_rms = min(rms_d) bestd = np.where(np.array(rms_d) == b_rms)[0][0] ub = rms_d[bestd] * 0.05 + rms_d[bestd] lb = rms_d[bestd] * 0.05 - rms_d[bestd] cnt = [] rms_obj = [] for t in range(it + 1): if (rms_d[t] >= lb) and (rms_d[t] <= ub): cnt.append(t) if len(cnt) > 1: for tt in cnt: rms_obj.append(rms_stsr[tt]) rb_rms = min(rms_obj) be = np.where(np.array(rms_obj) == rb_rms)[0][0] best = cnt[be] else: best = best # // print(best) fn = 2 objl = [] objlSP = [] # // Generate the graphs and error results for each optimisation run for bb in range(it + 1): fname = "fem_orig_data%s.npy" % bb fname1 = "RBF_data%s.npy" % bb fname2 = "exp_data%s.npy" % bb # Import all the saved data filepath = os.path.join(path1, fname) filepath1 = os.path.join(path1, fname1) filepath2 = os.path.join(path1, fname2) # obtain the correct file paths # ----------------------------------------------------------------------------------------------------------------- #----- Unindent the following lines only if two optimisation algorithms are used # ---- Only unindent before the 2nd algorithm is started, NOT during the 1st algorithm run # NB !!!! --- Remember to unindent lines 486 - 500 # fileobj = "objectfunction%s.npy"%bb # fileiter = "niter%s.npy"%bb # patobj = os.path.join(path1,fileobj) # patiter = os.path.join(path1,fileiter) # patobjSP = os.path.join(path2,fileobj) # objectivefunc = np.load(patobj) # objl.append(objectivefunc[-1]) # objectivefuncSP = np.load(patobjSP) # objlSP.append(objectivefuncSP[-1]) # numiter = np.load(patiter) # ----------------------------------------------------------------------------------------------------------------- femdata = np.load(filepath) RBFdata = np.load(filepath1) expdata = np.load(filepath2) sf = RBFdata.shape[0] fvr = RBFdata de = expdata[:, :, dm:( dm * 2 )] # obtain only the "EXP" model's disp data and not coordinate data seoefd = SEOE_disp(fvr, de) ste = stef[bb, :, :] fvrs = fvrsf[bb, :, :] expsr_e = expse_f[bb, :, 1] expst_e = expse_f[ bb, :, 0] # obtain the engineering stress and stretch calculated expsr_f = expsf_f[bb, :, 1] expst_f = expsf_f[bb, :, 0] rmsr = RMS_stvssr( ste, fvrs) # determine the RMS error for eng stress and stretch rsqs, alps, bets = RSQ_st( fvrs, ste) # determine the R^2 error for eng stress and stretch # print(rsqs) # print(alps) # print(bets) seoef = SEOE_str( fvrs, ste ) # determine the Standard Error of Estimation for eng stress and stretch incn = sf rmsd = RMS_disp( de, fvr) # determine the RMS error for each displacement direction rsq = RSQ_disp( fvr, de) # determine the R^2 error for each displacement direction # // Error result summary are written to text files if bb == best: with open(filepathb, "a+", encoding="utf-8") as fr: fr.write("According to THE BEST POINT - " + str(bb) + " the results are: \n") fr.write("The optimal %s coefficients are: \n" % ty) fr.write("\n") if len(orig_coef) == 3: fr.write("C10 = " + str(xf[bb, 0]) + "\nC01 = " + str(xf[bb, 1]) + "\nC20 = " + str(xf[bb, 2])) else: # web for unicodes for greek letter = https://pythonforundergradengineers.com/unicode-characters-in-python.html fr.write('\u03BC1 = ' + str(xf[bb, 0]) + "\n\u03BC2 = " + str(xf[bb, 1]) + "\n\u03BC3 = " + str(xf[bb, 2]) + '\n\u03B11 = ' + str(xf[bb, 3]) + "\n\u03B12 = " + str(xf[bb, 4]) + "\n\u03B13 = " + str(xf[bb, 5])) fr.write("\n") fr.write( "Percentage accuracy towards original model's coefficients: \n" ) fr.write("\n") if len(orig_coef) == 6: fr.write("\u03BC1 = " + str(per_acc[bb, 0]) + "\n\u03BC2 = " + str(per_acc[bb, 1]) + "\n\u03BC3 = " + str(per_acc[bb, 2]) + "\n\u03B11 = " + str(per_acc[bb, 3]) + "\n\u03B12 = " + str(per_acc[bb, 4]) + "\n\u03B13 = " + str(per_acc[bb, 5])) if len(orig_coef) == 3: fr.write("C10 = " + str(per_acc[bb, 0]) + "\nC01 = " + str(per_acc[bb, 1]) + "\nC20 = " + str(per_acc[bb, 2])) fr.write("\n") fr.write("It produced the following errors: \n") fr.write("\n") fr.write("Displacement RMS = " + str(rmsd[0]) + "\n") fr.write("Stress RMS = " + str(rmsr[0]) + "\n") fr.write("Strain RMS = " + str(rmsr[1]) + "\n") fr.write("Displacement x R**2 = " + str(rsq[0][0]) + "\n") fr.write("Displacement y R**2 = " + str(rsq[0][1]) + "\n") fr.write("Displacement z R**2 = " + str(rsq[0][2]) + "\n") fr.write("Stress R**2 = " + str(rsqs[0]) + "\n") fr.write("Strain R**2 = " + str(rsqs[1]) + "\n") fr.write("Displacement x Standard Error of Estimate = " + str(seoefd[0]) + "\n") fr.write("Displacement y Standard Error of Estimate = " + str(seoefd[1]) + "\n") fr.write("Displacement z Standard Error of Estimate = " + str(seoefd[2]) + "\n") fr.write("Stress Standard Error of Estimate = " + str(seoef[0]) + "\n") fr.write("Strain Standard Error of Estimate = " + str(seoef[1]) + "\n") fr.write("\n") fr.close() else: with open(filepathf, "a+", encoding="utf-8") as fr: fr.write("According to Starting point - " + str(bb) + " the results are: \n") fr.write("The optimal %s coefficients are: \n" % ty) fr.write("\n") if len(orig_coef) == 3: fr.write("C10 = " + str(xf[bb, 0]) + "\nC01 = " + str(xf[bb, 1]) + "\nC20 = " + str(xf[bb, 2])) else: # web for unicodes for greek letter = https://pythonforundergradengineers.com/unicode-characters-in-python.html fr.write('\u03BC1 = ' + str(xf[bb, 0]) + "\n\u03BC2 = " + str(xf[bb, 1]) + "\n\u03BC3 = " + str(xf[bb, 2]) + '\n\u03B11 = ' + str(xf[bb, 3]) + "\n\u03B12 = " + str(xf[bb, 4]) + "\n\u03B13 = " + str(xf[bb, 5])) fr.write("\n") fr.write( "\nPercentage accuracy towards original model's coefficients: \n" ) fr.write("\n") if len(orig_coef) == 6: fr.write("\u03BC1 = " + str(per_acc[bb, 0]) + "\n\u03BC2 = " + str(per_acc[bb, 1]) + "\n\u03BC3 = " + str(per_acc[bb, 2]) + "\n\u03B11 = " + str(per_acc[bb, 3]) + "\n\u03B12 = " + str(per_acc[bb, 4]) + "\n\u03B13 = " + str(per_acc[bb, 5])) if len(orig_coef) == 3: fr.write("C10 = " + str(per_acc[bb, 0]) + "\nC01 = " + str(per_acc[bb, 1]) + "\nC20 = " + str(per_acc[bb, 2])) fr.write("\n") fr.write("\nIt produced the following errors: \n") fr.write("\n") fr.write("Displacement RMS = " + str(rmsd[0]) + "\n") fr.write("Stress RMS = " + str(rmsr[0]) + "\n") fr.write("Strain RMS = " + str(rmsr[1]) + "\n") fr.write("Displacement x R**2 = " + str(rsq[0][0]) + "\n") fr.write("Displacement y R**2 = " + str(rsq[0][1]) + "\n") fr.write("Displacement z R**2 = " + str(rsq[0][2]) + "\n") fr.write("Stress R**2 = " + str(rsqs[0]) + "\n") fr.write("Strain R**2 = " + str(rsqs[1]) + "\n") fr.write("Displacement x Standard Error of Estimate = " + str(seoefd[0]) + "\n") fr.write("Displacement y Standard Error of Estimate = " + str(seoefd[1]) + "\n") fr.write("Displacement z Standard Error of Estimate = " + str(seoefd[2]) + "\n") fr.write("Stress Standard Error of Estimate = " + str(seoef[0]) + "\n") fr.write("Strain Standard Error of Estimate = " + str(seoef[1]) + "\n") fr.write("\n") fr.close() # // # // the final simulation increment is used for the displacement data, this is to obtain the final results # at full deformation inc = incn - 1 x_new = expdata[inc, :, 0] y_new = expdata[inc, :, 1] dx_new = expdata[inc, :, 3] dy_new = expdata[inc, :, 4] z_new = expdata[inc, :, 2] dz_new = expdata[inc, :, 5] x_rbf = RBFdata[inc, :, 0] y_rbf = RBFdata[inc, :, 1] z_rbf = RBFdata[inc, :, 2] orgx = expdata[0, :, 0] orgy = expdata[0, :, 1] px = orgx + x_rbf py = orgy + y_rbf # // # // The eng stress and stretch is determined for the increment x_strain_exp = np.linspace(0.4, 3.0, 50) y_stress_exp = 2 * orig_coef[0] * ( x_strain_exp - (1 / (x_strain_exp**2))) + 4 * orig_coef[2] * ( (x_strain_exp**2) + (2 / x_strain_exp) - 3) * (x_strain_exp - (1 / (x_strain_exp**2))) + 2 * orig_coef[1] * ( 1 - (1 / (x_strain_exp**3))) y_stress_fem = 2 * xf[bb, 0] * ( x_strain_exp - (1 / (x_strain_exp**2))) + 4 * xf[bb, 2] * ( (x_strain_exp**2) + (2 / x_strain_exp) - 3 ) * (x_strain_exp - (1 / (x_strain_exp**2))) + 2 * xf[bb, 1] * (1 - (1 / (x_strain_exp**3))) # // # // The error for the eng stress and stretch in the increment rsqid, alpd, betd = RSQ_disp(fvr, de, 1, inc) rms_f, rmsd_f = RMS_disp(de, fvr, 1, inc) seoedd = SEOE_disp(fvr, de, 1, inc) # // if bb == best: bb1 = bb bb = "best" else: bb = bb bb1 = bb # Line2D([0], [0], marker='o', color='b', label='FEM-data', markerfacecolor='w', markersize=3) # // The total error for the eng stress and stretch rmstot = RMS_stvssr(ste[:, :], fvrs[:, :]) rsqtot, alptot, bettot = RSQ_st(fvrs[:, :], ste[:, :]) seoetot = SEOE_str(fvrs[:, :], ste[:, :]) # // # // Figure 1 plots the Eng stress vs. stretch for the optimisation run plt.figure(fn, figsize=(11.0, 8.5)) plt.plot(expsr_e, expst_e, "r-") plt.plot(expsr_f, expst_f, "b-") yerr = np.std(y_stress_exp) / np.sqrt(len(y_stress_exp)) plt.plot(x_strain_exp, y_stress_exp, 'g-') plt.errorbar(x_strain_exp, y_stress_exp, yerr=yerr, fmt='none', ecolor='g', elinewidth=0.5, capsize=2, errorevery=2) plt.xlabel('Stretch', fontsize=18) plt.ylabel('Engineering Stress [MPa]', fontsize=18) plt.legend([ 'EXP Model Parameters', 'NUM Model Parameters', 'EXP Model Actual Stretch Range' ], fontsize=14) plt.text( 0.7 * max(expsr_e), max(expst_e) - 0.7 * (abs(max(expst_e) - min(expst_e))), "$R^2$ = %s, SEOE = %s\n RMS = %s" % (round(rsqtot[0], 4), round(seoetot[0], 4), round(rmstot[0], 4))) plt.grid("on") fig5 = "Figure1_%s.pdf" % bb figpath5 = os.path.join(path1, fig5) plt.savefig(figpath5, dpi=600) plt.close(fig=fn) fn += 1 # // Figure 2 plots the x, y and z displacement data to the coordinates plt.figure(fn, figsize=(15.0, 8.5)) plt.figure(fn).legend(handles=[ pll.Line2D([0], [0], marker='o', color='w', label='EXP Model Original Nodal Position', markerfacecolor='g', markersize=5), pll.Line2D([0], [0], marker='o', color='w', label='EXP Model Deformed Nodal Points', markerfacecolor='r', markersize=5), pll.Line2D([0], [0], marker='o', color='b', label='NUM Model Deformed Nodal Points', markerfacecolor='w', markersize=5) ], loc='center') plt.subplot(221) plt.plot(orgx, orgy, 'g.') plt.plot(x_new, y_new, 'r.') plt.plot(px, py, 'bo', fillstyle="none") plt.xlabel('X-Coordinate [mm]', fontsize=18) plt.ylabel('Y-Coordinate [mm]', fontsize=18) plt.grid("on") plt.subplot(222) plt.plot(x_new, dx_new, 'r.') plt.plot(x_new, x_rbf, 'bo', fillstyle="none") plt.xlabel('x [mm]', fontsize=18) plt.ylabel(r'$\Delta$x [mm]', fontsize=18) plt.grid("on") plt.subplot(223) plt.plot(y_new, dy_new, 'r.') plt.plot(y_new, y_rbf, 'bo', fillstyle="none") plt.xlabel('y [mm]', fontsize=18) plt.ylabel(r'$\Delta$y [mm]', fontsize=18) plt.grid("on") plt.subplot(224) plt.plot(z_new, dz_new, 'r.') plt.plot(z_new, z_rbf, 'bo', fillstyle="none") plt.xlabel('z [mm]', fontsize=18) plt.ylabel(r'$\Delta$z [mm]', fontsize=18) plt.grid("on") plt.subplots_adjust(left=0.08, right=0.94, bottom=0.08, top=0.90, wspace=0.2, hspace=0.55) fig6 = "Figure2_%s.pdf" % bb figpath6 = os.path.join(path1, fig6) plt.savefig(figpath6, dpi=600) plt.close(fig=fn) fn += 1 # // Figure 3 plots the x, y and z displacements for the "NUM" model vs. "EXP" model plt.figure(fn, figsize=(12.0, 8.5)) plt.subplot(221) xx = np.linspace(min(dx_new), max(dx_new), 100) yx = alpd[0] * xx + betd[0] plt.scatter(dx_new, x_rbf, s=15, c="b", alpha=0.5) plt.plot(xx, yx, 'r') plt.title("X-Displacement") plt.xlabel(r'EXP Model $\Delta$x [mm]', fontsize=18) plt.ylabel(r'NUM Model $\Delta$x [mm]', fontsize=18) plt.grid("on") plt.text( min(dx_new), max(x_rbf) - 0.2 * (abs(max(x_rbf) - min(x_rbf))), "$R^2$ = %s, SEOE = %s\n RMS = %s" % (round(rsqid[0], 4), round(seoedd[0], 4), round(rmsd_f[0], 4)), fontsize=14) plt.subplot(222) xy = np.linspace(min(dy_new), max(dy_new), 100) yy = alpd[1] * xy + betd[1] plt.plot(xy, yy, 'r') plt.scatter(dy_new, y_rbf, s=15, c="b", alpha=0.5) plt.title("Y-Displacement") plt.xlabel(r'EXP Model $\Delta$y [mm]', fontsize=18) plt.ylabel(r'NUM Model $\Delta$y [mm]', fontsize=18) plt.grid("on") plt.text( min(dy_new), max(y_rbf) - 0.2 * (abs(max(y_rbf) - min(y_rbf))), "$R^2$ = %s, SEOE = %s\n RMS = %s" % (round(rsqid[1], 4), round(seoedd[1], 4), round(rmsd_f[1], 4)), fontsize=14) plt.subplot(223) xz = np.linspace(min(dz_new), max(dz_new), 100) yz = alpd[2] * xz + betd[2] plt.plot(xz, yz, 'r') plt.scatter(dz_new, z_rbf, s=15, c="b", alpha=0.5) plt.title("Z-Displacement") plt.xlabel(r'EXP Model $\Delta$z [mm]', fontsize=18) plt.ylabel(r'NUM Model $\Delta$z [mm]', fontsize=18) plt.grid("on") plt.text( min(dz_new), max(z_rbf) - 0.2 * (abs(max(z_rbf) - min(z_rbf))), "$R^2$ = %s, SEOE = %s\n RMS = %s" % (round(rsqid[2], 4), round(seoedd[2], 4), round(rmsd_f[2], 4)), fontsize=14) plt.subplots_adjust(left=0.08, right=0.94, bottom=0.08, top=0.90, wspace=0.20, hspace=0.46) fig7 = "Figure3_%s.pdf" % bb figpath7 = os.path.join(path1, fig7) plt.savefig(figpath7, dpi=600) plt.close(fig=fn) fn += 1 print('hey') # ------------------------------------------------------------------------------------------------------------------ # ---- Unindent the next lines of code in case two optimisation algorithms are used. # ---- Only unindent bedore the 2nd optimisation algorithm run, NOT during the 1st one # objls = sorted(objl, reverse=True) # xs = np.linspace(1,len(objls),len(objls)) # objlsSP = sorted(objlSP, reverse=True) # xsSP = np.linspace(1,len(objlsSP),len(objlsSP)) # plt.figure(1, figsize=(12.0,8.5)) # plt.plot(xs,objls, "r*:") # plt.plot(xsSP,objlsSP, "bd:") # plt.xlabel('Optimisation Run',fontsize=18) # plt.ylabel('Optimisation Run Objective Function',fontsize=18) # plt.legend([algpat1,algpat2],fontsize=14) # plt.grid("on") # fig4 = "Figure4.pdf" # path3 = filepaths("path3") # figpath4 = os.path.join(path3,fig4) # plt.savefig(figpath4, dpi=600) # ------------------------------------------------------------------------------------------------------------------ return (best)
def myEvaluate(x, obj, g, param): # // # Since 10 deisgn points will be optimised, the optimser need to know which design point's # optimisation is currently running, the "iterations" file store the current design point's # number, zero indexed. # The current deisgn point's number only gets accessed here. file = open("iterations.txt", "r") it = int(file.readline()) file.close # // # // # A bias exits between the 3 design variables, therefore all of them gets scaled to a value # of 1 by dividing the starting design point by itself. This eliminates the bias within the # optimisation calculations. # For each optimisation iteration the design variables need to be multiplied again by the # starting point to ensure the procedure file written to MARC, runs the FE analysis with the # correct variables. # The next few lines obtaines the starting point to be multiplied with the current design variables. path1 = filepaths("path1") filen = "starting_points.txt" filp = os.path.join(path1, filen) start = open(filp, 'r') import ast xxx = ast.literal_eval(start.readlines()[it]) start.close() xxx = nm.array(xxx) xc = nm.array(x) print(xxx) print(xc) xa = xc * xxx print(xa) # // # // # Here the procedure file for MARC is created with the "material3d" function in the app.py file. # In case a Mooney-Rivlin two parameter model, the correct procedure file will be created. # This example is for the Mooney-Rivlin three parameter model time.sleep(1) if len(x) == 3: material3d(xa) #creates the procedure file for Marc elif len(x) == 2: material2d(xa) # // #// # With a pipeline this big and different files and function being imported, a fail safe is added # to sleep the code for a second to ensure it doesn't maybe skip a line or run to fast before # the data from the previous function has been obtained. # The subprocess function is used to run the MARC analysis in the background, therefore pausing # the code until MARC is closed. time.sleep(1) filem = "mat.proc" p = subprocess.Popen(["mentat.bat", filem], bufsize=2048) #start MARC and load the procedure file # which will open the correct FE model and change the material properties, start MARC solver and # to save the post file for the current DOT increment, close MARC and continue with the code below p.wait() time.sleep( 5 ) # the time delay allows Marc to create all output files, even after the program has closed, # it ensures that the code won't crash by loading all the output files too early # // # // # Define if MARC analysis converged by loading the NUMERICAL model's status file and reading which # EXIT CODE was obtained. # - 3004: Converged analysis # - Anything other than 3004, no convergence sts = filepaths("fem_sts") conver = pd.read_csv(sts, header=None, skipinitialspace=True, sep=' ', skiprows=4, keep_default_na=False) time.sleep(1) if len(conver) > 1: c = int(conver.iloc[-3, 6]) else: conver = pd.read_csv(sts, header=None, skipinitialspace=True, sep=' ', keep_default_na=False) c = int(conver.iloc[-3, 6]) # the boolean constraints are specified if c == 3004: g[0] = -1 # 3004 says the NUMERICAL model converged and the constraint is satisfied else: g[0] = 1 if len(x) == 3: xv = [xa[0], xa[1], xa[2]] elif len(x) == 2: xv = [xa[0], xa[1]] # Here the violated design variables are saved into a file. time.sleep(1) from functions import violated_constr violated_constr( xv, c ) # This function saves the parameters which caused non-convergence # and also what the exit number was print(g[0]) # // # // # List of all the output and input files needed to create the full data fields. # Here the RBF function is called. from RBF import RBF_int fname1, fname2, fname3, fname4, fnamef, fnamee = filepaths( "fem_out", "pointfem", "exp_out", "pointexp", "fem_dat", "exp_dat") ce, de, fci, fdi, fvr, nne, nnf, dm = RBF_int(fname1, fname2, fname3, fname4, fnamef, fnamee, g[0]) # calling the # RBF_int function from the RBF file, # - it fills the data of the NUMERICAL model to match that of the EXPERIMENTAL model time.sleep(1) from RMS import RMS_disp rms, rmsd = RMS_disp( de, fvr ) # The RMS function is loaded from the RMS file to determine the RMS value for convergence time.sleep(1) print("RMS value = ", rms) obj.value = rms #set the objection function of DOT to the RMS value
# sp[0,:] = [0.23985539715563783, 0.1086356159032091, 0.06752244405180519] # sp[1,:] = [0.22346941962260952, 0.08517834975399942, 0.04888277372798288] # sp[2,:] = [0.23680911902278512, 0.1008993817417827, 0.05522682051951559] # sp[3,:] = [0.2667989705559038, 0.09145828980269591, 0.047717784644901534] # sp[4,:] = [0.2780371475302363, 0.08052791834324839, 0.06226274627149697] # sp[5,:] = [0.21648774294463674, 0.10232477181284882, 0.0613617606707654] # sp[6,:] = [0.2846377298682449, 0.11539898192753328, 0.05897444807215557] # sp[7,:] = [0.2564777729233578, 0.11022702843829285, 0.05185050155523324] # sp[8,:] = [0.3009270768118156, 0.08863017446473127, 0.0659901485250131] # sp[9,:] = [0.3083142113950629, 0.09628959633853354, 0.05326192489971376] # cl = [0.208454096, 0.078039848, 0.046000552] # cu = [0.312681144, 0.117059772, 0.069000828] # ------------------------------------------------------------------------------------------------------------------ # // the next few lines of code creates a new folder containing the Results and set the path for the file as well path1 = filepaths("path1") access_rights = 0o777 if not os.path.exists(path1): os.mkdir(path1, access_rights) # // # // Next a new file is created in the new Results folder containing the list of starting points from LHC as well # as the limits for the starting points. # The correct path to the folder is created and given for the file filename = "starting_points.txt" filepath = os.path.join(path1, filename) st = open(filepath, "w") # the starting points file is written for sl in range(len(sp)): st.write("%s\n" % list(sp[sl])) lines_w = ["%s\n" % cl, "%s" % cu]