class FactoryTester(unittest.TestCase): def setUp(self): self.factory = Factory() ## Tests the createParametersObject() function without a type parameter def testCreateParametersObjectWithNoTypeParam(self): params = {"gamma" : "1.4", "R" : "200"} self.factory.createParametersObject("IdealGasEoS", params) ## Tests the createParametersObject() function with a type parameter def testCreateParametersObjectWithTypeParam(self): params = {"type" : "IdealGasEoS", "gamma" : "1.4", "R" : "200"} object_class = params["type"] self.factory.createParametersObject(object_class, params) ## Tests the createObject() function def testCreateObject(self): params = {"type" : "IdealGasEoS", "gamma" : "1.4", "R" : "200"} object_class = params["type"] self.factory.createObject(object_class, params) ## Tests the createObjectFromParametersObject() function def testCreateObjectFromParametersObject(self): object_class = "IdealGasEoS" parameters_object = self.factory.createParametersObject(object_class) parameters_object.set("gamma", 1.4) parameters_object.set("R", 200) self.factory.createObjectFromParametersObject(object_class, parameters_object)
def outputPrintDoFVectorToFile(path): # area function def A(x): return 2.0 # create the DoF handler factory = Factory() n_cell = 5 mesh = factory.createObject("UniformMesh", { "name": "mesh", "n_cell": n_cell }) dof_handler = factory.createObject("DoFHandler1Phase", { "meshes": [mesh], "A": A }) # solution vector U = range((n_cell + 1) * 3) # capture the output captor = OutputCaptor() printDoFVector(U, dof_handler) out = captor.getCapturedOutput() # write the output file text_file = open(path + "print_dof_vector.txt", "w") text_file.write(out) text_file.close()
def testJunctionConstraintDoFIndices(self): # create the factory factory = Factory() # create the meshes n_cells_list = [3, 5, 4] meshes = list() for i, n_cells in enumerate(n_cells_list): name = "mesh" + str(i + 1) params = {"name": name, "n_cell": n_cells} meshes.append(factory.createObject("UniformMesh", params)) # area function def A(x): return 2.0 # create the DoF handler params = {"meshes": meshes, "A": A} dof_handler = factory.createObject("DoFHandler1Phase", params) # create an EoS eos_list = [factory.createObject("TestEoS", {})] # create the junctions n_constraints_list = [2, 6, 3] meshes_list = [["mesh1", "mesh2"], ["mesh2", "mesh3"], ["mesh1", "mesh2"]] sides_list = [["right", "left"]] * 3 junctions = list() for i in xrange(3): params = { "mesh_names": meshes_list[i], "mesh_sides": sides_list[i], "dof_handler": dof_handler, "eos_list": eos_list, "n_constraints": n_constraints_list[i] } junctions.append(factory.createObject("TestJunction", params)) # update the DoF handler with the junction constraints dof_handler.updateWithJunctionConstraints(junctions) # check all of the constraint DoF indices are the expected expected_constraint_dof_indices = [[12, 13], [35, 36, 37, 38, 39, 40], [14, 15, 16]] for i, junction in enumerate(junctions): self.assertEqual(junction.i_constraint, expected_constraint_dof_indices[i])
def run(input_file, mods=list()): # parse the input file input_file_parser = InputFileParser() input_file_parser.parse(input_file) # apply modifications to input parameters, if any for mod in mods: input_file_parser.applyModification(mod) # create the factory factory = Factory() # equation of state eos_param_data = input_file_parser.getBlockData("EoS") eos_class = eos_param_data["type"] eos = factory.createObject(eos_class, eos_param_data) # thermodynamic state state_data = input_file_parser.getBlockData("ThermodynamicState") state = factory.createObject("ThermodynamicState", state_data) state.computeRemainingProperties(eos) print state
def checkJacobian(self, bc_name, model_type=ModelType.OnePhase, phase=0, boundary="right", bc_params=dict(), fd_eps=1e-8): self.model_type = model_type self.phase = phase # factory factory = Factory() # mesh params = {"n_cell": 1} meshes = [factory.createObject("UniformMesh", params)] # test node index if boundary == "left": k_test = 0 else: k_test = 1 # area function def A(x): return 2.0 # DoF handler dof_handler_params = {"meshes": meshes, "A": A} if self.model_type == ModelType.OnePhase: dof_handler_class = "DoFHandler1Phase" elif self.model_type == ModelType.TwoPhaseNonInteracting: dof_handler_class = "DoFHandler2PhaseNonInteracting" def vf1_initial(x): return 0.3 dof_handler_params["initial_vf1"] = vf1_initial elif self.model_type == ModelType.TwoPhase: dof_handler_class = "DoFHandler2Phase" dof_handler = factory.createObject(dof_handler_class, dof_handler_params) n_dof = dof_handler.n_dof n_var = dof_handler.n_var # equation of state eos_params = dict() eos_params["gamma"] = 1.4 eos_params["R"] = 2.0 eos_list = [factory.createObject("IdealGasEoS", eos_params)] # BC bc_params["mesh_name"] = meshes[0].name bc_params["boundary"] = boundary bc_params["dof_handler"] = dof_handler bc_params["eos_list"] = eos_list bc_params["phase"] = phase bc = factory.createObject(bc_name, bc_params) # compute base solution U = np.zeros(n_dof) for i in xrange(n_dof): U[i] = i + 1.0 # base calculation r = np.zeros(n_dof) J_hand_coded = np.zeros(shape=(n_dof, n_dof)) bc.applyWeakBC(U, r, J_hand_coded) # finite difference Jacobians rel_diffs = np.zeros(shape=(n_var, n_var)) J_fd = np.zeros(shape=(n_var, n_var)) for var_index_j in xrange(dof_handler.n_var): # solution index to perturb j = dof_handler.i(k_test, var_index_j) # perturb solution U_perturbed = deepcopy(U) U_perturbed[j] += fd_eps # compute finite difference Jacobian r_perturbed = np.zeros(n_dof) J_perturbed = np.zeros(shape=(n_dof, n_dof)) bc.applyWeakBC(U_perturbed, r_perturbed, J_perturbed) for var_index_i in xrange(n_var): # residual index tested i = dof_handler.i(k_test, var_index_i) J_fd[var_index_i][var_index_j] = (r_perturbed[i] - r[i]) / fd_eps rel_diffs[var_index_i][ var_index_j] = computeRelativeDifference( J_hand_coded[i][j], J_fd[var_index_i][var_index_j]) # print results if self.verbose: for var_index_i in xrange(n_var): i = dof_handler.i(k_test, var_index_i) var_i = dof_handler.variable_names[var_index_i] print "\nEquation variable:", var_i for var_index_j in xrange(n_var): j = dof_handler.i(k_test, var_index_j) var_j = dof_handler.variable_names[var_index_j] print "\n Derivative variable:", var_j print " Hand-coded =", J_hand_coded[i][j] print " Finite difference =", J_fd[var_index_i][ var_index_j] print " Rel. difference =", rel_diffs[var_index_i][ var_index_j] # take the absolute value of the relative differences return abs(rel_diffs)
def checkDerivatives(self, kernel_name, model_type, phase, aux_dependencies, aux_gradients=list(), kernel_params=dict(), fd_eps=1e-8): self.model_type = model_type self.phase = phase # factory factory = Factory() # mesh params = {"n_cell": 1} meshes = [factory.createObject("UniformMesh", params)] # area function def A(x): return 2.0 # DoF handler dof_handler_params = {"meshes": meshes, "A": A} if self.model_type == ModelType.OnePhase: dof_handler_class = "DoFHandler1Phase" elif self.model_type == ModelType.TwoPhaseNonInteracting: dof_handler_class = "DoFHandler2PhaseNonInteracting" def vf1_initial(x): return 0.3 dof_handler_params["initial_vf1"] = vf1_initial elif self.model_type == ModelType.TwoPhase: dof_handler_class = "DoFHandler2Phase" dof_handler = factory.createObject(dof_handler_class, dof_handler_params) # quadrature quadrature_params = {} quadrature = factory.createObject("Quadrature", quadrature_params) # FE values fe_values_params = { "quadrature": quadrature, "dof_handler": dof_handler, "meshes": meshes } self.fe_values = factory.createObject("FEValues", fe_values_params) # kernel kernel_params["phase"] = phase kernel_params["dof_handler"] = dof_handler kernel = factory.createObject(kernel_name, kernel_params) # aux aux_list = list() for a, aux_name in enumerate(aux_dependencies): # "vf1" is a special case of aux because its name is also the name of # a solution variable (in 2-phase); therefore one needs to make sure that # it uses its own "identity" aux instead of the generic test aux if aux_name == "vf1": params = {"phase": 0} aux_list.append( factory.createObject("VolumeFractionPhase1", params)) else: params = TestAuxParameters() params.set("var", aux_name) params.set("other_vars", aux_dependencies[aux_name]) coefs = list() for d, dependency in enumerate(aux_dependencies[aux_name]): coefs.append(a + 2.0 + d * 0.5) params.set("coefs", coefs) params.set("b", 1.0) aux_list.append(TestAux(params)) # add the aux derivatives for aux_name in aux_gradients: params = { "aux": aux_name, "variable_names": aux_dependencies[aux_name] } aux_list.append(factory.createObject("AuxGradient", params)) # data data = dict() aux_names = [aux.name for aux in aux_list] der = dof_handler.initializeDerivativeData(aux_names) self.elem = 0 i = 0 j = 1 q = 0 data["grad_A"] = 0.3 data["phi"] = self.fe_values.get_phi() data["grad_phi"] = self.fe_values.get_grad_phi(self.elem) data["JxW"] = self.fe_values.get_JxW(self.elem) # compute base solution U = np.zeros(dof_handler.n_dof) for k in xrange(dof_handler.n_dof): U[k] = k + 1.0 self.computeSolutionDependentData(U, data) for aux in aux_list: aux.compute(data, der) # base calculation r = kernel.computeResidual(data, i)[q] J_hand_coded = dict() for var_index in kernel.var_indices: J_hand_coded[var_index] = kernel.computeJacobian( data, der, var_index, i, j)[q] # finite difference Jacobians rel_diffs = dict() J_fd = dict() for var_index in kernel.var_indices: # perturb solution and recompute aux U_perturbed = deepcopy(U) j_global = dof_handler.i(j, var_index) U_perturbed[j_global] += fd_eps self.computeSolutionDependentData(U_perturbed, data) for aux in aux_list: aux.compute(data, der) # compute finite difference Jacobian r_perturbed = kernel.computeResidual(data, i)[q] J_fd[var_index] = (r_perturbed - r) / fd_eps rel_diffs[var_index] = computeRelativeDifference( J_hand_coded[var_index], J_fd[var_index]) # print results if self.verbose: for var_index in kernel.var_indices: var = dof_handler.variable_names[var_index] print "\nDerivative variable:", var print " Hand-coded =", J_hand_coded[var_index] print " Finite difference =", J_fd[var_index] print " Rel. difference =", rel_diffs[var_index] # take the absolute value of the relative differences for x in rel_diffs: rel_diffs[x] = abs(rel_diffs[x]) return rel_diffs
def checkJacobian(self, test_option, model_type=ModelType.OnePhase, phase=0, junction_params=dict(), fd_eps=1e-8): # factory factory = Factory() # meshes params1 = {"n_cell": 1, "name": "mesh1"} params2 = {"n_cell": 1, "name": "mesh2"} meshes = [ factory.createObject("UniformMesh", params1), factory.createObject("UniformMesh", params2) ] # area function def A(x): return 0.2 # DoF handler dof_handler_params = {"meshes": meshes, "A": A} if model_type == ModelType.OnePhase: dof_handler_class = "DoFHandler1Phase" elif model_type == ModelType.TwoPhaseNonInteracting: dof_handler_class = "DoFHandler2PhaseNonInteracting" def vf1_initial(x): return 0.3 dof_handler_params["initial_vf1"] = vf1_initial elif model_type == ModelType.TwoPhase: dof_handler_class = "DoFHandler2Phase" dof_handler = factory.createObject(dof_handler_class, dof_handler_params) n_dof = dof_handler.n_dof # equation of state eos_params1 = {"slope_initial": 1.0, "slope_increment": 0.1} eos_list = [factory.createObject("TestEoS", eos_params1)] if model_type != ModelType.OnePhase: eos_params2 = {"slope_initial": 1.1, "slope_increment": 0.07} eos_list.append(factory.createObject("TestEoS", eos_params2)) # junction junction_params["mesh_names"] = " ".join( [mesh.name for mesh in meshes]) junction_params["mesh_sides"] = "right left" junction_params["dof_handler"] = dof_handler junction_params["eos_list"] = eos_list junction_parameters = factory.createParametersObject( self.junction_name) for param in junction_params: junction_parameters.set(param, junction_params[param]) if junction_parameters.hasRegisteredParam("phase"): junction_parameters.set("phase", phase) junction = factory.createObjectFromParametersObject( self.junction_name, junction_parameters) # update DoF handler with junction constraints dof_handler.updateWithJunctionConstraints([junction]) # compute base solution U = np.zeros(n_dof) U_old = np.zeros(n_dof) for i in xrange(n_dof): U[i] = i + 1.0 U_old[i] = i + 2.0 # determine evaluation function if test_option == "weak": f = junction.applyWeaklyToNonlinearSystem elif test_option == "strong": f = junction.applyStronglyToNonlinearSystem elif test_option == "both": def f(*args, **kwargs): junction.applyWeaklyToNonlinearSystem(*args, **kwargs) junction.applyStronglyToNonlinearSystem(*args, **kwargs) else: error("Invalid test option") # base calculation r = np.zeros(n_dof) J_hand_coded = np.zeros(shape=(n_dof, n_dof)) f(U, U_old, r, J_hand_coded) # finite difference Jacobians rel_diffs = np.zeros(shape=(n_dof, n_dof)) J_fd = np.zeros(shape=(n_dof, n_dof)) for j in xrange(n_dof): # perturb solution U_perturbed = deepcopy(U) U_perturbed[j] += fd_eps # compute finite difference Jacobian r_perturbed = np.zeros(n_dof) J_perturbed = np.zeros(shape=(n_dof, n_dof)) f(U_perturbed, U_old, r_perturbed, J_perturbed) for i in xrange(n_dof): J_fd[i, j] = (r_perturbed[i] - r[i]) / fd_eps # compute difference matrices abs_diffs = abs(J_hand_coded - J_fd) rel_diffs = computeRelativeDifferenceMatrix(J_hand_coded, J_fd) # print results if self.verbose: print "\nRelative difference of Jacobian for " + test_option + " contributions:" printRelativeMatrixDifference(rel_diffs, abs_diffs, 1e-1, 1e-3) matched = np.zeros((n_dof, n_dof), dtype=bool) for i in xrange(n_dof): for j in xrange(n_dof): matched[i, j] = abs_diffs[i, j] < self.abs_tol or rel_diffs[ i, j] < self.rel_tol return matched
def run(input_file, mods=list()): # parse the input file input_file_parser_original = InputFileParser() input_file_parser_original.parse(input_file) # check if the input file was a differential input file if input_file_parser_original.blockExists("BaseInputFile"): # get the name of the base input file and parse it base_input_file = input_file_parser_original.getBlockData("BaseInputFile")["base"] input_file_parser_base = InputFileParser() input_file_parser_base.parse(base_input_file) # apply modifications to base input file parser input_file_parser_base.applyDifferentialInputFileParser(input_file_parser_original) input_file_parser = input_file_parser_base else: input_file_parser = input_file_parser_original # apply modifications to input parameters, if any for mod in mods: input_file_parser.applyModification(mod) # create the factory factory = Factory() # model model_param_data = input_file_parser.getBlockData("Model") model = factory.createObject("Model", model_param_data) model_type = model.model_type # mesh(es) mesh_subblocks = input_file_parser.getSubblockNames("Mesh") if len(mesh_subblocks) == 0: # single mesh; no subblock is required mesh_param_data = input_file_parser.getBlockData("Mesh") mesh_class = mesh_param_data["type"] mesh = factory.createObject(mesh_class, mesh_param_data) meshes = [mesh] else: # multiple meshes; subblocks are required meshes = list() for mesh_subblock in mesh_subblocks: mesh_param_data = input_file_parser.getSubblockData("Mesh", mesh_subblock) mesh_class = mesh_param_data["type"] mesh_param_data["name"] = mesh_subblock mesh = factory.createObject(mesh_class, mesh_param_data) meshes.append(mesh) # check that no meshes have the same name mesh_names = list() for mesh in meshes: if mesh.name in mesh_names: error("Multiple meshes with the name '" + mesh.name + "'.") else: mesh_names.append(mesh.name) # equations of state eos_subblocks = input_file_parser.getSubblockNames("EoS") if model_type == ModelType.OnePhase: if len(eos_subblocks) != 1: error("Single-phase flow should have exactly 1 equation of state.") else: if len(eos_subblocks) != 2: error("Two-phase flow should have exactly 2 equations of state.") eos_list = list() phase_name_to_index = dict() for k, eos_subblock in enumerate(eos_subblocks): phase_name_to_index[eos_subblock] = k eos_param_data = input_file_parser.getSubblockData("EoS", eos_subblock) eos_class = eos_param_data["type"] eos_list.append(factory.createObject(eos_class, eos_param_data)) # initial conditions / initial guess ic_param_data = input_file_parser.getBlockData("IC") if model_type == ModelType.OnePhase: ics = factory.createObject("InitialConditions1Phase", ic_param_data) else: ics = factory.createObject("InitialConditions2Phase", ic_param_data) # DoF handler dof_handler_params = {"meshes": meshes, "A": ics.A} if model_type == ModelType.OnePhase: dof_handler_class = "DoFHandler1Phase" elif model_type == ModelType.TwoPhaseNonInteracting: dof_handler_class = "DoFHandler2PhaseNonInteracting" dof_handler_params["initial_vf1"] = ics.vf1 elif model_type == ModelType.TwoPhase: dof_handler_class = "DoFHandler2Phase" dof_handler = factory.createObject(dof_handler_class, dof_handler_params) # junctions junctions = list() if input_file_parser.blockExists("Junctions"): junction_subblocks = input_file_parser.getSubblockNames("Junctions") for junction_subblock in junction_subblocks: junction_param_data = input_file_parser.getSubblockData("Junctions", junction_subblock) junction_class = junction_param_data["type"] if "phase" in junction_param_data: junction_param_data["phase"] = phase_name_to_index[junction_param_data["phase"]] junction_param_data["dof_handler"] = dof_handler junction_param_data["eos_list"] = eos_list junction = factory.createObject(junction_class, junction_param_data) junctions.append(junction) # update DoF handler with junction constraints dof_handler.updateWithJunctionConstraints(junctions) # boundary conditions bcs = list() bc_subblocks = input_file_parser.getSubblockNames("BC") for bc_subblock in bc_subblocks: bc_param_data = input_file_parser.getSubblockData("BC", bc_subblock) bc_class = bc_param_data["type"] # if there is only 1 mesh, add the mesh parameter if not supplied already if len(meshes) == 1: if "mesh_name" not in bc_param_data: bc_param_data["mesh_name"] = meshes[0].name if "phase" in bc_param_data: bc_param_data["phase"] = phase_name_to_index[bc_param_data["phase"]] bc_param_data["dof_handler"] = dof_handler bc_param_data["eos_list"] = eos_list bc = factory.createObject(bc_class, bc_param_data) bcs.append(bc) # interface closures if model_type == ModelType.TwoPhase: interface_closures_params = input_file_parser.getBlockData("InterfaceClosures") interface_closures_params["factory"] = factory interface_closures_class = interface_closures_params["type"] interface_closures = factory.createObject(interface_closures_class, interface_closures_params) else: interface_closures = None # gravity physics_param_data = input_file_parser.getBlockData("Physics") physics_params = factory.createParametersObject("Physics", physics_param_data) gravity = physics_params.get("gravity") # nonlinear solver options nonlinear_solver_params = input_file_parser.getBlockData("NonlinearSolver") # stabilization if input_file_parser.blockExists("Stabilization"): stabilization_param_data = input_file_parser.getBlockData("Stabilization") stabilization_param_data["factory"] = factory stabilization_param_data["dof_handler"] = dof_handler stabilization_param_data["model_type"] = model_type stabilization_class = stabilization_param_data["type"] else: stabilization_param_data = {"factory": factory, "dof_handler": dof_handler, "model_type": model_type} stabilization_class = "NoStabilization" stabilization = factory.createObject(stabilization_class, stabilization_param_data) # create and run the executioner executioner_param_data = input_file_parser.getBlockData("Executioner") executioner_type = executioner_param_data["type"] executioner_param_data["model"] = model executioner_param_data["ics"] = ics executioner_param_data["bcs"] = bcs executioner_param_data["junctions"] = junctions executioner_param_data["eos_list"] = eos_list executioner_param_data["interface_closures"] = interface_closures executioner_param_data["gravity"] = gravity executioner_param_data["dof_handler"] = dof_handler executioner_param_data["meshes"] = meshes executioner_param_data["nonlinear_solver_params"] = nonlinear_solver_params executioner_param_data["stabilization"] = stabilization executioner_param_data["factory"] = factory executioner = factory.createObject(executioner_type, executioner_param_data) U = executioner.run() # create and run the output output_param_data = input_file_parser.getBlockData("Output") output_param_data["model"] = model output_param_data["eos_list"] = eos_list output_param_data["dof_handler"] = dof_handler output_param_data["meshes"] = meshes output = factory.createObject("Output", output_param_data) output.run(U)