FEM: reformat codebase

This commit is contained in:
lyphrowny
2024-06-19 14:29:15 +03:00
parent 8675aa87b4
commit 359c1ae2bb
302 changed files with 6702 additions and 9421 deletions

View File

@@ -45,18 +45,16 @@ ANALYSIS_TYPES = ["static"]
def create(doc, name="SolverZ88"):
return femutils.createObject(
doc, name, Proxy, ViewProxy)
return femutils.createObject(doc, name, Proxy, ViewProxy)
class Proxy(solverbase.Proxy):
"""The Fem::FemSolver's Proxy python type, add solver specific properties
"""
"""The Fem::FemSolver's Proxy python type, add solver specific properties"""
Type = "Fem::SolverZ88"
def __init__(self, obj):
super(Proxy, self).__init__(obj)
super().__init__(obj)
obj.Proxy = self
# z88_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Z88")
@@ -67,39 +65,41 @@ class Proxy(solverbase.Proxy):
def createMachine(self, obj, directory, testmode=False):
return run.Machine(
solver=obj, directory=directory,
solver=obj,
directory=directory,
check=tasks.Check(),
prepare=tasks.Prepare(),
solve=tasks.Solve(),
results=tasks.Results(),
testmode=testmode)
testmode=testmode,
)
def editSupported(self):
return True
def edit(self, directory):
pattern = os.path.join(directory, "z88i1.txt")
FreeCAD.Console.PrintMessage("{}\n".format(pattern))
FreeCAD.Console.PrintMessage(f"{pattern}\n")
f = glob.glob(pattern)[0]
FemGui.open(f)
pattern = os.path.join(directory, "z88i2.txt")
FreeCAD.Console.PrintMessage("{}\n".format(pattern))
FreeCAD.Console.PrintMessage(f"{pattern}\n")
f = glob.glob(pattern)[0]
FemGui.open(f)
pattern = os.path.join(directory, "z88i5.txt")
FreeCAD.Console.PrintMessage("{}\n".format(pattern))
FreeCAD.Console.PrintMessage(f"{pattern}\n")
f = glob.glob(pattern)[0]
FemGui.open(f)
pattern = os.path.join(directory, "z88man.txt")
FreeCAD.Console.PrintMessage("{}\n".format(pattern))
FreeCAD.Console.PrintMessage(f"{pattern}\n")
f = glob.glob(pattern)[0]
FemGui.open(f)
pattern = os.path.join(directory, "z88mat.txt")
FreeCAD.Console.PrintMessage("{}\n".format(pattern))
FreeCAD.Console.PrintMessage(f"{pattern}\n")
f = glob.glob(pattern)[0]
FemGui.open(f)
pattern = os.path.join(directory, "z88elp.txt")
FreeCAD.Console.PrintMessage("{}\n".format(pattern))
FreeCAD.Console.PrintMessage(f"{pattern}\n")
f = glob.glob(pattern)[0]
FemGui.open(f)
@@ -112,4 +112,5 @@ class ViewProxy(solverbase.ViewProxy):
def getIcon(self):
return ":/icons/FEM_SolverZ88.svg"
## @}

View File

@@ -76,11 +76,7 @@ class Prepare(run.Prepare):
# write solver input
w = writer.FemInputWriterZ88(
self.analysis,
self.solver,
mesh_obj,
meshdatagetter.member,
self.directory
self.analysis, self.solver, mesh_obj, meshdatagetter.member, self.directory
)
path = w.write_solver_input()
# report to user if task succeeded
@@ -111,7 +107,7 @@ class Solve(run.Solve):
prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Z88")
solver_index = prefs.GetInt("Solver", 0)
solver_name = SOLVER_TYPES[solver_index]
self.pushStatus("Used solver: {}\n".format(solver_name))
self.pushStatus(f"Used solver: {solver_name}\n")
# run solver test mode
# AFAIK: z88r needs to be run twice
@@ -136,14 +132,14 @@ class Solve(run.Solve):
cwd=self.directory,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
startupinfo=femutils.startProgramInfo(state)
startupinfo=femutils.startProgramInfo(state),
)
else:
self._process = subprocess.Popen(
[binary, command, "-" + solver_name],
cwd=self.directory,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
stderr=subprocess.PIPE,
)
self.signalAbort.add(self._process.terminate)
self._process.communicate()
@@ -155,8 +151,7 @@ class Solve(run.Solve):
class Results(run.Results):
def run(self):
prefs = FreeCAD.ParamGet(
"User parameter:BaseApp/Preferences/Mod/Fem/General")
prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/General")
if not prefs.GetBool("KeepResultsOnReRun", False):
self.purge_results()
self.load_results()
@@ -173,18 +168,14 @@ class Results(run.Results):
def load_results(self):
self.pushStatus("Import new results...\n")
# displacements from z88o2 file
disp_result_file = os.path.join(
self.directory, "z88o2.txt")
disp_result_file = os.path.join(self.directory, "z88o2.txt")
if os.path.isfile(disp_result_file):
result_name_prefix = "Z88_" + self.solver.AnalysisType + "_"
importZ88O2Results.import_z88_disp(
disp_result_file, self.analysis, result_name_prefix)
importZ88O2Results.import_z88_disp(disp_result_file, self.analysis, result_name_prefix)
else:
# TODO: use solver framework status message system
FreeCAD.Console.PrintError(
"FEM: No results found at {}!\n"
.format(disp_result_file)
)
FreeCAD.Console.PrintError(f"FEM: No results found at {disp_result_file}!\n")
self.fail()
## @}

View File

@@ -39,21 +39,9 @@ from femmesh import meshtools
class FemInputWriterZ88(writerbase.FemInputWriter):
def __init__(
self,
analysis_obj,
solver_obj,
mesh_obj,
member,
dir_name=None
):
def __init__(self, analysis_obj, solver_obj, mesh_obj, member, dir_name=None):
writerbase.FemInputWriter.__init__(
self,
analysis_obj,
solver_obj,
mesh_obj,
member,
dir_name
self, analysis_obj, solver_obj, mesh_obj, member, dir_name
)
self.file_name = join(self.dir_name, "z88")
@@ -63,18 +51,11 @@ class FemInputWriterZ88(writerbase.FemInputWriter):
timestart = time.process_time()
FreeCAD.Console.PrintMessage("\n") # because of time print in separate line
FreeCAD.Console.PrintMessage("Z88 solver input writing...\n")
FreeCAD.Console.PrintLog(
"FemInputWriterZ88 --> self.dir_name --> {}\n"
.format(self.dir_name)
)
FreeCAD.Console.PrintLog(f"FemInputWriterZ88 --> self.dir_name --> {self.dir_name}\n")
FreeCAD.Console.PrintMessage(
"FemInputWriterZ88 --> self.file_name --> {}\n"
.format(self.file_name)
)
FreeCAD.Console.PrintMessage(
"Write z88 input files to: {}\n"
.format(self.dir_name)
f"FemInputWriterZ88 --> self.file_name --> {self.file_name}\n"
)
FreeCAD.Console.PrintMessage(f"Write z88 input files to: {self.dir_name}\n")
control = self.set_z88_elparam()
if control is False:
return None
@@ -86,12 +67,10 @@ class FemInputWriterZ88(writerbase.FemInputWriter):
self.write_z88_integration_properties()
self.write_z88_memory_parameter()
self.write_z88_solver_parameter()
writing_time_string = (
"Writing time input file: {} seconds"
.format(round((time.process_time() - timestart), 2))
writing_time_string = "Writing time input file: {} seconds".format(
round((time.process_time() - timestart), 2)
)
FreeCAD.Console.PrintMessage(
"{}\n\n".format(writing_time_string))
FreeCAD.Console.PrintMessage(f"{writing_time_string}\n\n")
return self.dir_name
# ********************************************************************************************
@@ -107,14 +86,14 @@ class FemInputWriterZ88(writerbase.FemInputWriter):
param = {4: z8804, 24: z8824, 23: z8823, 17: z8817, 16: z8816, 1: z8801, 10: z8810}
# TODO: test elements 17, 16, 10, INTORD etc
self.z88_element_type = importZ88Mesh.get_z88_element_type(
self.femmesh,
self.femelement_table
self.femmesh, self.femelement_table
)
if self.z88_element_type in param:
self.z88_elparam = param[self.z88_element_type]
else:
FreeCAD.Console.PrintError(
"Element type not supported by Z88. Can not write Z88 solver input.\n")
"Element type not supported by Z88. Can not write Z88 solver input.\n"
)
return False
FreeCAD.Console.PrintMessage(self.z88_elparam)
FreeCAD.Console.PrintMessage("\n")
@@ -130,10 +109,7 @@ class FemInputWriterZ88(writerbase.FemInputWriter):
mesh_file_path = self.file_name + "i1.txt"
f = open(mesh_file_path, "w")
importZ88Mesh.write_z88_mesh_to_file(
self.femnodes_mesh,
self.femelement_table,
self.z88_element_type,
f
self.femnodes_mesh, self.femelement_table, self.z88_element_type, f
)
f.close()
@@ -145,9 +121,9 @@ class FemInputWriterZ88(writerbase.FemInputWriter):
# write nodes to constraints_data (different from writing to file in ccxInpWriter
for femobj in self.member.cons_fixed:
for n in femobj["Nodes"]:
constraints_data.append((n, "{} 1 2 0\n".format(n)))
constraints_data.append((n, "{} 2 2 0\n".format(n)))
constraints_data.append((n, "{} 3 2 0\n".format(n)))
constraints_data.append((n, f"{n} 1 2 0\n"))
constraints_data.append((n, f"{n} 2 2 0\n"))
constraints_data.append((n, f"{n} 3 2 0\n"))
# forces constraints
# write node loads to constraints_data
@@ -159,15 +135,15 @@ class FemInputWriterZ88(writerbase.FemInputWriter):
for n in sorted(ref_shape[1]):
# the loads in ref_shape[1][n] are without unit
node_load = ref_shape[1][n]
if (direction_vec.x != 0.0):
if direction_vec.x != 0.0:
v1 = direction_vec.x * node_load
constraints_data.append((n, "{} 1 1 {}\n".format(n, v1)))
if (direction_vec.y != 0.0):
constraints_data.append((n, f"{n} 1 1 {v1}\n"))
if direction_vec.y != 0.0:
v2 = direction_vec.y * node_load
constraints_data.append((n, "{} 2 1 {}\n".format(n, v2)))
if (direction_vec.z != 0.0):
constraints_data.append((n, f"{n} 2 1 {v2}\n"))
if direction_vec.z != 0.0:
v3 = direction_vec.z * node_load
constraints_data.append((n, "{} 3 1 {}\n".format(n, v3)))
constraints_data.append((n, f"{n} 3 1 {v3}\n"))
# write constraints_data to file
constraints_file_path = self.file_name + "i2.txt"
@@ -193,7 +169,7 @@ class FemInputWriterZ88(writerbase.FemInputWriter):
materials_file_path = self.file_name + "mat.txt"
fms = open(materials_file_path, "w")
fms.write("1\n")
fms.write("1 {} {}".format(self.element_count, material_data_file_name))
fms.write(f"1 {self.element_count} {material_data_file_name}")
fms.write("\n")
fms.close()
material_data_file_path = join(self.dir_name, material_data_file_name)
@@ -201,7 +177,7 @@ class FemInputWriterZ88(writerbase.FemInputWriter):
YM = FreeCAD.Units.Quantity(mat_obj.Material["YoungsModulus"])
YM_in_MPa = YM.getValueAs("MPa")
PR = float(mat_obj.Material["PoissonRatio"])
fmd.write("{0} {1:.3f}".format(YM_in_MPa, PR))
fmd.write(f"{YM_in_MPa} {PR:.3f}")
fmd.write("\n")
fmd.close()
@@ -219,35 +195,24 @@ class FemInputWriterZ88(writerbase.FemInputWriter):
elif beam_obj.SectionType == "Circular":
diameter = beam_obj.CircDiameter.getValueAs("mm").Value
from math import pi
area = 0.25 * pi * diameter * diameter
else:
FreeCAD.Console.PrintError(
"Cross section type {} not supported, "
"cross section area will be 0 in solver input.\n"
.format(beam_obj.SectionType)
"cross section area will be 0 in solver input.\n".format(beam_obj.SectionType)
)
# TODO make the check in prechecks and delete it here
# no extensive errorhandling in writer
# this way the solver will fail and an exception is raised somehow
elements_data.append(
"1 {} {} 0 0 0 0 0 0 "
.format(self.element_count, area)
)
FreeCAD.Console.PrintWarning(
"Be aware, only trusses are supported for edge meshes!\n"
)
elements_data.append(f"1 {self.element_count} {area} 0 0 0 0 0 0 ")
FreeCAD.Console.PrintWarning("Be aware, only trusses are supported for edge meshes!\n")
elif meshtools.is_face_femmesh(self.femmesh):
thick_obj = self.member.geos_shellthickness[0]["Object"]
thickness = thick_obj.Thickness.getValueAs("mm").Value
elements_data.append(
"1 {} {} 0 0 0 0 0 0 "
.format(self.element_count, thickness)
)
elements_data.append(f"1 {self.element_count} {thickness} 0 0 0 0 0 0 ")
elif meshtools.is_solid_femmesh(self.femmesh):
elements_data.append(
"1 {} 0 0 0 0 0 0 0"
.format(self.element_count)
)
elements_data.append(f"1 {self.element_count} 0 0 0 0 0 0 0")
else:
FreeCAD.Console.PrintError("Error!\n")
f = open(element_properties_file_path, "w")
@@ -260,14 +225,14 @@ class FemInputWriterZ88(writerbase.FemInputWriter):
# ********************************************************************************************
def write_z88_integration_properties(self):
integration_data = []
integration_data.append("1 {} {} {}".format(
self.element_count,
self.z88_elparam["INTORD"],
self.z88_elparam["INTOS"]
))
integration_data.append(
"1 {} {} {}".format(
self.element_count, self.z88_elparam["INTORD"], self.z88_elparam["INTOS"]
)
)
integration_properties_file_path = self.file_name + "int.txt"
f = open(integration_properties_file_path, "w")
f.write("{}\n".format(len(integration_data)))
f.write(f"{len(integration_data)}\n")
for i in integration_data:
f.write(i)
f.write("\n")
@@ -297,9 +262,9 @@ class FemInputWriterZ88(writerbase.FemInputWriter):
output = ""
for line in template_array:
if line.find("MAXGS") > -1:
line = " MAXGS {}".format(MaxGS)
line = f" MAXGS {MaxGS}"
if line.find("MAXKOI") > -1:
line = " MAXKOI {}".format(MaxKOI)
line = f" MAXKOI {MaxKOI}"
output += line + "\n"
solver_parameter_file_path = self.file_name + ".dyn"