ansys / pymechanical

Pythonic interface to Ansys Mechanical ™
https://mechanical.docs.pyansys.com/
MIT License
36 stars 18 forks source link

Having problem importing material properties from xml file and heat flux from csv file #291

Closed ambehnam closed 1 year ago

ambehnam commented 1 year ago

Hi there,

I am trying to automate a series of steady state thermal simulations with a same geometry and different heat flux boundary conditions imported from a CSV file. I have created a PyMechanical script attached below. My problem is that I couldn't find out how to import the material .xml file and the heat flux data from CSV file. In workbench I was using the Engineering Data and External Data to import these data, but I don't know how to do it in PyAnsys. The CSV file includes the X,Y,Z coordinates and the heat flux value for each coordinate. Can you please help me add the necessary commands to import these data appropriately.

I have an open Service Request 11421277844 on Ansys Support, but I was directed to GitHub Issues for PyMechanical.

The script is attached below and as a txt file.

Thanks a lot, Amir

# Steady State Thermal analysis

import os

from ansys.mechanical.core import launch_mechanical

geometry_path = "C:\\ANSYS\\Geometry.scdoc"
material_path = "C:\\ANSYS\\Material.xml"     # Don't know how to use it
heat_flux_path = "C:\\ANSYS\\power_map.csv"   # Don't know how to use it

############################################################################### 
# Launch Mechanical
# ~~~~~~~~~~~~~~~~~
# Launch a new Mechanical session in batch, setting ``cleanup_on_exit`` to
# ``False``. To close this Mechanical session when finished, this example
# must call  the ``mechanical.exit()`` method.

mechanical = launch_mechanical(batch=True, cleanup_on_exit=False)
print(mechanical)

###############################################################################
# Initialize variable for workflow
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Set the ``part_file_path`` variable on the server for later use.
# Make this variable compatible for Windows, Linux, and Docker containers.

project_directory = mechanical.project_directory
print(f"project directory = {project_directory}")

# Upload the file to the project directory.
mechanical.upload(file_name=geometry_path, file_location_destination=project_directory)

# Build the path relative to project directory.
base_name = os.path.basename(geometry_path)
combined_path = os.path.join(project_directory, base_name)
part_file_path = combined_path.replace("\\", "\\\\")
mechanical.run_python_script(f"part_file_path='{part_file_path}'")

# Verify the path
result = mechanical.run_python_script("part_file_path")
print(f"part_file_path on server: {result}")

###################################################################################
# Execute the script
# ~~~~~~~~~~~~~~~~~~
# Run the Mechanical script to attach the geometry and set up and solve the
# analysis.

output = mechanical.run_python_script(
    """
import json

# Import Geometry

geometry_import_group_1 = Model.GeometryImportGroup
geometry_import_1 = geometry_import_group_1.AddGeometryImport()

geometry_import_1_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic
geometry_import_1_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences()
geometry_import_1.Import( part_file_path, geometry_import_1_format, geometry_import_1_preferences)

# Import material properties and assign them

      ## How to import material properties from an XML file?
with Transaction(True):
    body_1 = DataModel.GetObjectsByName('SYS\Part1')[0]
    body_1.Material = "Indium"

with Transaction(True):
    body_2 = DataModel.GetObjectsByName('SYS\Part2')[0]
    body_2.Material = "Silicon"

# Define Steady state thermal analysis

Model.AddSteadyStateThermalAnalysis()
ST_STA = Model.Analyses[0]
CS_GRP = Model.CoordinateSystems
ANALYSIS_SETTINGS = ST_STA.Children[0]
SOLN= ST_STA.Solution

ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardMKS
ExtAPI.Application.ActiveAngleUnit = AngleUnitType.Radian

# Model Named Selections

Part2_bot = Model.NamedSelections.Children[0]
Part1_bot = Model.NamedSelections.Children[1]

# Model connections
connections_1 = Model.Connections
connection_group_1 = connections_1.AddConnectionGroup()
connection_group_1.ToleranceType = ContactToleranceType.Value
connection_group_1.ToleranceValue = Quantity(0.001, "mm")

MSH = Model.Mesh
MSH.ElementSize =Quantity("1.0 [mm]")
MSH.GenerateMesh()

# Import heat flux from external data .csv file
    ##### How to import the heat flux data from csv file?

imported_load_1 = ST_STA.AddImportedLoadExternalData()
imported_load_1.GetExternalDataFiles

heat_flux_1 = imported_load_1.AddImportedHeatFlux()
heat_flux_1.Location = Part1_bot
heat_flux_1.ImportLoad()

# Add heat transfer 
convection_1 = ST_STA.AddConvection()
convection_1.Location = Part2_bot
convection_1.FilmCoefficient.Output.SetDiscreteValue(0, Quantity(0.001, "W mm^-1 mm^-1 K^-1"))
convection_1.AmbientTemperature.Output.SetDiscreteValue(0, Quantity(35, "C"))

Temp_1 = ST_STA.Solution().AddTemperature()
ST_STA.Solution.Solve(True)

temperature_details = {
"Minimum": str(Temp_1.Minimum),
"Maximum": str(Temp_1.Maximum),
"Average": str(Temp_1.Average),
}

json.dumps(dir_deformation_details)
"""
)
print(output)

###############################################################################
# Download output file from solve and print contents
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Download the ``solve.out`` file from the server to the current working
# directory and print the contents. Remove the ``solve.out`` file.
def get_solve_out_path(mechanical):
    solve_out_path = ""
    for file_path in mechanical.list_files():
        if file_path.find("solve.out") != -1:
            solve_out_path = file_path
            break

    return solve_out_path

def write_file_contents_to_console(path):
    with open(path, "rt") as file:
        for line in file:
            print(line, end="")

solve_out_path = get_solve_out_path(mechanical)

if solve_out_path != "":
    current_working_directory = os.getcwd()

    local_file_path_list = mechanical.download(solve_out_path, target_dir=current_working_directory)
    solve_out_local_path = local_file_path_list[0]
    print(f"Local solve.out path : {solve_out_local_path}")

    write_file_contents_to_console(solve_out_local_path)

    os.remove(solve_out_local_path)

###########################################################
# Close Mechanical
# ~~~~~~~~~~~~~~~~
# Close the Mechanical instance.

mechanical.exit()

example_01_steady_state_thermal_solve.txt

ambehnam commented 1 year ago

I found the command for importing the material data from Example_06 which are:

MAT = ExtAPI.DataModel.Project.Model.Materials
MAT.Import(mat_Copper_file_path)
MAT.Import(mat_Steel_file_path)

However, when I run this example I get the following error (Ansys 2023R1):

_MultiThreadedRendezvous: <_MultiThreadedRendezvous of RPC that terminated with:
    status = StatusCode.UNKNOWN
    details = "'Materials' object has no attribute 'Import'"
    debug_error_string = "UNKNOWN:Error received from peer  {created_time:"2023-07-07T15:44:16.840381658+00:00", grpc_status:2, grpc_message:"\'Materials\' object has no attribute \'Import\'"}"
koubaa commented 1 year ago

Materials.Import is only supported from Ansys 2023R2 onwards. Prior to that version, we have a workaround. See the file src/ansys/mechanical/core/embedding/shims.py for more information.

ambehnam commented 1 year ago

@koubaa Hi Mohamed. Thanks, I used the jscript as a workaround to import the material until the 23R2 is released. I have another issue that is mentioned in the original post for importing external data. I use the following script and I get an error:

Model.AddSteadyStateThermalAnalysis()
ST_STA = Model.Analyses[0]
imported_load_group_104 = ST_STA.AddImportedLoadExternalData()
external_data_files = Ansys.Mechanical.ExternalData.ExternalDataFileCollection()
external_data_files.SaveFilesWithProject = False
external_data_file_1 = Ansys.Mechanical.ExternalData.ExternalDataFile()
external_data_files.Add(external_data_file_1)
external_data_file_1.Identifier = "File1"
external_data_file_1.Description = ""
external_data_file_1.IsMainFile = True
external_data_file_1.FilePath = r"C:\\Ansys\\CCD_power_map.csv"
external_data_file_1.ImportSettings = Ansys.Mechanical.ExternalData.ImportSettingsFactory.GetSettingsForFormat(MechanicalEnums.ExternalData.ImportFormat.Delimited)
import_settings = external_data_file_1.ImportSettings
import_settings.SkipRows = 0
import_settings.SkipFooter = 0
import_settings.Delimiter = ","
import_settings.AverageCornerNodesToMidsideNodes = "True"
import_settings.UseColumn(1, MechanicalEnums.ExternalData.VariableType.XCoordinate, "mm", "X Coordinate@B")
import_settings.UseColumn(2, MechanicalEnums.ExternalData.VariableType.YCoordinate, "mm", "Y Coordinate@C")
import_settings.UseColumn(3, MechanicalEnums.ExternalData.VariableType.ZCoordinate, "mm", "Z Coordinate@D")
import_settings.UseColumn(4, MechanicalEnums.ExternalData.VariableType.HeatFlux, "W m^-2", "Heat Flux@E")
imported_load_group_104.ImportExternalDataFiles(external_data_files)
imported_heatflux_111 = imported_load_group_104.AddImportedHeatFlux()
imported_heatflux_111.Location = CCDs_NS
imported_heatflux_111.Import()

The error screenshot is attached. Do you know what might be wrong that causes this error? The error is for imported_load_group_104.ImportExternalDataFiles(external_data_files) which is AttributeError:'NoneType' object has no attribute 'ImportExternalDataFile'

mechanical_heatflux
ambehnam commented 1 year ago

Found the issue through Ansys Support. The problem was I was not using the Stand alone version of Mechanical using the following command: 'C:\Program Files\ANSYS Inc\v231\aisol\Bin\winx64\AnsysWBU.exe' -DSApplet -AppModeMech