def traction_1d( ell=0.1, degree=1, n=3, E=1., load_min=0, load_max=2, loads=None, nsteps=20, Lx=1, outdir="outdir", postfix='', savelag=1, sigma_D0=1., continuation=False, checkstability=True, configString='', breakifunstable=False, ): # constants ell = ell Lx = Lx load_min = load_min load_max = load_max nsteps = nsteps outdir = outdir loads = loads savelag = 1 ell = dolfin.Constant(ell) E0 = dolfin.Constant(E) sigma_D0 = E0 n = n continuation = continuation config = json.loads(configString) if configString != '' else '' cmd_parameters = { 'material': { "ell": ell.values()[0], "E": E0.values()[0], "sigma_D0": sigma_D0.values()[0] }, 'geometry': { 'Lx': Lx, 'n': n, }, 'experiment': { 'signature': '', 'break-if-unstable': breakifunstable }, 'stability': { 'checkstability': checkstability, 'continuation': continuation }, 'time_stepping': { 'load_min': load_min, 'load_max': load_max, 'nsteps': nsteps, 'outdir': outdir, 'postfix': postfix, 'savelag': savelag }, 'alt_min': {}, "code": {} } if config: for par in config: parameters[par].update(config[par]) else: for par in parameters: parameters[par].update(cmd_parameters[par]) print(parameters) signature = hashlib.md5(str(parameters).encode('utf-8')).hexdigest() outdir += '-{}{}'.format(signature, cmd_parameters['time_stepping']['postfix']) # outdir += '-{}'.format(cmd_parameters['time_stepping']['postfix']) parameters['time_stepping']['outdir'] = outdir Path(outdir).mkdir(parents=True, exist_ok=True) print('Outdir is: ' + outdir) with open(os.path.join(outdir, 'rerun.sh'), 'w') as f: configuration = deepcopy(parameters) configuration['time_stepping'].pop('outdir') str(configuration).replace("\'True\'", "True").replace("\'False\'", "False") rerun_cmd = 'python3 {} --config="{}"'.format( os.path.basename(__file__), configuration) f.write(rerun_cmd) with open(os.path.join(outdir, 'parameters.pkl'), 'w') as f: json.dump(parameters, f) with open(os.path.join(outdir, 'signature.md5'), 'w') as f: f.write(signature) print('experiment = {}'.format( os.path.join('~/Documents/WIP/paper_stability_code', outdir))) mesh = dolfin.IntervalMesh(int(float(n * Lx / ell)), -Lx / 2., Lx / 2.) meshf = dolfin.File(os.path.join(outdir, "mesh.xml")) meshf << mesh left = dolfin.CompiledSubDomain("near(x[0], -Lx/2.)", Lx=Lx) right = dolfin.CompiledSubDomain("near(x[0], Lx/2.)", Lx=Lx) mf = dolfin.MeshFunction("size_t", mesh, 1, 0) right.mark(mf, 1) left.mark(mf, 2) # bottom.mark(mf, 3) ds = dolfin.Measure("ds", subdomain_data=mf) dx = dolfin.Measure("dx", metadata=form_compiler_parameters, domain=mesh) # Function Spaces V_u = dolfin.FunctionSpace(mesh, "CG", 1) V_alpha = dolfin.FunctionSpace(mesh, "CG", 1) u = dolfin.Function(V_u, name="Total displacement") alpha = dolfin.Function(V_alpha, name="Damage") state = [u, alpha] Z = dolfin.FunctionSpace( mesh, dolfin.MixedElement([u.ufl_element(), alpha.ufl_element()])) z = dolfin.Function(Z) v, beta = dolfin.split(z) # BCs (homogenous version needed for residual evaluation) ut = dolfin.Expression("t", t=0.0, degree=0) bcs_u = [ dolfin.DirichletBC(V_u, dolfin.Constant(0), left), dolfin.DirichletBC(V_u, ut, right) ] bcs_alpha = [] # bcs_alpha = [dolfin.DirichletBC(V_alpha, dolfin.Constant(1.), right)] # Files for output ColorPrint.print_warn('Outdir = {}'.format(outdir)) file_out = dolfin.XDMFFile(os.path.join(outdir, "output.xdmf")) file_out.parameters["functions_share_mesh"] = True file_out.parameters["flush_output"] = True file_con = dolfin.XDMFFile(os.path.join(outdir, "cont.xdmf")) file_con.parameters["functions_share_mesh"] = True file_con.parameters["flush_output"] = True file_eig = dolfin.XDMFFile(os.path.join(outdir, "modes.xdmf")) file_eig.parameters["functions_share_mesh"] = True file_eig.parameters["flush_output"] = True # Problem definition # model = DamageElasticityModel1D(state, E0, ell, sigma_D0) # k_ell = 1e-8 a = (1 - alpha)**2. + k_ell w_1 = parameters['material']['sigma_D0']**2 / parameters['material']['E'] w = w_1 * alpha eps = u.dx(0) # sigma = parameters['material']['E']*eps # energy = 1./2.* parameters['material']['E']*a*eps**2. * dx + (w + w_1 * parameters['material']['ell'] ** 2. * alpha.dx(0)**2.)*dx # # Rayleigh Ratio # rP = (dolfin.sqrt(a)*sigma + dolfin.diff(a, alpha)/dolfin.sqrt(a)*sigma*beta)*(dolfin.sqrt(a)*v.dx(0) + dolfin.diff(a, alpha)/dolfin.sqrt(a)*eps*beta)*dx + \ # 2*w_1*parameters['material']['ell'] ** 2 * beta.dx(0)**2*dx # da = dolfin.diff(a, alpha) # dda = dolfin.diff(dolfin.diff(a, alpha), alpha) # ddw = dolfin.diff(dolfin.diff(w, alpha), alpha) # rN = -(1./2.*(dda - da**2./a)*sigma*eps +1./2.*ddw)*beta**2.*dx # import pdb; pdb.set_trace() # ------------------------------ model = DamageElasticityModel1D(state, E0, ell, sigma_D0) model.dx = dx # energy = model.total_energy_density(u, alpha)*model.dx energy = 1. / 2. * parameters['material']['E'] * a * eps**2. * dx + ( w + w_1 * parameters['material']['ell']**2. * alpha.dx(0)**2.) * dx rP = model.rP(u, alpha, v, beta) * model.dx rN = model.rN(u, alpha, beta) * model.dx # Alternate minimisation solver # import pdb; pdb.set_trace() solver = solvers.AlternateMinimizationSolver( energy, [u, alpha], [bcs_u, bcs_alpha], parameters=parameters['alt_min']) stability = StabilitySolver(mesh, energy, [u, alpha], [bcs_u, bcs_alpha], z, rayleigh=[rP, rN], parameters=parameters['stability']) # stability = StabilitySolver(mesh, energy, [u, alpha], [bcs_u, bcs_alpha], z, parameters = parameters['stability']) # Time iterations load_steps = np.linspace(load_min, load_max, parameters['time_stepping']['nsteps']) # load_steps = np.logspace(np.log10(load_min), np.log10(load_max), parameters['time_stepping']['nsteps']) if loads: load_steps = loads stability.parameters['checkstability'] = True time_data = [] linesearch = LineSearch(energy, [u, alpha]) alpha_old = dolfin.Function(alpha.function_space()) lmbda_min_prev = 0.000001 bifurcated = False bifurcation_loads = [] save_current_bifurcation = False bifurc_i = 0 alpha_bif = dolfin.Function(V_alpha) alpha_bif_old = dolfin.Function(V_alpha) lmbda_min_prev = 0.000001 bifurcated = False bifurcation_loads = [] time_data_pd = [] for it, load in enumerate(load_steps): # import pdb; pdb.set_trace() ut.t = load alpha_old.assign(alpha) ColorPrint.print_warn('Solving load t = {:.2f}'.format(load)) # First order stability conditions (time_data_i, am_iter) = solver.solve() # import pdb; pdb.set_trace() # Second order stability conditions (stable, negev) = stability.solve(solver.problem_alpha.lb) ColorPrint.print_pass( 'Current state is{}stable'.format(' ' if stable else ' un')) solver.update() # mineig = stability.mineig if hasattr(stability, 'mineig') else 0.0 print('lmbda min', lmbda_min_prev) print('mineig', mineig) Deltav = (mineig - lmbda_min_prev) if hasattr(stability, 'eigs') else 0 if (mineig + Deltav) * (lmbda_min_prev + dolfin.DOLFIN_EPS) < 0 and not bifurcated: bifurcated = True # save 3 bif modes print('About to bifurcate load ', load, 'step', it) bifurcation_loads.append(load) modes = np.where(stability.eigs < 0)[0] with dolfin.XDMFFile(os.path.join(outdir, "postproc.xdmf")) as file: leneigs = len(modes) maxmodes = min(3, leneigs) for n in range(maxmodes): mode = dolfin.project(stability.linsearch[n]['beta_n'], V_alpha) modename = 'beta-%d' % n print(modename) file.write_checkpoint(mode, modename, 0, append=True) bifurc_i += 1 lmbda_min_prev = mineig if hasattr(stability, 'mineig') else 0. # stable == True time_data_i["load"] = load time_data_i["stable"] = stable time_data_i["elastic_energy"] = dolfin.assemble( 1. / 2. * parameters['material']['E'] * a * eps**2. * dx) time_data_i["dissipated_energy"] = dolfin.assemble( (w + w_1 * parameters['material']['ell']**2. * alpha.dx(0)**2.) * dx) time_data_i["elastic_energy"] = dolfin.assemble( model.elastic_energy_density(u.dx(0), alpha) * dx) time_data_i["dissipated_energy"] = dolfin.assemble( model.damage_dissipation_density(alpha) * dx) time_data_i["eigs"] = stability.eigs if hasattr(stability, 'eigs') else np.inf time_data_i["stable"] = stability.stable time_data_i["# neg ev"] = stability.negev # import pdb; pdb.set_trace() # time_data_i["S(alpha)"] = dolfin.assemble(1./(a)*dx) # time_data_i["a(alpha)"] = dolfin.assemble(a*dx) # time_data_i["avg_alpha"] = dolfin.assemble(alpha*dx) ColorPrint.print_pass( "Time step {:.4g}: it {:3d}, err_alpha={:.4g}".format( time_data_i["load"], time_data_i["iterations"], time_data_i["alpha_error"])) time_data.append(time_data_i) time_data_pd = pd.DataFrame(time_data) if np.mod(it, savelag) == 0: with file_out as f: f.write(alpha, load) f.write(u, load) with dolfin.XDMFFile(os.path.join(outdir, "output_postproc.xdmf")) as f: f.write_checkpoint(alpha, "alpha-{}".format(it), 0, append=True) print('DEBUG: written step ', it) time_data_pd.to_json(os.path.join(outdir, "time_data.json")) # if size == 1: # plt.figure() # dolfin.plot(alpha, marker='o') # plt.savefig(os.path.join(outdir, "alpha-{}.png".format(it))) # plt.figure() # dolfin.plot(u, marker='o') # plt.savefig(os.path.join(outdir, "u-{}.png".format(it))) # plt.clf() if not stable and parameters['experiment']['break-if-unstable']: print('Unstable state, breaking', parameters['experiment']['break-if-unstable']) break # print(time_data_pd) print() # print(time_data_pd['stable']) print('Output in: ' + outdir) # # solve optimal profile # # Alternate minimisation solver # beta = dolfin.TestFunction(V_alpha) # dalpha = dolfin.TrialFunction(V_alpha) # F = (ell*alpha.dx(0)*alpha.dx(0) + w/ell*alpha)*dx # dF = dolfin.derivative(F,alpha,beta); ddF = dolfin.derivative(dF,alpha,dalpha) # # bcs_u = [dolfin.DirichletBC(V_u, dolfin.Constant(0.), 'on_boundary')] alpha = dolfin.Function(V_alpha) u = dolfin.Function(V_u) bcs_alpha = [ dolfin.DirichletBC(V_alpha, dolfin.Constant(1.), right), dolfin.DirichletBC(V_alpha, dolfin.Constant(0.), left) ] solver = solvers.AlternateMinimizationSolver( energy, [u, alpha], [[], bcs_alpha], parameters=parameters['alt_min']) solver.solve() print('DEBUG: h1 norm alpha profile {}'.format(dolfin.norm(alpha, 'h1'))) # ub = dolfin.interpolate(dolfin.Constant(1.), V_alpha); lb = dolfin.interpolate(dolfin.Constant(0.), V_alpha) # profile = dolfin.NonlinearVariationalProblem(dF, alpha, bcs_alpha, J = ddF) # profile.set_bounds(lb, ub) # solver_nl = dolfin.NonlinearVariationalSolver(profile) # snes_solver_parameters_bounds = {"nonlinear_solver": "snes", # "snes_solver": {"linear_solver": "cg", # "maximum_iterations": 100, # "report": True, # "line_search": "basic", # "method":"vinewtonrsls", # "absolute_tolerance":1e-6, # "relative_tolerance":1e-6, # "solution_tolerance":1e-6}} # solver_nl.parameters.update(snes_solver_parameters_bounds) # solver_nl.solve() xs = np.linspace(-Lx / 2., Lx / 2., 100) profile = np.array([alpha(x) for x in xs]) plt.figure() plt.plot(xs, profile, marker='o') # plt.plot(xs, np.array([u(x) for x in xs])) plt.savefig(os.path.join(outdir, 'profile.pdf')) # import pdb; pdb.set_trace() return time_data_pd, outdir
def test_5_1D_poisson_solver(self): """Test a Poisson solve in 1D radial spherical coordinates starting at r = 0. The mesh and mesh BC markers used here read from files written by test_1D_spherical_mesh in test_UserMesh.py. The charge-density is from a file written by test_6_compute_charge_density_on_1Dmesh() in test_ChargeDensity.py. The potential is set to zero at the outer radius at 5 meters. At the inner radius (0) no value is set, and so the slope is zero. See Calc file test_FieldSolve.ods:test_5 for calculation of potential """ fncName = '(' + __file__ + ') ' + sys._getframe( ).f_code.co_name + '():\n' print('\ntest: ', fncName) ### Specialized mesh and field-solver modules for this test ### from UserMesh_y_Fields_Spherical1D_Module import UserMesh1DS_C from UserMesh_y_Fields_Spherical1D_Module import UserMeshInput1DS_C from UserMesh_y_Fields_Spherical1D_Module import UserPoissonSolve1DS_C ### Read the mesh and boundary-condition markers ### # Create a mesh object and read in the mesh. coordinateSystem = '1D-spherical-radial' mesh1d_M = Mesh_C( mesh_file='mesh_1D_radial_r0.xml', coordinate_system=coordinateSystem, field_boundary_marker_file='mesh_1D_radial_r0_Fbcs.xml', compute_dictionaries=True, compute_cpp_arrays=False, compute_tree=True, plot_flag=self.plot_mesh) ### Create the charge-density vector ### chargeDensityElementType = 'Lagrange' chargeDensityElementDegree = 1 chargeDensityFieldType = 'scalar' chargeDensity_F = Field_C(mesh_M=mesh1d_M, element_type=chargeDensityElementType, element_degree=chargeDensityElementDegree, field_type=chargeDensityFieldType) ### Set the charge density values ### # Read in the charge-density written by # test_ChargeDensity.py:test_5_compute_charge_density_on_1Dmesh file = df_m.File("charge_1DS_r0.xml") file >> chargeDensity_F.function ### Set the Poisson solver parameters ### linearSolver = 'lu' preconditioner = None ### Set the field boundary conditions ### # Copy over from test_ChargeDensity.py:test_5 for convenience in using the # integer markers to set boundary values. # # This associates the field marker integers with boundary names. rminIndx = 1 rmaxIndx = 2 fieldBoundaryDict = { 'rmin': rminIndx, 'rmax': rmaxIndx, } # Dirichlet boundaries are applied using a mesh function that marks the outer # edges of the mesh. fieldBoundaryMarker = mesh1d_M.field_boundary_marker # Specify the boundary values of the potential phiVals = { 'rmin': 'unset', # Analytic potential inside the particle radius 'rmax': 0.0, } phiBCs = dict((bnd, [fieldBoundaryDict[bnd], phiVals[bnd]]) for bnd in list(fieldBoundaryDict.keys())) ### Create vectors for for the potential and electric field ### phiElementType = 'Lagrange' phiElementDegree = 1 phiFieldType = 'scalar' phi_F = Field_C(mesh_M=mesh1d_M, element_type=phiElementType, element_degree=phiElementDegree, field_type=phiFieldType) if phiElementDegree == 1: # For linear elements, grad(phi) is discontinuous across # elements. To get these values, we need Discontinuous Galerkin # elements. electricFieldElementType = "DG" else: electricFieldElementType = "Lagrange" negElectricField_F = Field_C(mesh_M=mesh1d_M, element_type=electricFieldElementType, element_degree=phiElementDegree - 1, field_type='vector') ### Create the Poisson-solver object ### potentialsolve = UserPoissonSolve1DS_C( phi_F, linearSolver, preconditioner, fieldBoundaryMarker, phiBCs, neg_electric_field=negElectricField_F) # Create the source term from a given density # (In this test, the charge comes from kinetic point particles, rather # than from a density function, so the following isn't needed.) # poissonsolve.assemble_source_expression(charge_density) # self.b = df_m.assemble(self.L) # Solve for the potential plotTitle = os.path.basename( __file__) + ": " + sys._getframe().f_code.co_name # poissonsolve.solve_for_phi(plot_flag=plotFlag, plot_title=plotTitle) spacechargeFactor = 1.0 potentialsolve.solve_for_phi(assembled_charge=chargeDensity_F, assembled_charge_factor=spacechargeFactor, plot_flag=self.plot_results, plot_title=plotTitle) # Write the potential to a file in VTK and XML formats file = df_m.File('phi_test_5_1D.pvd') # phi_name goes into the output file; phi_label doesn't phi_F.function.rename("phi1D", "phi_label") file << phi_F.function file = df_m.File('phi_test_5_1D.xml') file << phi_F.function # Write -E to a file in VTK and XML formats if negElectricField_F is not None: negElectricField_F.function.rename("E1D", "E_label") # !!! VTK cannot write a vector field on a 1D grid. # file = df_m.File("negE_test_5_1D.pvd") # file << negElectricField_F.function file = df_m.File("negE_test_5_1D.xml") file << negElectricField_F.function # Check that -E has the analytic value at r=1.842 # See test_FieldSolve.ods for values negE_arr = negElectricField_F.function.vector().get_local() # print("negE_arr =", negE_arr) negE_at_1_842 = 2649589637.58845 ratio = negE_at_1_842 / negE_arr[5] decimal_places = 2 self.assertAlmostEqual(ratio, 1.0, places=decimal_places, msg="negE is not correct") print("test_5: negE is correct to %d decimal places; ratio = %.5g" % (decimal_places, ratio)) return
# set up the optimizer prob.driver = driver = om.pyOptSparseDriver() driver.options['optimizer'] = 'SNOPT' driver.opt_settings['Verify level'] = 0 driver.opt_settings['Major iterations limit'] = 100000 driver.opt_settings['Minor iterations limit'] = 100000 driver.opt_settings['Iterations limit'] = 100000000 driver.opt_settings['Major step limit'] = 2.0 driver.opt_settings['Major feasibility tolerance'] = 1.0e-6 driver.opt_settings['Major optimality tolerance'] = 1.e-8 prob.setup() prob.run_model() # print(prob['compliance']); exit() prob.run_driver() #save the solution vector if method == 'SIMP': penalized_density = df.project(density_function**3, density_function_space) else: penalized_density = df.project( density_function / (1 + 8. * (1. - density_function)), density_function_space) df.File('solutions/case_1/cantilever_beam/displacement.pvd' ) << displacements_function df.File('solutions/case_1/cantilever_beam/penalized_density.pvd' ) << penalized_density
pointwise_var_exact = dl.Vector() Prior.init_vector(pointwise_var_exact, 0) tic() get_diagonal(Prior.Rsolver, pointwise_var_exact, solve_mode=True) toc("Exact Elapsed: %s s") print(pointwise_var - pointwise_var_exact).norm("linf") / (pointwise_var_exact).norm("linf") print(pointwise_var_2 - pointwise_var_exact).norm("linf") / (pointwise_var_exact).norm("linf") dl.plot(vector2Function(pointwise_var_exact - pointwise_var, Vh)) dl.plot(vector2Function(pointwise_var_exact - pointwise_var_2, Vh)) dl.interactive() dl.File("marginal_variance.pvd") << vector2Function(pointwise_var, Vh, name="pointwise_variance") << \ vector2Function(pointwise_var_2, Vh, name="pointwise_variance") << vector2Function(pointwise_var_exact, Vh, name="pointwise_variance") exit() class RinvM: def mult(self, x, y): Prior.Rsolver.solve(y, Prior.M * x) def init_vector(self, x, dim): Prior.init_vector(x, dim) class MRinv: def mult(self, x, y):
def test_3_1D_poisson_solver(self): """Test a 1D Poisson equation in cartesian coordinates. Note: the mesh, mesh BC markers, and the charge-density are read from external files written by test_4_compute_charge_density_on_1Dmesh() in test_ChargeDensity.py. Boundary values are specified here. See Calc file test_FieldSolve.ods for calculation of electric field. """ fncName = '(' + __file__ + ') ' + sys._getframe( ).f_code.co_name + '():\n' print('\ntest: ', fncName) ### Specialized mesh and field-solver modules for this test ### from UserMesh_y_Fields_FE_XYZ_Module import UserMesh_C from UserMesh_y_Fields_FE_XYZ_Module import UserMeshInput_C from UserMesh_y_Fields_FE_XYZ_Module import UserPoissonSolve1D_C ### Read the mesh and boundary-condition markers ### # Create the mesh object and read in the mesh and boundary markers coordinateSystem = 'Cartesian' mesh1d_M = Mesh_C(mesh_file='mesh_2cell_1D.xml', coordinate_system=coordinateSystem, field_boundary_marker_file='mesh_2cell_1D_Fbcs.xml', compute_dictionaries=True, compute_cpp_arrays=False, compute_tree=True, plot_flag=self.plot_mesh) ### Create the charge-density vector ### # Copy over from test_ChargeDensity.py:test_4 # This associates the field marker integers with boundaries. # IS THIS NEEDED? xminIndx = 1 xmaxIndx = 2 fieldBoundaryDict = { 'xmin': xminIndx, 'xmax': xmaxIndx, } chargeDensityElementType = 'Lagrange' chargeDensityElementDegree = 1 chargeDensityFieldType = 'scalar' chargeDensity_F = Field_C(mesh_M=mesh1d_M, element_type=chargeDensityElementType, element_degree=chargeDensityElementDegree, field_type=chargeDensityFieldType) ### Set the charge density values ### # Read in the charge-density written by # test_ChargeDensity.py:test_4_compute_charge_density_on_1Dmesh file = df_m.File("charge_1D.xml") file >> chargeDensity_F.function ### Set the Poisson solver parameters ### linearSolver = 'lu' preconditioner = None ### Set the field boundary conditions ### # Dirichlet boundaries are applied using a mesh function that marks the outer # edges of the mesh. fieldBoundaryMarker = mesh1d_M.field_boundary_marker # Specify the boundary values of the potential phiVals = { 'xmin': -2.0, 'xmax': 1.0, } phiBCs = dict((bnd, [fieldBoundaryDict[bnd], phiVals[bnd]]) for bnd in list(fieldBoundaryDict.keys())) ### Create vectors for for the potential and electric field ### phiElementType = 'Lagrange' phiElementDegree = 1 phiFieldType = 'scalar' phi_F = Field_C(mesh_M=mesh1d_M, element_type=phiElementType, element_degree=phiElementDegree, field_type=phiFieldType) if phiElementDegree == 1: # For linear elements, grad(phi) is discontinuous across # elements. To get these values, we need Discontinuous Galerkin # elements. electricFieldElementType = "DG" else: electricFieldElementType = "Lagrange" negElectricField_F = Field_C(mesh_M=mesh1d_M, element_type=electricFieldElementType, element_degree=phiElementDegree - 1, field_type='vector') ### Create the Poisson-solver object ### poissonsolve = UserPoissonSolve1D_C( phi_F, linearSolver, preconditioner, fieldBoundaryMarker, phiBCs, neg_electric_field=negElectricField_F) # Create the source term from a given density # (In this test, the charge comes from kinetic point particles, rather # than from a density function, so the following isn't needed.) # poissonsolve.assemble_source_expression(charge_density) # self.b = df_m.assemble(self.L) # Solve for the potential plotTitle = os.path.basename( __file__) + ": " + sys._getframe().f_code.co_name poissonsolve.solve_for_phi(plot_flag=self.plot_results, plot_title=plotTitle) return
def testit(problem=None, nu=None, ininu=None, charvel=None, meshlvl=1, rho=1., ParaviewOutput=False, scheme='TH'): meshfile = 'mesh/karman2D-rotcyl_lvl{0}.xml.gz'.format(meshlvl) physregs = 'mesh/karman2D-rotcyl_lvl{0}_facet_region.xml.gz'.\ format(meshlvl) meshparams = dict(strtomeshfile=meshfile, strtophysicalregions=physregs, strtobcsobs=geodata) femp, stokesmatsc, rhsd = \ dnsps.get_sysmats(problem=problem, nu=nu, bccontrol=False, charvel=charvel, scheme=scheme, mergerhs=True, meshparams=meshparams) soldict = {} soldict.update(stokesmatsc) # containing A, J, JT soldict.update(femp) # adding V, Q, invinds, diribcs ddir = 'data/' data_prfx = problem + '{2}_mesh{0}_Re{1}'.\ format(meshlvl, femp['Re'], scheme) soldict.update(fv=rhsd['fv'], fp=rhsd['fp'], N=meshlvl, nu=nu, verbose=True, vel_pcrd_stps=0, vel_nwtn_tol=1e-10, vel_nwtn_stps=10, return_vp=True, get_datastring=None, dbcinds=femp['dbcinds'], dbcvals=femp['dbcvals'], data_prfx=ddir + data_prfx, paraviewoutput=ParaviewOutput, vfileprfx=proutdir + 'vel_', pfileprfx=proutdir + 'p_') L = femp['charlen'] # characteristic length phionevec = np.zeros((femp['V'].dim(), 1)) phionevec[femp['mvwbcinds'], :] = 1. phione = dolfin.Function(femp['V']) phione.vector().set_local(phionevec) pickx = dolfin.as_matrix([[1., 0.], [0., 0.]]) picky = dolfin.as_matrix([[0., 0.], [0., 1.]]) pox = pickx * phione poy = picky * phione phitwovec = np.zeros((femp['V'].dim(), 1)) phitwovec[femp['mvwbcinds'], 0] = femp['mvwbcvals'] phitwo = dolfin.Function(femp['V']) phitwo.vector().set_local(phitwovec) if ParaviewOutput: phifile = dolfin.File('results/phione.pvd') phifile << phitwo # getld = dnsps.LiftDragSurfForce(V=femp['V'], nu=nu, # phione=phione, phitwo=phitwo, # outflowds=femp['outflowds'], # ldds=femp['liftdragds']) steady_state_res = \ get_steady_state_res(V=femp['V'], gradvsymmtrc=True, outflowds=femp['outflowds'], nu=nu) def comptorque(rotval, thingdict=None, returnitall=False): def rotcont(t, vel=None, p=None, memory={}): return rotval, memory rotcondict = {} dircntdict = dict(diricontbcinds=[femp['mvwbcinds']], diricontbcvals=[femp['mvwbcvals']], diricontfuncs=[rotcont], diricontfuncmems=[rotcondict]) soldict.update(dircntdict) soldict.update(dict(vel_start_nwtn=thingdict['vel_start_nwtn'])) if ininu is not None and thingdict['vel_start_nwtn'] is None: inifemp, inistokesmatsc, inirhsd = \ dnsps.get_sysmats(problem=problem, nu=ininu, bccontrol=False, charvel=charvel, scheme=scheme, mergerhs=True, meshparams=meshparams) soldict.update(inistokesmatsc) soldict.update(inifemp) soldict.update(fv=inirhsd['fv'], fp=inirhsd['fp']) vp_ss_nse = snu.solve_steadystate_nse(**soldict) soldict.update(dict(vel_start_nwtn=vp_ss_nse[0])) soldict.update(stokesmatsc) soldict.update(femp) soldict.update(fv=rhsd['fv'], fp=rhsd['fp']) vp_ss_nse = snu.solve_steadystate_nse(**soldict) thingdict.update(dict(vel_start_nwtn=vp_ss_nse[0])) if returnitall: vfun, pfun = dts.\ expand_vp_dolfunc(vc=vp_ss_nse[0], pc=vp_ss_nse[1], V=femp['V'], Q=femp['Q']) # lift, drag = getld.evaliftdragforce(u=vfun, p=pfun) drag = steady_state_res(vfun, pfun, phi=pox) lift = steady_state_res(vfun, pfun, phi=poy) # phionex = phione.sub(0) trqe = steady_state_res(vfun, pfun, phi=phitwo) # trqe = getld.evatorqueSphere2D(u=vfun, p=pfun) a_1 = dolfin.Point(0.15, 0.2) a_2 = dolfin.Point(0.25, 0.2) pdiff = rho * pfun(a_2) - rho * pfun(a_1) return trqe, lift, drag, pdiff else: vfun, pfun = dts.\ expand_vp_dolfunc(vc=vp_ss_nse[0], pc=vp_ss_nse[1], V=femp['V'], Q=femp['Q']) # trqe = getld.evatorqueSphere2D(u=vfun, p=pfun) trqe = steady_state_res(vfun, pfun, phi=phitwo) print('omeg: {0:.3e} -- trqe: {1:.3e}'.format(rotval, trqe)) return np.abs(trqe) Um = charvel thingdict = dict(vel_start_nwtn=None) testrot = 0. trqe, lift, drag, pdif = comptorque(testrot, thingdict, returnitall=True) print('\n\n# ## Nonrotating Cylinder ') cdclfac = 2. / (rho * L * Um**2) trqefac = 4 / (Um**2 * rho * L**2) print('Cl: {0:.9f}'.format(cdclfac * lift)) print('Cd: {0:.9f}'.format(cdclfac * drag)) print('Ct: {0:.5e}'.format(trqefac * trqe)) print('Delta P: {0:.9f}'.format(pdif)) if charvel == 0.2: print('\n cp. values from Schaefer/Turek as in') print('www.featflow.de/en/benchmarks/cfdbenchmarking/flow/' + 'dfg_benchmark1_re20.html:') print('Cl: {0:.8f}'.format(0.010618948146)) print('Cd: {0:.8f}'.format(5.57953523384)) print('Delta P: {0:.8f}'.format(0.11752016697)) print('\n\n# ## Rotating Cylinder -- optimizing rotation for zero torque') tinfo = {} with dou.Timer(timerinfo=tinfo): res = sco.minimize_scalar(comptorque, args=(thingdict), options={'maxiter': 80}, tol=1e-13) trqe, lift, drag, pdiff = comptorque(res['x'], thingdict, returnitall=True) print('\n# ## Rotating Cylinder -- optimized rotation for zero torque') print('omega*: {0:.8f}'.format(res['x'] * L / (2 * Um))) print('Cl: {0:.8f}'.format(cdclfac * lift)) print('Cd: {0:.8f}'.format(cdclfac * drag)) print('Ct: {0:.4e}'.format(trqefac * trqe)) print('Delta P: {0:.8f}'.format(pdif)) if charvel == 0.2: print('\n cp. values from Richter et. al') print('omega*: {0}'.format(0.00126293)) print('Cl: {0}'.format(0.0047141)) print('Cd: {0}'.format(5.579558)) print('Delta P: {0}'.format(0.117520))
T_sol_d2[cou_ti] = do.Function(V2) T_sol_d3[cou_ti] = do.Function(V2) #nearest-neighbor interpolation NDI = NearestNDInterpolator(dofs_x1, val_ti.vector().array()) #ADD NOISE #delete 2nd line in 3D simulations T_sol_d2[cou_ti].vector()[:] = NDI(dofs_x2) + \ delta_ND * np.random.normal(mu_ND, sigma_ND, len(dofs_x2)) T_sol_d3[cou_ti].vector()[:] = NDI(dofs_x2) if cou_ti == 10: #CHECK NDI_DHCP = do.File(os.path.join(savings_dol1, 'T_NDI_DHCP.pvd')) NDI_IHCP = do.File(os.path.join(savings_dol1, 'T_NDI_IHCP.pvd')) NDI_DHCP << val_ti NDI_IHCP << T_sol_d2[cou_ti] while itera1 < max_itera2: # and exit_cri2 > whil_tol2: #primal problem #heat flux at S_in = g1 T_step_d2 = nablaT_fun( V2, v2, hol_cyl2, A2, boundary_faces2, mark_in2,
field.setNumber(fid, 'XMax', 0 + geometry_parameters['X']) field.setNumber(fid, 'YMin', y) field.setNumber(fid, 'YMax', y + w) field.setNumber(fid, 'VIn', Vin) field.setNumber(fid, 'VOut', Vout) boxes.append(fid) fid += 1 # Combine field.add('Min', fid) field.setNumbers(fid, 'FieldsList', boxes) field.setAsBackgroundMesh(fid) model.occ.synchronize() # gmsh.fltk.initialize() # gmsh.fltk.run() h5_filename = './test/two_solid_domain.h5' mesh_model2d(model, tags, h5_filename) mesh, markers, lookup = load_mesh2d(h5_filename) cell_f, facet_f = markers check_markers(cell_f, facet_f, lookup, geometry_parameters) gmsh.finalize() df.File('./test/two_solid_cells.pvd') << cell_f df.File('./test/two_solid_facets.pvd') << facet_f
field.setNumber(fid, 'YMin', ymin) field.setNumber(fid, 'YMax', ymax) field.setNumber(fid, 'VIn', Vin) field.setNumber(fid, 'VOut', Vout) field.setNumber(fid, 'Thickness', t) boxes.append(fid) fid += 1 # Combine field.add('Min', fid) field.setNumbers(fid, 'FieldsList', boxes) field.setAsBackgroundMesh(fid) model.occ.synchronize() # gmsh.fltk.initialize() # gmsh.fltk.run() h5_filename = './test/fbb_domain.h5' mesh_model2d(model, tags, h5_filename) mesh, markers, lookup = load_mesh2d(h5_filename) cell_f, facet_f = markers check_markers(cell_f, facet_f, lookup, geometry_parameters) gmsh.finalize() df.File('./test/fbb_cells.pvd') << cell_f df.File('./test/fbb_facets.pvd') << facet_f
def generate_initial_condition(mesh, county_geom, total_pop, infected_cases, recovered_cases, deceased_cases, infected_total_state, deceased_state, save_path='./', transmit_rate=1.16, date=None, FE_polynomial=1, save_numpy=True, save_vtu=True): # Define function space and all functions Vu = dl.FunctionSpace(mesh, "Lagrange", FE_polynomial) u = [dl.Function(Vu) for i in range(5)] # Determine the day index based on the given date if date is None: day_index = 0 else: validate_date(date) d0 = datetime.strptime("2020-03-06", "%Y-%m-%d") d1 = datetime.strptime(date, "%Y-%m-%d") day_index = abs((d1 - d0)).days # Determine the infected and deseased data on the given date infected_pop = infected_cases[day_index, :] deceased_pop = deceased_cases[day_index, :] recovered_pop = recovered_cases[day_index, :] active_infected_pop = infected_pop - deceased_pop - recovered_pop susceptible_pop = total_pop - transmit_rate * active_infected_pop - deceased_pop - recovered_pop - active_infected_pop # Interpolate initial conditions of the deceased/recovered/infected density based on the total cases deceased_pop_ic = seird_ic(county_geom, deceased_pop) u[DE] = dl.interpolate(deceased_pop_ic, Vu) recovered_pop_ic = seird_ic(county_geom, recovered_pop) u[RE] = dl.interpolate(recovered_pop_ic, Vu) active_infected_pop_ic = seird_ic(county_geom, active_infected_pop) u[IN] = dl.interpolate(active_infected_pop_ic, Vu) exposed_pop_ic = seird_ic(county_geom, transmit_rate * active_infected_pop) u[EX] = dl.interpolate(exposed_pop_ic, Vu) susceptible_pop_ic = seird_ic(county_geom, susceptible_pop) u[SU] = dl.interpolate(susceptible_pop_ic, Vu) r1 = deceased_state[day_index] / (10000 * dl.assemble(u[DE] * dl.dx)) print(r1) u[DE] = dl.project(r1 * u[DE], Vu) r2 = (infected_total_state[day_index] - deceased_state[day_index]) / (10000 * dl.assemble( (u[IN] + u[RE]) * dl.dx)) print(r2) u[IN] = dl.project(r2 * u[IN], Vu) u[RE] = dl.project(r2 * u[RE], Vu) names = ["susceptible", "exposed", "infected", "recovered", "deceased"] for i in range(5): print(names[i] + ": ", dl.assemble(10000 * u[i] * dl.dx)) if save_numpy: for i in range(5): np.save(save_path + names[i] + '_ic.npy', u[i].vector().get_local()) if save_vtu: for i in range(5): file = dl.File(save_path + names[i] + '_ic.pvd', "compressed") file << u[i]
elif df.near(x[1], 1.): assert np.linalg.norm(n(x) - np.array([0, 1, 0])) < 1E-10 elif df.near(x[2], 0): assert np.linalg.norm(n(x) - np.array([0, 0, -1])) < 1E-10 else: assert np.linalg.norm(n(x) - np.array([0, 0, 1])) < 1E-10 # EmbeddedMesh with cell_f mesh = df.BoxMesh(df.Point(*(-1, ) * 3), df.Point(*(1, ) * 3), 10, 10, 10) cell_f = df.MeshFunction('size_t', mesh, mesh.topology().dim(), 0) for cell in df.cells(mesh): x, y, z = cell.midpoint().array() if x > 0: cell_f[cell] = 1 if y > 0 else 2 else: cell_f[cell] = 3 if y > 0 else 4 df.File('t.pvd') << cell_f mesh = EmbeddedMesh(cell_f, (1, 3)) df.File('bar.pvd') << mesh df.File('foo.pvd') << mesh.marking_function for cell in df.SubsetIterator(mesh.marking_function, 1): x, y, z = cell.midpoint().array() assert x > 0 and y > 0 for cell in df.SubsetIterator(mesh.marking_function, 3): x, y, z = cell.midpoint().array() assert x < 0 and y > 0
plt.yscale('log') plt.show() compute_trace = True if compute_trace: post_tr, prior_tr, corr_tr = posterior.trace(method="Estimator", tol=1e-2, min_iter=20, max_iter=20) print( "Posterior trace {0:5e}; Prior trace {1:5e}; Correction trace {2:5e}".format(post_tr, prior_tr, corr_tr) ) post_pw_variance, pr_pw_variance, corr_pw_variance = posterior.pointwise_variance(method="Exact") objs = [dl.Function(Vh[PARAMETER], pr_pw_variance), dl.Function(Vh[PARAMETER], post_pw_variance)] mytitles = ["Prior variance", "Posterior variance"] nb.multi1_plot(objs, mytitles, logscale=False) plt.show() fid = dl.File("results/pointwise_variance.pvd") fid << dl.Function(Vh[PARAMETER], post_pw_variance, name="Posterior") fid << dl.Function(Vh[PARAMETER], pr_pw_variance, name="Prior") fid << dl.Function(Vh[PARAMETER], corr_pw_variance, name="Correction") #plt.figure() #plt.plot(range(0,k), d, 'ob') #plt.yscale('log') #plt.title("Spectrum of data misfit Hessian") print(sep, "Generate samples from Prior and Posterior\n","Export generalized Eigenpairs", sep) fid_prior = dl.File("samples/sample_prior.pvd") fid_post = dl.File("samples/sample_post.pvd") nsamples = 8 noise = dl.Vector() posterior.init_vector(noise,"noise")
def solve_nonlinear(self, inputs, outputs): pde_problem = self.options['pde_problem'] state_name = self.options['state_name'] problem_type = self.options['problem_type'] visualization = self.options['visualization'] state_function = pde_problem.states_dict[state_name]['function'] for argument_name, argument_function in iteritems( self.argument_functions_dict): density_func = argument_function mesh = state_function.function_space().mesh() sub_domains = df.MeshFunction('size_t', mesh, mesh.topology().dim() - 1) upper_edge = TractionBoundary() upper_edge.mark(sub_domains, 6) dss = df.Measure('ds')(subdomain_data=sub_domains) tractionBC = dss(6) self.itr = self.itr + 1 state_function = pde_problem.states_dict[state_name]['function'] residual_form = get_residual_form( state_function, df.TestFunction(state_function.function_space()), density_func, density_func.function_space(), tractionBC, # df.Constant((0.0, -9.e-1)) df.Constant((0.0, -9.e-1)), int(self.itr)) self._set_values(inputs, outputs) self.derivative_form = df.derivative(residual_form, state_function) df.set_log_level(df.LogLevel.ERROR) df.set_log_active(True) # df.solve(residual_form==0, state_function, bcs=pde_problem.bcs_list, J=self.derivative_form) if problem_type == 'linear_problem': df.solve(residual_form == 0, state_function, bcs=pde_problem.bcs_list, J=self.derivative_form, solver_parameters={ "newton_solver": { "maximum_iterations": 60, "error_on_nonconvergence": False } }) elif problem_type == 'nonlinear_problem': problem = df.NonlinearVariationalProblem(residual_form, state_function, pde_problem.bcs_list, self.derivative_form) solver = df.NonlinearVariationalSolver(problem) solver.parameters['nonlinear_solver'] = 'snes' solver.parameters["snes_solver"]["line_search"] = 'bt' solver.parameters["snes_solver"][ "linear_solver"] = 'mumps' # "cg" "gmres" solver.parameters["snes_solver"]["maximum_iterations"] = 500 solver.parameters["snes_solver"]["relative_tolerance"] = 5e-13 solver.parameters["snes_solver"]["absolute_tolerance"] = 5e-13 # solver.parameters["snes_solver"]["linear_solver_"]["maximum_iterations"]=1000 solver.parameters["snes_solver"]["error_on_nonconvergence"] = False solver.solve() elif problem_type == 'nonlinear_problem_load_stepping': num_steps = 3 state_function.vector().set_local( np.zeros((state_function.function_space().dim()))) for i in range(num_steps): v = df.TestFunction(state_function.function_space()) if i < (num_steps - 1): residual_form = get_residual_form( state_function, v, density_func, density_func.function_space(), tractionBC, # df.Constant((0.0, -9.e-1)) df.Constant((0.0, -9.e-1 / num_steps * (i + 1))), int(self.itr)) else: residual_form = get_residual_form( state_function, v, density_func, density_func.function_space(), tractionBC, # df.Constant((0.0, -9.e-1)) df.Constant((0.0, -9.e-1 / num_steps * (i + 1))), int(self.itr)) problem = df.NonlinearVariationalProblem( residual_form, state_function, pde_problem.bcs_list, self.derivative_form) solver = df.NonlinearVariationalSolver(problem) solver.parameters['nonlinear_solver'] = 'snes' solver.parameters["snes_solver"]["line_search"] = 'bt' solver.parameters["snes_solver"][ "linear_solver"] = 'mumps' # "cg" "gmres" solver.parameters["snes_solver"]["maximum_iterations"] = 500 solver.parameters["snes_solver"]["relative_tolerance"] = 1e-15 solver.parameters["snes_solver"]["absolute_tolerance"] = 1e-15 # solver.parameters["snes_solver"]["linear_solver_"]["maximum_iterations"]=1000 solver.parameters["snes_solver"][ "error_on_nonconvergence"] = False solver.solve() # option to store the visualization results if visualization == 'True': for argument_name, argument_function in iteritems( self.argument_functions_dict): df.File('solutions_iterations_3d/{}_{}.pvd'.format( argument_name, self.itr)) << argument_function self.L = -residual_form self.itr = self.itr + 1 outputs[state_name] = state_function.vector().get_local()
# inverse_solver.assign_model_parameters(m0) # inverse_solver.solve_inverse_problem() if T_msr.perturb or u_msr.perturb: T_msr.perturb = u_msr.perturb = 0.0 inverse_solver.assign_model_parameters(model_parameters_forall) inverse_solver.solve_inverse_problem() if PLOT_RESULTS or SAVE_RESULTS: fig_handle_and_name_pairs = plot_everything() fig_handles = [f[0] for f in fig_handle_and_name_pairs] fig_names = [f[1] for f in fig_handle_and_name_pairs] if SAVE_RESULTS: if not os.path.isdir(RESULTS_DIR): os.makedirs(RESULTS_DIR) for handle_i, name_i in zip(fig_handles, fig_names): handle_i.savefig(os.path.join(RESULTS_DIR, name_i) + '.png') handle_i.savefig(os.path.join(RESULTS_DIR, name_i) + '.pdf') if not PLOT_RESULTS: plt.close('all') outfile = dolfin.File(os.path.join(RESULTS_DIR, 'pvd', 'u.pvd')) for t in inverse_solver.observation_times: outfile << inverse_solver.observe_u(t, copy=False)
""" import mshr import dolfin from vtkplotter.dolfin import datadir, plot fname = "shuttle.stl" surface = mshr.Surface3D(datadir + fname) # add a cylinder cyl = mshr.Cylinder(dolfin.Point(-1.4, 0, 0), dolfin.Point(-1.0, 0, 0), 0.5, 0.7) totdomain = surface + cyl polyhedral_domain = mshr.CSGCGALDomain3D(totdomain) dolfin.info(polyhedral_domain, True) generator = mshr.CSGCGALMeshGenerator3D() #### Try automatic generator.parameters["mesh_resolution"] = 35.0 mesh = generator.generate(polyhedral_domain) xmlname = fname.split(".")[0] + ".xml" dolfin.File(xmlname) << mesh print(mesh, "saved to " + xmlname) ################################## plot(mesh, text=__doc__) ##################################
# Write mesh as xml file numVertices = p.shape[0] numCells = t.shape[0] editor = df.MeshEditor() mesh = df.Mesh() dim = 2 editor.open(mesh, 2, 2) # top. and geom. dimension are both 3 editor.init_vertices(numVertices) # number of vertices editor.init_cells(numCells) # number of cells for x in range(0, numVertices): editor.add_vertex(x, p[x][:]) for x in range(0, numCells): editor.add_cell(x, np.array(t[x][:], dtype=np.uintp)) editor.close() #Plot mesh using dolfin df.plot(mesh) df.interactive() #Write to file df.File('twovortexmesh.xml') << mesh
# # hIPPYlib is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License (as published by the Free # Software Foundation) version 2.0 dated June 1991. import dolfin as dl import sys sys.path.append("../../") from hippylib import * import numpy as np nx = 32 ny = 32 mesh = dl.UnitSquareMesh(nx, ny) Vh = dl.FunctionSpace(mesh, 'Lagrange', 1) Prior = LaplacianPrior(Vh, 1., 100.) nsamples = 1000 s = dl.Function(Vh, name="sample") noise = dl.Vector() Prior.init_vector(noise, "noise") size = len(noise.array()) fid = dl.File("results_cg/samples.pvd") for i in range(0, nsamples): noise.set_local(np.random.randn(size)) Prior.sample(noise, s.vector()) fid << s
posterior.mean = x[PARAMETER] post_tr, prior_tr, corr_tr = posterior.trace(method="Randomized", r=200) if rank == 0: print( "Posterior trace {0:5e}; Prior trace {1:5e}; Correction trace {2:5e}" .format(post_tr, prior_tr, corr_tr)) post_pw_variance, pr_pw_variance, corr_pw_variance = posterior.pointwise_variance( method="Randomized", r=200) kl_dist = posterior.klDistanceFromPrior() if rank == 0: print("KL-Distance from prior: ", kl_dist) fid = dl.File("results/pointwise_variance.pvd") fid << vector2Function(post_pw_variance, Vh[PARAMETER], name="Posterior") fid << vector2Function(pr_pw_variance, Vh[PARAMETER], name="Prior") fid << vector2Function(corr_pw_variance, Vh[PARAMETER], name="Correction") if rank == 0: print(sep, "Save State, Parameter, Adjoint, and observation in paraview", sep) xxname = ["State", "Parameter", "Adjoint"] xx = [vector2Function(x[i], Vh[i], name=xxname[i]) for i in range(len(Vh))] dl.File("results/poisson_state.pvd") << xx[STATE] dl.File("results/poisson_state_true.pvd") << vector2Function( utrue, Vh[STATE], name=xxname[STATE]) dl.File("results/poisson_parameter.pvd") << xx[PARAMETER] dl.File("results/poisson_parameter_true.pvd") << vector2Function(
def Cost(xp): comm = nMPI.COMM_WORLD mpi_rank = comm.Get_rank() x1, x2 = xp #The two variables (length and feed offset) rs = 8.0 # radiation boundary radius l = x1 # Patch length w = 4.5 # Patch width s1 = x2 * x1 / 2.0 # Feed offset h = 1.0 # Patch height t = 0.05 # Metal thickness lc = 1.0 # Coax length rc = 0.25 # Coax shield radius cc = 0.107 #Coax center conductor 50 ohm air diel eps = 1.0e-4 tol = 1.0e-6 eta = 377.0 # vacuum intrinsic wave impedance eps_c = 1.0 # dielectric permittivity k0 = 2.45 * 2.0 * np.pi / 30.0 # Frequency in GHz ls = 0.025 #Mesh density parameters for GMSH lm = 0.8 lw = 0.06 lp = 0.3 # Run GMSH only on one MPI processor (process 0). # We use the GMSH Python interface to generate the geometry and mesh objects if mpi_rank == 0: print("x[0] = {0:<f}, x[1] = {1:<f} ".format(xp[0], xp[1])) print("length = {0:<f}, width = {1:<f}, feed offset = {2:<f}".format(l, w, s1)) gmsh.initialize() gmsh.option.setNumber('General.Terminal', 1) gmsh.model.add("SimplePatchOpt") # Radiation sphere gmsh.model.occ.addSphere(0.0, 0.0, 0.0, rs, 1) gmsh.model.occ.addBox(0.0, -rs, 0.0, rs, 2*rs, rs, 2) gmsh.model.occ.intersect([(3,1)],[(3,2)], 3, removeObject=True, removeTool=True) # Patch gmsh.model.occ.addBox(0.0, -l/2, h, w/2, l, t, 4) # coax center gmsh.model.occ.addCylinder(0.0, s1, -lc, 0.0, 0.0, lc+h, cc, 5, 2.0*np.pi) # coax shield gmsh.model.occ.addCylinder(0.0, s1, -lc, 0.0, 0.0, lc, rc, 7) gmsh.model.occ.addBox(0.0, s1-rc, -lc, rc, 2.0*rc, lc, 8) gmsh.model.occ.intersect([(3,7)], [(3,8)], 9, removeObject=True, removeTool=True) gmsh.model.occ.fuse([(3,3)], [(3,9)], 10, removeObject=True, removeTool=True) # cutout internal boundaries gmsh.model.occ.cut([(3,10)], [(3,4),(3,5)], 11, removeObject=True, removeTool=True) gmsh.option.setNumber('Mesh.MeshSizeMin', ls) gmsh.option.setNumber('Mesh.MeshSizeMax', lm) gmsh.option.setNumber('Mesh.Algorithm', 6) gmsh.option.setNumber('Mesh.Algorithm3D', 1) gmsh.option.setNumber('Mesh.MshFileVersion', 4.1) gmsh.option.setNumber('Mesh.Format', 1) gmsh.option.setNumber('Mesh.MinimumCirclePoints', 36) gmsh.option.setNumber('Mesh.CharacteristicLengthFromCurvature', 1) gmsh.model.occ.synchronize() pts = gmsh.model.getEntities(0) gmsh.model.mesh.setSize(pts, lm) #Set background mesh density pts = gmsh.model.getEntitiesInBoundingBox(-eps, -l/2-eps, h-eps, w/2+eps, l/2+eps, h+t+eps) gmsh.model.mesh.setSize(pts, ls) pts = gmsh.model.getEntitiesInBoundingBox(-eps, s1-rc-eps, -lc-eps, rc+eps, s1+rc+eps, h+eps) gmsh.model.mesh.setSize(pts, lw) pts = gmsh.model.getEntitiesInBoundingBox(-eps, -rc-eps, -eps, rc+eps, rc+eps, eps) gmsh.model.mesh.setSize(pts, lw) # Embed points to reduce mesh density on patch faces fce1 = gmsh.model.getEntitiesInBoundingBox(-eps, -l/2-eps, h+t-eps, w/2+eps, l/2+eps, h+t+eps, 2) gmsh.model.occ.synchronize() gmsh.model.geo.addPoint(w/4, -l/4, h+t, lp, 1000) gmsh.model.geo.addPoint(w/4, 0.0, h+t, lp, 1001) gmsh.model.geo.addPoint(w/4, l/4, h+t, lp, 1002) gmsh.model.geo.synchronize() gmsh.model.occ.synchronize() print(fce1) fce2 = gmsh.model.getEntitiesInBoundingBox(-eps, -l/2-eps, h-eps, w/2+eps, l/2+eps, h+eps, 2) gmsh.model.geo.addPoint(w/4, -9*l/32, h, lp, 1003) gmsh.model.geo.addPoint(w/4, 0.0, h, lp, 1004) gmsh.model.geo.addPoint(w/4, 9*l/32, h, lp, 1005) gmsh.model.geo.synchronize() for tt in fce1: gmsh.model.mesh.embed(0, [1000, 1001, 1002], 2, tt[1]) for tt in fce2: gmsh.model.mesh.embed(0, [1003, 1004, 1005], 2, tt[1]) print(fce2) gmsh.model.occ.remove(fce1) gmsh.model.occ.remove(fce2) gmsh.model.occ.synchronize() gmsh.model.addPhysicalGroup(3, [11], 1) gmsh.model.setPhysicalName(3, 1, "Air") gmsh.model.mesh.optimize("Relocate3D", niter=5) gmsh.model.mesh.generate(3) gmsh.write("SimplePatch.msh") gmsh.finalize() # Mesh generation is finished. We now use Meshio to translate GMSH mesh to xdmf file for # importation into Fenics FE solver msh = meshio.read("SimplePatch.msh") for cell in msh.cells: if cell.type == "tetra": tetra_cells = cell.data for key in msh.cell_data_dict["gmsh:physical"].keys(): if key == "tetra": tetra_data = msh.cell_data_dict["gmsh:physical"][key] tetra_mesh = meshio.Mesh(points=msh.points, cells={"tetra": tetra_cells}, cell_data={"VolumeRegions":[tetra_data]}) meshio.write("mesh.xdmf", tetra_mesh) # Here we import the mesh into Fenics mesh = dolfin.Mesh() with dolfin.XDMFFile("mesh.xdmf") as infile: infile.read(mesh) mvc = dolfin.MeshValueCollection("size_t", mesh, 3) with dolfin.XDMFFile("mesh.xdmf") as infile: infile.read(mvc, "VolumeRegions") cf = dolfin.cpp.mesh.MeshFunctionSizet(mesh, mvc) # The boundary classes for the FE solver class PEC(dolfin.SubDomain): def inside(self, x, on_boundary): return on_boundary class InputBC(dolfin.SubDomain): def inside(self, x, on_boundary): return on_boundary and dolfin.near(x[2], -lc, tol) class OutputBC(dolfin.SubDomain): def inside(self, x, on_boundary): rr = np.sqrt(x[0]*x[0]+x[1]*x[1]+x[2]*x[2]) return on_boundary and dolfin.near(rr, 8.0, 1.0e-1) class PMC(dolfin.SubDomain): def inside(self, x, on_boundary): return on_boundary and dolfin.near(x[0], 0.0, tol) # Volume domains dolfin.File("VolSubDomains.pvd").write(cf) dolfin.File("Mesh.pvd").write(mesh) # Mark boundaries sub_domains = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1) sub_domains.set_all(4) pec = PEC() pec.mark(sub_domains, 0) in_port = InputBC() in_port.mark(sub_domains, 1) out_port = OutputBC() out_port.mark(sub_domains, 2) pmc = PMC() pmc.mark(sub_domains, 3) dolfin.File("BoxSubDomains.pvd").write(sub_domains) # Set up function spaces cell = dolfin.tetrahedron ele_type = dolfin.FiniteElement('N1curl', cell, 2, variant="integral") # H(curl) element for EM V2 = dolfin.FunctionSpace(mesh, ele_type * ele_type) V = dolfin.FunctionSpace(mesh, ele_type) (u_r, u_i) = dolfin.TrialFunctions(V2) (v_r, v_i) = dolfin.TestFunctions(V2) dolfin.info(mesh) #surface integral definitions from boundaries ds = dolfin.Measure('ds', domain = mesh, subdomain_data = sub_domains) #volume regions dx_air = dolfin.Measure('dx', domain = mesh, subdomain_data = cf, subdomain_id = 1) dx_subst = dolfin.Measure('dx', domain = mesh, subdomain_data = cf, subdomain_id = 2) # with source and sink terms u0 = dolfin.Constant((0.0, 0.0, 0.0)) #PEC definition # The incident field sources (E and H-fields) h_src = dolfin.Expression(('-(x[1] - s) / (2.0 * pi * (pow(x[0], 2.0) + pow(x[1] - s,2.0)))', 'x[0] / (2.0 * pi *(pow(x[0],2.0) + pow(x[1] - s,2.0)))', 0.0), degree = 2, s = s1) e_src = dolfin.Expression(('x[0] / (2.0 * pi * (pow(x[0], 2.0) + pow(x[1] - s,2.0)))', 'x[1] / (2.0 * pi *(pow(x[0],2.0) + pow(x[1] - s,2.0)))', 0.0), degree = 2, s = s1) Rrad = dolfin.Expression(('sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2])'), degree = 2) #Boundary condition dictionary boundary_conditions = {0: {'PEC' : u0}, 1: {'InputBC': (h_src)}, 2: {'OutputBC': Rrad}} n = dolfin.FacetNormal(mesh) #Build PEC boundary conditions for real and imaginary parts bcs = [] for i in boundary_conditions: if 'PEC' in boundary_conditions[i]: bc = dolfin.DirichletBC(V2.sub(0), boundary_conditions[i]['PEC'], sub_domains, i) bcs.append(bc) bc = dolfin.DirichletBC(V2.sub(1), boundary_conditions[i]['PEC'], sub_domains, i) bcs.append(bc) # Build input BC source term and loading term integral_source = [] integrals_load =[] for i in boundary_conditions: if 'InputBC' in boundary_conditions[i]: r = boundary_conditions[i]['InputBC'] bb1 = 2.0 * (k0 * eta) * dolfin.inner(v_i, dolfin.cross(n, r)) * ds(i) #Factor of two from field equivalence principle integral_source.append(bb1) bb2 = dolfin.inner(dolfin.cross(n, v_i), dolfin.cross(n, u_r)) * k0 * np.sqrt(eps_c) * ds(i) integrals_load.append(bb2) bb2 = dolfin.inner(-dolfin.cross(n, v_r), dolfin.cross(n, u_i)) * k0 * np.sqrt(eps_c) * ds(i) integrals_load.append(bb2) for i in boundary_conditions: if 'OutputBC' in boundary_conditions[i]: r = boundary_conditions[i]['OutputBC'] bb2 = (dolfin.inner(dolfin.cross(n, v_i), dolfin.cross(n, u_r)) * k0 + 1.0 * dolfin.inner(dolfin.cross(n, v_i), dolfin.cross(n, u_i)) / r)* ds(i) integrals_load.append(bb2) bb2 = (dolfin.inner(-dolfin.cross(n, v_r), dolfin.cross(n, u_i)) * k0 + 1.0 * dolfin.inner(dolfin.cross(n, v_r), dolfin.cross(n, u_r)) / r)* ds(i) integrals_load.append(bb2) # for PMC, do nothing. Natural BC. a = (dolfin.inner(dolfin.curl(v_r), dolfin.curl(u_r)) + dolfin.inner(dolfin.curl(v_i), dolfin.curl(u_i)) - eps_c * k0 * k0 * (dolfin.inner(v_r, u_r) + dolfin.inner(v_i, u_i))) * dx_subst + (dolfin.inner(dolfin.curl(v_r), dolfin.curl(u_r)) + dolfin.inner(dolfin.curl(v_i), dolfin.curl(u_i)) - k0 * k0 * (dolfin.inner(v_r, u_r) + dolfin.inner(v_i, u_i))) * dx_air + sum(integrals_load) L = sum(integral_source) u1 = dolfin.Function(V2) vdim = u1.vector().size() print("Solution vector size =", vdim) dolfin.solve(a == L, u1, bcs, solver_parameters = {'linear_solver' : 'mumps'}) #Here we write files of the field solution for inspection u1_r, u1_i = u1.split(True) fp = dolfin.File("EField_r.pvd") fp << u1_r fp = dolfin.File("EField_i.pvd") fp << u1_i # Compute power relationships and reflection coefficient H = dolfin.interpolate(h_src, V) # Get input field P = dolfin.assemble((-dolfin.dot(u1_r,dolfin.cross(dolfin.curl(u1_i),n))+dolfin.dot(u1_i,dolfin.cross(dolfin.curl(u1_r),n))) * ds(2)) P_refl = dolfin.assemble((-dolfin.dot(u1_i,dolfin.cross(dolfin.curl(u1_r), n)) + dolfin.dot(u1_r, dolfin.cross(dolfin.curl(u1_i), n))) * ds(1)) P_inc = dolfin.assemble((dolfin.dot(H, H) * eta / (2.0 * np.sqrt(eps_c))) * ds(1)) print("Integrated power on port 2:", P/(2.0 * k0 * eta)) print("Incident power at port 1:", P_inc) print("Integrated reflected power on port 1:", P_inc - P_refl / (2.0 * k0 * eta)) #Reflection coefficient is returned as cost function rho_old = (P_inc - P_refl / (2.0 * k0 * eta)) / P_inc #Fraction of incident power reflected as objective function return rho_old
def _save_dolfin(data, FILE): dolfin.File(str(os.path.join(DIR, FILE))) << data
def traction_test( ell=0.1, degree=1, n=3, nu=0.0, E=1., load_min=0, load_max=2, loads=None, nsteps=20, Lx=1, Ly=0.1, outdir="outdir", postfix='', savelag=1, sigma_D0=1., continuation=False, checkstability=True, configString='' ): # constants ell = ell Lx = Lx Ly = Ly load_min = load_min load_max = load_max nsteps = nsteps outdir = outdir loads=loads savelag = 1 nu = dolfin.Constant(nu) ell = dolfin.Constant(ell) E0 = dolfin.Constant(E) sigma_D0 = E0 n = n continuation = continuation config = json.loads(configString) if configString != '' else '' cmd_parameters = { 'material': { "ell": ell.values()[0], "E": E0.values()[0], "nu": nu.values()[0], "sigma_D0": sigma_D0.values()[0]}, 'geometry': { 'Lx': Lx, 'Ly': Ly, 'n': n, }, 'experiment': { 'signature': '' }, 'stability': { 'checkstability' : checkstability, 'continuation' : continuation }, 'time_stepping': { 'load_min': load_min, 'load_max': load_max, 'nsteps': nsteps, 'outdir': outdir, 'postfix': postfix, 'savelag': savelag}, 'alt_min': {}, "code": {} } if config: for par in config: parameters[par].update(config[par]) else: for par in parameters: parameters[par].update(cmd_parameters[par]) print(parameters) signature = hashlib.md5(str(parameters).encode('utf-8')).hexdigest() outdir += '-{}{}'.format(signature, cmd_parameters['time_stepping']['postfix']) # outdir += '-{}'.format(cmd_parameters['time_stepping']['postfix']) parameters['time_stepping']['outdir']=outdir Path(outdir).mkdir(parents=True, exist_ok=True) print('Outdir is: '+outdir) with open(os.path.join(outdir, 'rerun.sh'), 'w') as f: configuration = deepcopy(parameters) configuration['time_stepping'].pop('outdir') str(configuration).replace("\'True\'", "True").replace("\'False\'", "False") rerun_cmd = 'python3 {} --config="{}"'.format(__file__, configuration) f.write(rerun_cmd) with open(os.path.join(outdir, 'parameters.pkl'), 'w') as f: json.dump(parameters, f) with open(os.path.join(outdir, 'signature.md5'), 'w') as f: f.write(signature) geom = mshr.Rectangle(dolfin.Point(-Lx/2., -Ly/2.), dolfin.Point(Lx/2., Ly/2.)) mesh = mshr.generate_mesh(geom, int(float(n * Lx / ell))) meshf = dolfin.File(os.path.join(outdir, "mesh.xml")) meshf << mesh left = dolfin.CompiledSubDomain("near(x[0], -Lx/2.)", Lx=Lx) right = dolfin.CompiledSubDomain("near(x[0], Lx/2.)", Lx=Lx) bottom = dolfin.CompiledSubDomain("near(x[1],-Ly/2.)", Ly=Ly) top = dolfin.CompiledSubDomain("near(x[1],Ly/2.)", Ly=Ly) left_bottom_pt = dolfin.CompiledSubDomain("near(x[0],-Lx/2.) && near(x[1],-Ly/2.)", Lx=Lx, Ly=Ly) mf = dolfin.MeshFunction("size_t", mesh, 1, 0) right.mark(mf, 1) left.mark(mf, 2) bottom.mark(mf, 3) ds = dolfin.Measure("ds", subdomain_data=mf) dx = dolfin.Measure("dx", metadata=form_compiler_parameters, domain=mesh) # Function Spaces V_u = dolfin.VectorFunctionSpace(mesh, "CG", 1) V_alpha = dolfin.FunctionSpace(mesh, "CG", 1) u = dolfin.Function(V_u, name="Total displacement") alpha = dolfin.Function(V_alpha, name="Damage") state = [u, alpha] Z = dolfin.FunctionSpace(mesh, dolfin.MixedElement([u.ufl_element(),alpha.ufl_element()])) z = dolfin.Function(Z) v, beta = dolfin.split(z) # BCs (homogenous version needed for residual evaluation) ut = dolfin.Expression("t", t=0.0, degree=0) bcs_u = [dolfin.DirichletBC(V_u.sub(0), dolfin.Constant(0), left), dolfin.DirichletBC(V_u.sub(0), ut, right), dolfin.DirichletBC(V_u, (0, 0), left_bottom_pt, method="pointwise")] bcs_alpha = [] # Files for output ColorPrint.print_warn('Outdir = {}'.format(outdir)) file_out = dolfin.XDMFFile(os.path.join(outdir, "output.xdmf")) file_out.parameters["functions_share_mesh"] = True file_out.parameters["flush_output"] = True file_con = dolfin.XDMFFile(os.path.join(outdir, "cont.xdmf")) file_con.parameters["functions_share_mesh"] = True file_con.parameters["flush_output"] = True file_eig = dolfin.XDMFFile(os.path.join(outdir, "modes.xdmf")) file_eig.parameters["functions_share_mesh"] = True file_eig.parameters["flush_output"] = True file_postproc = dolfin.XDMFFile(os.path.join(outdir, "output_postproc.xdmf")) file_postproc.parameters["functions_share_mesh"] = True file_postproc.parameters["flush_output"] = True file_bif = dolfin.XDMFFile(os.path.join(outdir, "bifurcation_postproc.xdmf")) file_bif.parameters["functions_share_mesh"] = True file_bif.parameters["flush_output"] = True # Problem definition model = DamageElasticityModel(state, E0, nu, ell, sigma_D0) model.dx = dx model.ds = ds energy = model.total_energy_density(u, alpha)*model.dx # Alternate minimisation solver solver = solvers.AlternateMinimizationSolver(energy, [u, alpha], [bcs_u, bcs_alpha], parameters=parameters['alt_min']) rP = model.rP(u, alpha, v, beta)*model.dx rN = model.rN(u, alpha, beta)*model.dx stability = StabilitySolver(mesh, energy, [u, alpha], [bcs_u, bcs_alpha], z, rayleigh=[rP, rN], parameters = parameters['stability']) # stability = StabilitySolver(mesh, energy, [u, alpha], [bcs_u, bcs_alpha], z, parameters = parameters['stability']) # Time iterations load_steps = np.linspace(load_min, load_max, parameters['time_stepping']['nsteps']) if loads: load_steps = loads stability.parameters['checkstability'] = True time_data = [] linesearch = LineSearch(energy, [u, alpha]) alpha_old = dolfin.Function(alpha.function_space()) lmbda_min_prev = 0.000001 bifurcated = False bifurcation_loads = [] save_current_bifurcation = False bifurc_i = 0 alpha_bif = dolfin.Function(V_alpha) alpha_bif_old = dolfin.Function(V_alpha) for it, load in enumerate(load_steps): ut.t = load alpha_old.assign(alpha) ColorPrint.print_warn('Solving load t = {:.2f}'.format(load)) # First order stability conditions (time_data_i, am_iter) = solver.solve() # Second order stability conditions (stable, negev) = stability.solve(solver.problem_alpha.lb) ColorPrint.print_pass('Current state is{}stable'.format(' ' if stable else ' un')) mineig = stability.mineig if hasattr(stability, 'mineig') else 0.0 print('lmbda min', lmbda_min_prev) print('mineig', mineig) Deltav = (mineig-lmbda_min_prev) if hasattr(stability, 'eigs') else 0 if (mineig + Deltav)*(lmbda_min_prev+dolfin.DOLFIN_EPS) < 0 and not bifurcated: bifurcated = True # save 3 bif modes print('About to bifurcate load ', load, 'step', it) bifurcation_loads.append(load) print('DEBUG: decide what to do') # save_current_bifurcation = True bifurc_i += 1 lmbda_min_prev = mineig if hasattr(stability, 'mineig') else 0. if stable: solver.update() else: # Continuation iteration = 1 while stable == False: # linesearch perturbation_v = stability.perturbation_v perturbation_beta = stability.perturbation_beta h_opt, (hmin, hmax), energy_perturbations = linesearch.search( [u, alpha, alpha_old], perturbation_v, perturbation_beta) if h_opt != 0: save_current_bifurcation = True alpha_bif.assign(alpha) alpha_bif_old.assign(alpha_old) # admissible uval = u.vector()[:] + h_opt * perturbation_v.vector()[:] aval = alpha.vector()[:] + h_opt * perturbation_beta.vector()[:] u.vector()[:] = uval alpha.vector()[:] = aval u.vector().vec().ghostUpdate() alpha.vector().vec().ghostUpdate() # import pdb; pdb.set_trace() (time_data_i, am_iter) = solver.solve() (stable, negev) = stability.solve(alpha_old) ColorPrint.print_pass(' Continuation iteration {}, current state is{}stable'.format(iteration, ' ' if stable else ' un')) iteration += 1 else: # warn ColorPrint.print_warn('Found zero increment, we are stuck in the matrix') ColorPrint.print_warn('Continuing load program') break solver.update() # stable == True time_data_i["load"] = load time_data_i["stable"] = stable time_data_i["elastic_energy"] = dolfin.assemble( model.elastic_energy_density(model.eps(u), alpha)*dx) time_data_i["dissipated_energy"] = dolfin.assemble( model.damage_dissipation_density(alpha)*dx) time_data_i["eigs"] = stability.eigs if hasattr(stability, 'eigs') else np.inf time_data_i["stable"] = stability.stable time_data_i["# neg ev"] = stability.negev # import pdb; pdb.set_trace() _sigma = model.stress(model.eps(u), alpha) e1 = dolfin.Constant([1, 0]) _snn = dolfin.dot(dolfin.dot(_sigma, e1), e1) time_data_i["sigma"] = 1/Ly * dolfin.assemble(_snn*model.ds(1)) time_data_i["S(alpha)"] = dolfin.assemble(1./(model.a(alpha))*model.dx) time_data_i["A(alpha)"] = dolfin.assemble((model.a(alpha))*model.dx) time_data_i["avg_alpha"] = 1/dolfin.assemble(dolfin.project(Constant(1.), V_alpha)*model.dx) * dolfin.assemble(alpha*model.dx) ColorPrint.print_pass( "Time step {:.4g}: it {:3d}, err_alpha={:.4g}".format( time_data_i["load"], time_data_i["iterations"], time_data_i["alpha_error"])) time_data.append(time_data_i) time_data_pd = pd.DataFrame(time_data) if np.mod(it, savelag) == 0: with file_out as file: file.write(alpha, load) file.write(u, load) with file_postproc as file: file.write_checkpoint(alpha, "alpha-{}".format(it), 0, append = True) print('DEBUG: written step ', it) file.read_checkpoint(alpha, 'alpha-{}'.format(it), 0) print('DEBUG: read step {}, load {}'.format(it, load)) print('DEBUG: file {}'.format(os.path.join(outdir, "output_postproc.xdmf"))) # import pdb; pdb.set_trace() if save_current_bifurcation: # modes = np.where(stability.eigs < 0)[0] time_data_i['h_opt'] = h_opt time_data_i['max_h'] = hmax time_data_i['min_h'] = hmin with file_bif as file: # leneigs = len(modes) # maxmodes = min(3, leneigs) beta0v = dolfin.project(stability.perturbation_beta, V_alpha) print('DEBUG: irrev ', alpha.vector()-alpha_old.vector()) file.write_checkpoint(beta0v, 'beta0', 0, append = True) file.write_checkpoint(alpha_bif_old, 'alpha-old', 0, append=True) file.write_checkpoint(alpha_bif, 'alpha-bif', 0, append=True) file.write_checkpoint(alpha, 'alpha', 0, append=True) np.save(os.path.join(outdir, 'energy_perturbations'), energy_perturbations, allow_pickle=True, fix_imports=True) with file_eig as file: _v = dolfin.project(dolfin.Constant(h_opt)*perturbation_v, V_u) _beta = dolfin.project(dolfin.Constant(h_opt)*perturbation_beta, V_alpha) _v.rename('perturbation displacement', 'perturbation displacement') _beta.rename('perturbation damage', 'perturbation damage') # import pdb; pdb.set_trace() file.write(_v, load) file.write(_beta, load) file.write_checkpoint(_v, 'perturbation_v', 0, append=True) file.write_checkpoint(_beta, 'perturbation_beta', 0, append=True) save_current_bifurcation = False # if np.mod(it, 10) == 0: # alphatest = dolfin.Function(V_alpha) # with dolfin.XDMFFile(os.path.join(outdir, "output_postproc.xdmf")) as f: # f.read_checkpoint(alphatest, "alpha-{}".format(it), 0) # print('DEBUG: read step ', it) time_data_pd.to_json(os.path.join(outdir, "time_data.json")) from post_processing import plot_global_data print(time_data_pd) print() print('Output in: '+outdir) # if size == 1: # plt.figure() # dolfin.plot(alpha) # plt.savefig(os.path.join(outdir, "alpha.png")) # plt.figure() # dolfin.plot(u, mode="displacement") # plt.savefig(os.path.join(outdir, "u.png")) # plt.close('all') return time_data_pd
max_iter=100) if rank == 0: print "Posterior trace {0:5g}; Prior trace {1:5g}; Correction trace {2:5g}".format( post_tr, prior_tr, corr_tr) post_pw_variance, pr_pw_variance, corr_pw_variance = posterior.pointwise_variance( "Exact") if rank == 0: print sep, "Save results", sep problem.exportState([u, a, p], "results/conc.pvd", "concentration") problem.exportState([utrue, true_initial_condition, p], "results/true_conc.pvd", "concentration") problem.exportState([problem.ud, true_initial_condition, p], "results/noisy_conc.pvd", "concentration") fid = dl.File("results/pointwise_variance.pvd") fid << vector2Function(post_pw_variance, Vh, name="Posterior") fid << vector2Function(pr_pw_variance, Vh, name="Prior") fid << vector2Function(corr_pw_variance, Vh, name="Correction") U.export(Vh, "hmisfit/evect.pvd", varname="gen_evect", normalize=True) if rank == 0: np.savetxt("hmisfit/eigevalues.dat", d) if rank == 0: print sep, "Generate samples from Prior and Posterior", sep fid_prior = dl.File("samples/sample_prior.pvd") fid_post = dl.File("samples/sample_post.pvd") nsamples = 50 noise = dl.Vector() posterior.init_vector(noise, "noise")
def test_2_2D_cyl_laplace_solver(self): """Test a 2D Laplace equation in cylindrical coordinates. This is a Laplace solve as there is no source term, only boundary-conditions. """ fncName = '(' + __file__ + ') ' + sys._getframe( ).f_code.co_name + '():\n' print('\ntest: ', fncName) ## Specialized modules for the mesh and field solver from UserMesh_y_Fields_FE2D_Module import UserMesh2DCirc_C from UserMesh_y_Fields_FE2D_Module import UserMeshInput2DCirc_C from UserMesh_y_Fields_FE2D_Module import UserPoissonSolve2DCirc_C # For this calculation, we use the Dolfin framework for finite-element fields. # field_infrastructure_module = 'Dolfin_Module' # fI_M = im_m.import_module(field_infrastructure_module) umi = UserMeshInput2DCirc_C() # Make the mesh # radial umi.rmin, umi.rmax = 1.0, 5.0 # Mesh goes from rmin to rmax in radius umi.nr = 10 # Number of divisions in r direction umi.stretch = 1.3 # Stretch parameter # Name the Dirichlet boundaries and assign integers to them. # These are the boundary-name -> int pairs used to mark mesh # facets: rminIndx = 1 rmaxIndx = 2 fieldBoundaryDict = { 'rmin': rminIndx, 'rmax': rmaxIndx, } umi.field_boundary_dict = fieldBoundaryDict # theta, starts at 0 umi.tmax = math.pi / 2 # quarter-circle umi.nt = 20 # Number of divisions in theta direction # The diagonal that makes the triangular mesh # Options: 'left, 'right', 'left/right', 'crossed' umi.diagonal = 'crossed' mesh_M = UserMesh2DCirc_C(umi, compute_tree=False, plot_flag=self.plot_mesh) # Storage for the potential and electric field phiElementType = 'Lagrange' phiElementDegree = 1 phiFieldType = 'scalar' phi_F = Field_C(mesh_M=mesh_M, element_type=phiElementType, element_degree=phiElementDegree, field_type=phiFieldType) if phiElementDegree == 1: # For linear elements, grad(phi) is discontinuous across # elements. To get these values, we need Discontinuous Galerkin # elements. electricFieldElementType = "DG" else: electricFieldElementType = "Lagrange" negElectricField_F = Field_C(mesh_M=mesh_M, element_type=electricFieldElementType, element_degree=phiElementDegree - 1, field_type='vector') # The Laplace solver parameters linearSolver = 'lu' preconditioner = None # Don't get exactly the same solutions with the following # linearSolver = 'cg' # preconditioner = 'ilu' # Dirichlet Boundaries are marked with a boundary marker mesh # function fieldBoundaryMarker = mesh_M.field_boundary_marker # Boundary values of the potential. These names have to be # the same as those assigned to the boundaries above. phiVals = { 'rmin': 0.0, 'rmax': -1.5, } phiBCs = dict((bnd, [fieldBoundaryDict[bnd], phiVals[bnd]]) for bnd in list(fieldBoundaryDict.keys())) computeEflag = True laplacesolve = UserPoissonSolve2DCirc_C( phi_F, linearSolver, preconditioner, fieldBoundaryMarker, phiBCs, neg_electric_field=negElectricField_F) laplacesolve.assemble_source_expression(0.0) plotTitle = os.path.basename( __file__) + ": " + sys._getframe().f_code.co_name laplacesolve.solve_for_phi(plot_flag=self.plot_results, plot_title=plotTitle) # yesno = raw_input("Looks OK [Y/n]?") # self.assertNotEqual(yesno, 'n', "Problem with mesh") # Write the potential to a file in VTK and XML formats file = df_m.File("phi_test_2_2D.pvd") phi_F.function.rename("phi2D", "phi_label") file << phi_F.function file = df_m.File("phi_test_2_2D.xml") file << phi_F.function # Write -E to a file in VTK and XML formats if negElectricField_F is not None: negElectricField_F.function.rename("E2D", "E_label") file = df_m.File("negE_test_2_2D.pvd") file << negElectricField_F.function file = df_m.File("negE_test_2_2D.xml") file << negElectricField_F.function # Try XDMF format xf = df_m.XDMFFile("phi_test_2_2D.xdmf") xf.write(phi_F.function) return
double R = sqrt(pow(x[0],2)+pow(x[1],2)); double phi = atan2(x[1],x[0]); double d_0 = C_9 + C_2*cyl_bessel_k(0, R*lambda_2/tau) + C_8*cyl_bessel_i(0, R*lambda_2/tau); double d = - (10*A_1 * pow(R,2))/(27*tau) + (4*C_4*R)/(tau) - (2*C_5*tau)/R + C_14*cyl_bessel_k(1, R*lambda_2/tau) + C_15* cyl_bessel_i(1, R*lambda_2/tau); values[0] = d_0 + cos(phi) * d; } // The data stored in mesh functions double R; }; PYBIND11_MODULE(SIGNATURE, m) { py::class_<Pressure, std::shared_ptr<Pressure>, dolfin::Expression> (m, "Pressure") .def(py::init<>()); } """ c = df.CompiledExpression(df.compile_cpp_code(p_code).Pressure(), degree=1) print(2 * c([1, 1])) p_i = df.interpolate(c, V) df.plot(p_i) file = df.File("out.pvd") file.write(p_i)
def test_1_1D_spherical_laplace_solver(self): """Test a 1D Laplace equation in spherical coordinates. This is a Laplace solve as there is no source term, only boundary-conditions. NB: The potential is represented with quadratic elements are used instead of the usual linear ones. """ fncName = '(' + __file__ + ') ' + sys._getframe( ).f_code.co_name + '():\n' print('\ntest: ', fncName) ## Specialized modules for the mesh and field solver from UserMesh_y_Fields_Spherical1D_Module import UserMeshInput1DS_C from UserMesh_y_Fields_Spherical1D_Module import UserMesh1DS_C from UserMesh_y_Fields_Spherical1D_Module import UserPoissonSolve1DS_C # For this calculation, we use the Dolfin framework for finite-element fields. # field_infrastructure_module = 'Dolfin_Module' # fI_M = im_m.import_module(field_infrastructure_module) umi = UserMeshInput1DS_C() ## Make the mesh # radial umi.rmin, umi.rmax = 1.0, 5.0 # Mesh goes from rmin to rmax in radius umi.nr = 10 # Number of divisions in r direction umi.stretch = 1.3 # Stretch parameter # Name the Dirichlet boundaries and assign integers to them. # These are the boundary-name -> int pairs used to mark mesh # facets: rminIndx = 1 rmaxIndx = 2 fieldBoundaryDict = { 'rmin': rminIndx, 'rmax': rmaxIndx, } umi.field_boundary_dict = fieldBoundaryDict plotTitle = os.path.basename( __file__) + ": " + sys._getframe().f_code.co_name mesh_M = UserMesh1DS_C(umi, compute_tree=False, plot_flag=self.plot_mesh, plot_title=plotTitle) # yesno = raw_input("Just called UserMesh1DS_C() in test_1_1D_spherical_laplace_solver") ## Storage for the potential and electric field phiElementType = 'Lagrange' phiElementDegree = 2 phiFieldType = 'scalar' phi_F = Field_C(mesh_M=mesh_M, element_type=phiElementType, element_degree=phiElementDegree, field_type=phiFieldType) if phiElementDegree == 1: # For linear elements, grad(phi_F) is discontinuous across # elements. To represent this field, we need Discontinuous Galerkin # elements. electricFieldElementType = 'DG' else: electricFieldElementType = 'Lagrange' negElectricField_F = Field_C(mesh_M=mesh_M, element_type=electricFieldElementType, element_degree=phiElementDegree - 1, field_type='vector') ## The Laplace solver parameters # Gives PETSc LU solver, (null). (Direct solver). linearSolver = 'lu' preconditioner = None # Dirichlet boundaries are marked with a boundary marker mesh function fieldBoundaryMarker = mesh_M.field_boundary_marker # Boundary values of the potential phiVals = { 'rmin': 0.0, 'rmax': -1.5, } phiBCs = dict((bnd, [fieldBoundaryDict[bnd], phiVals[bnd]]) for bnd in list(fieldBoundaryDict.keys())) # Compute the electrostatic field from phi laplacesolve = UserPoissonSolve1DS_C( phi_F, linearSolver, preconditioner, fieldBoundaryMarker, phiBCs, neg_electric_field=negElectricField_F) # Set the source term: it's zero for Laplace's equation. # This sets the b vector laplacesolve.assemble_source_expression(0.0) # Solve for the potential plotTitle = os.path.basename( __file__) + ": " + sys._getframe().f_code.co_name laplacesolve.solve_for_phi(plot_flag=self.plot_results, plot_title=plotTitle) # yesno = raw_input("Looks OK [Y/n]?") # self.assertNotEqual(yesno, 'n', "Problem with mesh") # potentialFieldOutputFile = ctrl.title + "-phi" + ".xdmf" # potentialFieldOutputObj = df_m.XDMFFile(potentialFieldOutputFile) # Write the potential to a file in VTK and XML formats file = df_m.File('phi_test_1_1D.pvd') # phi_name goes into the output file; phi_label doesn't phi_F.function.rename("phi1D", "phi_label") file << phi_F.function file = df_m.File('phi_test_1_1D.xml') file << phi_F.function # Write the potential in XDMF format xf = df_m.XDMFFile("phi_test_1_1D.xdmf") xf.write(phi_F.function) # Write -E to a file in VTK and XML formats # !!! VTK cannot write a vector field on a 1D grid. # file = df_m.File('negE_test_1_1D.pvd') # file << fieldsolveCI.negE file = df_m.File('negE_test_1_1D.xml') file << negElectricField_F.function # Write -E in XDMF format xf = df_m.XDMFFile("negE_test_1_1D.xdmf") xf.write(negElectricField_F.function) # Check the 1/r^2 fall-off in E: (Emin, Emax) = (negElectricField_F.function(umi.rmin), negElectricField_F.function(umi.rmax)) # print "Emin, Emax =", Emin, Emax ratio = Emin * umi.rmin**2 / (Emax * umi.rmax**2) # print "ratio:", ratio decimal_places = 1 # Note: can get 2 decimal places for degree-3 elements. self.assertAlmostEqual(ratio, 1.0, places=decimal_places, msg="Falloff in E is not 1/r^2 to %d decimals" % decimal_places) r_arr = mesh_M.mesh.coordinates()[:, 0] phi_arr = phi_F.function.vector().get_local() nnodes = len(phi_arr) nvertices = len(r_arr) # print "nnode =", nnodes # print "nvertex =", nvertex # print "r_arr =", r_arr # print "phi_arr =", phi_arr # Compute E from a simple derivative, for linear elements if nnodes == nvertices: # Check the derivative: (nvertices*dim array, so need the ,0) # Set up temp arrays ncells = len(r_arr) - 1 negEexp = np_m.zeros(ncells) dr = np_m.zeros(ncells) dr[0:ncells] = r_arr[1:ncells + 1] - r_arr[0:ncells] # Have to reverse phi_arr to get it in same order as r_arr phi_arr = phi_arr[::-1] # Compute dphi/dr negEexp[0:ncells] = (phi_arr[1:ncells + 1] - phi_arr[0:ncells]) / dr[0:ncells] # print "negEexp =", negEexp negEget = laplacesolve.negE.vector().get_local() # print "negEget =", fieldsolveCI.negE.vector().array() # Check that the derivative equals the stored negE for ic in range(ncells): self.assertAlmostEqual( negEget[ic], negEexp[ic], msg="Expected and stored values of negE are not the same") return
dolfin.solve(a == L2, u_sol2, bc) # ### Dolfin plot # In[65]: dolfin.plot(u_sol1) dolfin.interactive() # ### Save VTK files # In[66]: dolfin.File('u_sol1.pvd') << u_sol1 # In[67]: dolfin.File('u_sol2.pvd') << u_sol2 # In[68]: f = dolfin.File('combined.pvd') f << mesh f << u_sol1 f << u_sol2
llg.A =1.3e-11 llg.D = 4e-3 #llg.set_m(( # 'MS * (2*x[0]/L - 1)', # 'sqrt(MS*MS - MS*MS*(2*x[0]/L - 1)*(2*x[0]/L - 1))', # '0'), L=length, MS=llg.Ms) llg.set_m(( 'MS', '0', '0'), MS=llg.Ms) llg.setup(use_dmi=True,use_exchange=True) llg.pins = [] print "point 0:",mesh.coordinates()[0] print "Solving problem..." ts = numpy.linspace(0, 1e-9, 50) tol = 1e-4 file = df.File('s.pvd') for i in range(len(ts)-1): print "step=%4d, time=%12.6g " % (i,ts[i]), #ys,infodict = odeint(llg.solve_for, llg.m, [ts[i],ts[i+1]], full_output=True,printmessg=True,rtol=tol,atol=tol) ys,infodict = odeint(llg.solve_for, llg.m, [ts[i],ts[i+1]], full_output=True,printmessg=False) print "NFE=%4d, NJE=%4d" % (infodict['nfe'],infodict['nje']) file << llg._m df.plot(llg._m) df.interactive() print "Done"
def main(dt, tEnd, length=10.0, height=5.0, numElementsFilm=2.0, reGen=True, ratLame=5.0, ratFilmSub=100.0): #fileDir = ("results-dt-%.2f-tEnd-%.0f-L-%.1f-H-%.1f-ratioLame-%.0f-ratioFilm-%.0f" % # (dt, tEnd, length, height, ratLame, ratFilmSub)) fileDir = "results-1" # create geometry rectDomain = Geometry(length=length, height=height, filmHeight=0.05) rectDomain.read_mesh(numElementsFilm, reGen) # define periodic boundary conditions periodicBC = PeriodicBoundary(rectDomain) # specify physical parameters physParams = Physical_Params(lmbdaSub=ratLame, muSub=1.0, ratFilmSub=100.0) physParams.create_Lame(rectDomain) # create discrete function space element = create_vector_element(rectDomain, order=1) W = dl.FunctionSpace(rectDomain.mesh, element, constrained_domain=periodicBC) # define boundaries def left(x, on_boundary): return dl.near(x[0], 0.) and on_boundary def right(x, on_boundary): return dl.near(x[0], rectDomain.length) and on_boundary def bottom(x, on_boundary): return dl.near(x[1], 0.0) and on_boundary def top(x, on_boundary): return dl.near(x[1], rectDomain.height) and on_boundary def corner(x, on_boundary): return dl.near(x[0], 0.0) and dl.near(x[1], 0.0) # define fixed boundary bcs = [ dl.DirichletBC(W.sub(0), dl.Constant(0), left), dl.DirichletBC(W.sub(0), dl.Constant(0), right), dl.DirichletBC(W.sub(1), dl.Constant(0), bottom), dl.DirichletBC(W.sub(0), dl.Constant(0), corner, method="pointwise") ] bcs = bcs[-2:] # the variable to solve for w = dl.Function(W, name="Variables at current step") # test and trial function dw = dl.TrialFunction(W) w_ = dl.TestFunction(W) # dealing with physics of growth growthFactor = create_growthFactor(rectDomain, filmGrowth=1, subGrowth=0) Fg = create_Fg(growthFactor, "uniaxial") # kinematics I = dl.Identity(2) F = I + dl.grad(w) Fe = F * dl.inv(Fg) # write the variational form from potential energy psi = cal_neoHookean(Fe, physParams) Energy = psi * dl.dx Residual = dl.derivative(Energy, w, w_) Jacobian = dl.derivative(Residual, w, dw) problem = BucklingProblem(w, Energy, Residual, Jacobian) wLowerBound, wUpperBound = create_bounds(wMin=[-0.5, -0.5], wMax=[0.5, 0.5], functionSpace=W, boundaryCondtions=bcs) # Create the PETScTAOSolver solver = dl.PETScTAOSolver() TAOSolverParameters = { "method": "tron", "maximum_iterations": 1000, "monitor_convergence": True } solver.parameters.update(TAOSolverParameters) #solver.parameters["report"] = False #solver.parameters["linear_solver"] = "umfpack" #solver.parameters["line_search"] = "gpcg" #solver.parameters["preconditioner"] = "ml_amg" growthRate = 0.1 growthEnd = growthRate * tEnd gF = 0.0 outDisp = dl.File(fileDir + "/displacement.pvd") outDisp << (w, 0.0) iCounter = 0 wArray = w.compute_vertex_values() while gF <= growthEnd - tol: gF += growthRate * dt iCounter += 1 growthFactor.gF = gF w.vector()[:] += 2e-04 * np.random.uniform(-1, 1, w.vector().local_size()) nIters, converged = solver.solve(problem, w.vector(), wLowerBound.vector(), wUpperBound.vector()) wArray[:] = w.compute_vertex_values() np.save(fileDir + "/w-{}.npy".format(iCounter), wArray) print("--- growth = %.4f, niters = %d, dt = %.5f -----" % (1 + gF, nIters, dt)) outDisp << (w, gF)
noise_array = noise.get_local() else: noise_array = None noise_array = comm.bcast(noise_array, root=0) noise.set_local(noise_array) mtrue = dl.Vector() prior.init_vector(mtrue, 0) prior.sample(noise, mtrue) if rank == 0: filename = 'data/particle_true.xdmf' particle_fun = dl.Function(Vh[PARAMETER], name='particle') particle_fun.vector().axpy(1.0, mtrue) if dlversion() <= (1, 6, 0): dl.File(mesh.mpi_comm(), filename) << particle_fun else: xf = dl.XDMFFile(mesh.mpi_comm(), filename) xf.write(particle_fun) utrue = pde.generate_state() x = [utrue, mtrue, None] pde.solveFwd(x[STATE], x, 1e-9) misfit.B.mult(x[STATE], misfit.d) rel_noise = 0.01 MAX = misfit.d.norm("linf") noise_std_dev = rel_noise * MAX parRandom.normal_perturb(noise_std_dev, misfit.d) if rank == 0: d_array = misfit.d.get_local() else:
def setUp(self): self.plot_mesh = False self.plot_results = False self.plot_phase_space = False # Turn plots off if there's no display. if os.environ.get('DISPLAY') is None: self.plot_mesh = False self.plot_results = False fncName = '(' + __file__ + ') ' + sys._getframe( ).f_code.co_name + '():\n' # initializations for each test go here... self.ctrl = DTcontrol_C() self.ctrl.title = "test_ParticleTrajectory" self.ctrl.author = "tph" self.ctrl.dt = 1.0e-6 self.ctrl.MAX_FACET_CROSS_COUNT = 100 # Initialize time counters self.ctrl.timeloop_count = 0 self.ctrl.time = 0.0 # This gives a list of species to apply E to. # 'None' value means that the field is applied to ALL species self.ctrl.apply_solved_electric_field = None self.ctrl.write_trajectory_files = True ### Particle species input # Create an instance of the DTparticleInput class pin = ParticleInput_C() # Initialize particles pin.precision = numpy.float64 pin.particle_integration_loop = 'loop-on-particles' pin.coordinate_system = 'cartesian_xy' pin.force_components = [ 'x', 'y', ] pin.force_precision = numpy.float64 pin.use_cpp_integrators = False # Define an electron species called 'trajelectrons'. speciesName = 'trajelectrons' charge = -1.0 * MyPlasmaUnits_C.elem_charge mass = 1.0 * MyPlasmaUnits_C.electron_mass dynamics = 'charged' trajelectrons_S = ParticleSpecies_C(speciesName, charge, mass, dynamics) # Define an electron species called 'test_electrons'. speciesName = 'test_electrons' charge = -1.0 * MyPlasmaUnits_C.elem_charge mass = 1.0 * MyPlasmaUnits_C.electron_mass dynamics = 'charged' test_electrons_S = ParticleSpecies_C(speciesName, charge, mass, dynamics) # Add the electrons to particle input pin.particle_species = ( trajelectrons_S, test_electrons_S, ) ## Make the particle storage array for all species. self.particle_P = Particle_C(pin, print_flag=True) ## Give the name of the .py file containing special particle data (lists of # particles, boundary conditions, source regions, etc.) userParticlesModuleName = "UserParticles_2D_e" # Import this module userParticlesModule = im_m.import_module(userParticlesModuleName) # self.particle_P.user_particles_module_name = userParticlesModuleName self.particle_P.user_particles_class = userParticlesClass = userParticlesModule.UserParticleDistributions_C ### Mesh creation umi = UserMeshInput2DCirc_C() # Make the mesh & fields from saved files umi.mesh_file = 'mesh_quarter_circle_crossed.xml' umi.particle_boundary_file = 'mesh_quarter_circle_crossed_Pbcs.xml' ### Input for initial particles (i.e., particles present at t=0) # A. trajelectrons # Name the species (it should be in species_names above) speciesName = 'trajelectrons' # Check that this species has been defined above if speciesName in self.particle_P.species_names: charge = self.particle_P.charge[speciesName] mass = self.particle_P.mass[speciesName] else: print("The species", speciesName, "has not been defined") sys.exit() initialDistributionType = 'listed' # Check that there's a function listing the particles particles printFlag = True if hasattr(userParticlesClass, speciesName): if printFlag: print(fncName + "DnT INFO: Initial distribution for", speciesName, "is the function of that name in", userParticlesClass) # Write error message and exit if no distribution function exists else: errorMsg = fncName + "(DnT ERROR) Need to define a particle distribution function %s in UserParticle.py for species %s " % ( speciesName, speciesName) sys.exit(errorMsg) # Collect the parameters into a dictionary # The 'listed' type will expect a function with the same name as the species. trajElectronParams = { 'species_name': speciesName, 'initial_distribution_type': initialDistributionType, } # B. test_electrons # Name the species (it should be in species_names above) speciesName = 'test_electrons' # Check that this species has been defined above if speciesName in self.particle_P.species_names: charge = self.particle_P.charge[speciesName] mass = self.particle_P.mass[speciesName] else: print("The species", speciesName, "has not been defined") sys.exit() initialDistributionType = 'listed' # Check that there's a function listing the particles particles printFlag = True if hasattr(userParticlesClass, speciesName): if printFlag: print(fncName + "DnT INFO: Initial distribution for", speciesName, "is the function of that name in", userParticlesClass) # Write error message and exit if no distribution function exists else: errorMsg = fncName + "(DnT ERROR) Need to define a particle distribution function %s in UserParticle.py for species %s " % ( speciesName, speciesName) sys.exit(errorMsg) # Collect the parameters into a dictionary # The 'listed' type will expect a function with the same name as the species. test_electronParams = { 'species_name': speciesName, 'initial_distribution_type': initialDistributionType, } ## Collect the initial particles into a dictionary # The dictionary keys are mnemonics for the initialized particles initialParticlesDict = { 'initial_trajelectrons': (trajElectronParams, ), 'initial_test_electrons': (test_electronParams, ), } # Add the initialized particles to the Particle_C object self.particle_P.initial_particles_dict = initialParticlesDict # Create the particle mesh object # 'crossed' diagonals # self.pmesh2D = Mesh_C(meshFile="quarter_circle_mesh_crossed.xml", computeDictionaries=True, computeTree=True, plotFlag=False) # 'left' diagonal # self.pmesh2D = Mesh_C(meshFile="quarter_circle_mesh_left.xml", computeDictionaries=True, computeTree=True, plotFlag=False) # These are the boundary-name -> int pairs used to mark mesh facets: rminIndx = 1 rmaxIndx = 2 thminIndx = 4 thmaxIndx = 8 particleBoundaryDict = { 'rmin': rminIndx, 'rmax': rmaxIndx, 'thmin': thminIndx, 'thmax': thmaxIndx, } umi.particle_boundary_dict = particleBoundaryDict # Read the mesh from an existing file # pin.pmesh_M = UserMesh_C(meshFile='quarter_circle_mesh_crossed.xml', particleBoundaryFile='Pbcs_quarter_circle_mesh_crossed.xml', computeDictionaries=True, computeTree=True, plotFlag=False) # Can this be attached to Particle_C after Particle_C construction? YES pmesh_M = UserMesh2DCirc_C(umi, compute_dictionaries=True, compute_cpp_arrays=False, compute_tree=True, plot_flag=self.plot_mesh) self.particle_P.pmesh_M = pmesh_M ### Field creation # The following value should correspond to the element degree # used in the potential from which negE was obtained phi_element_degree = 1 if phi_element_degree == 1: # For linear elements, grad(phi) is discontinuous across # elements. To represent this field, we need Discontinuous Galerkin # elements. electric_field_element_type = "DG" else: electric_field_element_type = "Lagrange" ## Create the electric field from a file written by test_FieldSolve.py. # Put the negative electric field directly on the particle mesh self.neg_electric_field = Field_C( pmesh_M, element_type=electric_field_element_type, element_degree=phi_element_degree - 1, field_type='vector') file = df_m.File( "negE2D_crossed-2016.xml" ) # Use a frozen version instead of the one created each time test_FieldSolve.py runs. file >> self.neg_electric_field.function ## Particle boundary-conditions # UserParticleBoundaryFunctions_C is where the facet-crossing callback # functions are defined. # userPBndFnsClass = userParticlesModule.UserParticleBoundaryFunctions_C # LHS is an abbreviation userPBndFns = userParticlesModule.UserParticleBoundaryFunctions_C( self.particle_P.position_coordinates, self.particle_P.dx) # Make the particle-mesh boundary-conditions object and add it # to the particle object. spNames = self.particle_P.species_names # pmeshBCs = ParticleMeshBoundaryConditions_C(spNames, pmesh_M, userPBndFnsClass, print_flag=False) pmeshBCs = ParticleMeshBoundaryConditions_C(spNames, pmesh_M, userPBndFns, print_flag=False) self.particle_P.pmesh_bcs = pmeshBCs ### Create input for a particle trajectory object # Use an input object to collect initialization data for the trajectory object self.trajin = TrajectoryInput_C() self.trajin.maxpoints = None # Set to None to get every point self.trajin.extra_points = 10 # Set to 1 to make sure one boundary-crossing can be # accommodated. Set to a larger value if there are # multiple boundary reflections. 10 is needed for # all the the reflections in test_4. # Specify which particle variables to save. This has the form of a numpy # dtype specification. name_list_base = ['step', 't'] # These are always recorded format_list_base = [int, numpy.float32 ] # Start off the format list with types for # 'step' and 't' charged_attributes = ['x', 'ux', 'y', 'uy', 'crossings', 'Ex', 'Ey'] format_list = format_list_base + [ numpy.float32 for i in range(len(charged_attributes)) ] self.trajin.charged_dict = { 'names': name_list_base + charged_attributes, 'formats': format_list } neutral_attributes = ['x', 'ux', 'y', 'uy'] format_list = format_list_base + [ numpy.float32 for i in range(len(neutral_attributes)) ] self.trajin.neutral_dict = { 'names': name_list_base + neutral_attributes, 'formats': format_list } return