diff --git a/examples/SS316L.json b/examples/SS316L.json index 6197ddf..bc09703 100644 --- a/examples/SS316L.json +++ b/examples/SS316L.json @@ -129,6 +129,18 @@ "reference": "None", "uncertainty": "None", "print_symbol": "\\alpha" + }, + "interface_response_function": { + "print_name": "Dendrite tip velocity", + "value_laurent_poly": [[0,0],[-0.000517783154178829,1],[0.000231067291419276, 2]], + "dependent_variable_print_name": "Undercooling", + "dependent_variable_print_symbol": "\\Delta T", + "dependent_variable_unit": "K", + "unit": "m/s", + "reference": "W. Tan, Y.C. Shin, Multi-scale modeling of solidification and microstructure development in laser keyhole welding process for austenitic stainless steel, Computational Materials Science 98 (2015) 446-458. DOI: https://doi.org/10.1016/j.commatsci.2014.10.063", + "uncertainty": "None", + "print_symbol": "IRF", + "note": "These values are from a 2nd order polynomial fit with y-intercept of 0.0 (R^2 = 0.995) using data from the Fe-18.5Cr-12.5Ni line in Fig. A2" } }, "note": "This file currently excludes the surface tension, marangoni coefficient, and the vapor pressure due to the need for function representations other than Laurent polynomials." diff --git a/mistlib/core.py b/mistlib/core.py index 03103f3..e8e4531 100644 --- a/mistlib/core.py +++ b/mistlib/core.py @@ -115,6 +115,7 @@ def __init__(self, file=None): "laser_absorption", "solidus_eutectic_temperature", "hall_petch_coefficient", + "interface_response_function", ] self.composition = {} @@ -606,6 +607,40 @@ def write_additivefoam_input( self.write_additivefoam_thermoPath(file=thermo_file) return [transport_file, thermo_file] + def write_exaca_input(self, file="exaca_material_file.json"): + data = {} + eutectic_temp = self.properties["solidus_eutectic_temperature"].value + liquidus_temp = self.properties["liquidus_temperature"].value + data["freezing_range"] = liquidus_temp - eutectic_temp + # Get interface response function as a Laurent polynomial + irf = self.properties["interface_response_function"].value_laurent_poly + irf_dict = {} + for value, order in irf: + irf_dict[order] = value + if len(irf) == 4: + data["function"] = "cubic" + data["coefficients"] = { + "A": irf_dict[3], + "B": irf_dict[2], + "C": irf_dict[1], + "D": irf_dict[0], + } + elif len(irf) == 3: + data["function"] = "quadratic" + data["coefficients"] = { + "A": irf_dict[2], + "B": irf_dict[1], + "C": irf_dict[0], + } + else: + print( + f"interface_response_function must be polynomial of 3rd order or less for ExaCA input file" + ) + raise ValueError + with open(file, "w", encoding="utf-8") as f: + json.dump(data, f, ensure_ascii=False, indent=4) + return file + def write_3dthesis_input(self, file, initial_temperature=None): # 3DThesis/autothesis/Condor assumes at "T_0" initial temperature value. Myna populates this from Peregrine. For now we add a placeholder of -1 unless the user specifies an initial temperature. if initial_temperature == None: diff --git a/tests/unit_tests.py b/tests/unit_tests.py index 910276a..e112dc8 100644 --- a/tests/unit_tests.py +++ b/tests/unit_tests.py @@ -175,6 +175,18 @@ def test_write_adamantine(self): os.path.exists(adamantine_file_path), f"File {file} should exist." ) + def test_write_exaca(self): + path_to_example_data = os.path.join( + os.path.dirname(__file__), "../examples/SS316L.json" + ) + mat = mist.core.MaterialInformation(path_to_example_data) + material_filepath = mat.write_exaca_input() + + # Asserts whether the files actually exist + self.assertTrue( + os.path.exists(material_filepath), f"File {material_filepath} should exist." + ) + def test_write_additivefoam(self): path_to_example_data = os.path.join( os.path.dirname(__file__), "../examples/SS316L.json"