diff --git a/src/Mod/Fem/CMakeLists.txt b/src/Mod/Fem/CMakeLists.txt index 4b1720427a..d6f6ae5261 100755 --- a/src/Mod/Fem/CMakeLists.txt +++ b/src/Mod/Fem/CMakeLists.txt @@ -188,6 +188,18 @@ SET(FemSolverCalculix_SRCS femsolver/calculix/solver.py femsolver/calculix/tasks.py femsolver/calculix/writer.py + femsolver/calculix/con_centrif.py + femsolver/calculix/con_contact.py + femsolver/calculix/con_displacement.py + femsolver/calculix/con_fixed.py + femsolver/calculix/con_force.py + femsolver/calculix/con_heatflux.py + femsolver/calculix/con_planerotation.py + femsolver/calculix/con_pressure.py + femsolver/calculix/con_sectionprint.py + femsolver/calculix/con_temperature.py + femsolver/calculix/con_tie.py + femsolver/calculix/con_transform.py ) SET(FemSolverElmer_SRCS diff --git a/src/Mod/Fem/femsolver/calculix/con_centrif.py b/src/Mod/Fem/femsolver/calculix/con_centrif.py new file mode 100644 index 0000000000..9e9eff93f2 --- /dev/null +++ b/src/Mod/Fem/femsolver/calculix/con_centrif.py @@ -0,0 +1,82 @@ +# *************************************************************************** +# * Copyright (c) 2021 Bernd Hahnebach * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM calculix constraint centrif" +__author__ = "Bernd Hahnebach" +__url__ = "https://www.freecadweb.org" + + +import math +import six + +import FreeCAD + + +def write_element_sets_elements_constraints_centrif(f, femobj, centrif_obj, ccxwriter): + f.write("*ELSET,ELSET={}\n".format(centrif_obj.Name)) + # use six to be sure to be Python 2.7 and 3.x compatible + if isinstance(femobj["FEMElements"], six.string_types): + f.write("{}\n".format(femobj["FEMElements"])) + else: + for e in femobj["FEMElements"]: + f.write("{},\n".format(e)) + + +def constraint_centrif_writer(f, femobj, centrif_obj, ccxwriter): + + # get some data from the centrif_obj + refobj = centrif_obj.RotationAxis[0][0] + subobj = centrif_obj.RotationAxis[0][1][0] + axis = refobj.Shape.getElement(subobj) + + if axis.Curve.TypeId == "Part::GeomLine": + axiscopy = axis.copy() # apply global placement to copy + axiscopy.Placement = refobj.getGlobalPlacement() + direction = axiscopy.Curve.Direction + location = axiscopy.Curve.Location + else: # no line found, set default + # TODO: No test at all in the writer + # they should all be before in prechecks + location = FreeCAD.Vector(0., 0., 0.) + direction = FreeCAD.Vector(0., 0., 1.) + + # write to file + f.write("*DLOAD\n") + # Why {:.13G} ... + # ccx uses F20.0 FORTRAN input fields, see in dload.f in ccx's source + # https://forum.freecadweb.org/viewtopic.php?f=18&t=22759&#p176578 + # example "{:.13G}".format(math.sqrt(2.)*-1e100) and count chars + f.write( + "{},CENTRIF,{:.13G},{:.13G},{:.13G},{:.13G},{:.13G},{:.13G},{:.13G}\n" + .format( + centrif_obj.Name, + (2. * math.pi * float(centrif_obj.RotationFrequency.getValueAs("1/s"))) ** 2, + location.x, + location.y, + location.z, + direction.x, + direction.y, + direction.z + ) + ) + f.write("\n") diff --git a/src/Mod/Fem/femsolver/calculix/con_contact.py b/src/Mod/Fem/femsolver/calculix/con_contact.py new file mode 100644 index 0000000000..45d5030295 --- /dev/null +++ b/src/Mod/Fem/femsolver/calculix/con_contact.py @@ -0,0 +1,56 @@ +# *************************************************************************** +# * Copyright (c) 2021 Bernd Hahnebach * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM calculix constraint contact" +__author__ = "Bernd Hahnebach" +__url__ = "https://www.freecadweb.org" + + +def write_surfacefaces_constraints_contact(f, femobj, contact_obj, ccxwriter): + # slave DEP + f.write("*SURFACE, NAME=DEP{}\n".format(contact_obj.Name)) + for i in femobj["ContactSlaveFaces"]: + f.write("{},S{}\n".format(i[0], i[1])) + # master IND + f.write("*SURFACE, NAME=IND{}\n".format(contact_obj.Name)) + for i in femobj["ContactMasterFaces"]: + f.write("{},S{}\n".format(i[0], i[1])) + + +def constraint_contact_writer(f, femobj, contact_obj, ccxwriter): + f.write( + "*CONTACT PAIR, INTERACTION=INT{},TYPE=SURFACE TO SURFACE\n" + .format(contact_obj.Name) + ) + ind_surf = "IND" + contact_obj.Name + dep_surf = "DEP" + contact_obj.Name + f.write("{},{}\n".format(dep_surf, ind_surf)) + f.write("*SURFACE INTERACTION, NAME=INT{}\n".format(contact_obj.Name)) + f.write("*SURFACE BEHAVIOR,PRESSURE-OVERCLOSURE=LINEAR\n") + slope = contact_obj.Slope + f.write("{} \n".format(slope)) + friction = contact_obj.Friction + if friction > 0: + f.write("*FRICTION \n") + stick = (slope / 10.0) + f.write("{}, {} \n".format(friction, stick)) diff --git a/src/Mod/Fem/femsolver/calculix/con_displacement.py b/src/Mod/Fem/femsolver/calculix/con_displacement.py new file mode 100644 index 0000000000..f5f07972c6 --- /dev/null +++ b/src/Mod/Fem/femsolver/calculix/con_displacement.py @@ -0,0 +1,62 @@ +# *************************************************************************** +# * Copyright (c) 2021 Bernd Hahnebach * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM calculix constraint displacement" +__author__ = "Bernd Hahnebach" +__url__ = "https://www.freecadweb.org" + + +def write_node_sets_nodes_constraints_displacement(f, femobj, disp_obj, ccxwriter): + f.write("*NSET,NSET={}\n".format(disp_obj.Name)) + for n in femobj["Nodes"]: + f.write("{},\n".format(n)) + + +def constraint_displacement_writer(f, femobj, disp_obj, ccxwriter): + f.write("*BOUNDARY\n") + if disp_obj.xFix: + f.write("{},1\n".format(disp_obj.Name)) + elif not disp_obj.xFree: + f.write("{},1,1,{}\n".format(disp_obj.Name, disp_obj.xDisplacement)) + if disp_obj.yFix: + f.write("{},2\n".format(disp_obj.Name)) + elif not disp_obj.yFree: + f.write("{},2,2,{}\n".format(disp_obj.Name, disp_obj.yDisplacement)) + if disp_obj.zFix: + f.write("{},3\n".format(disp_obj.Name)) + elif not disp_obj.zFree: + f.write("{},3,3,{}\n".format(disp_obj.Name, disp_obj.zDisplacement)) + + if ccxwriter.beamsection_objects or ccxwriter.shellthickness_objects: + if disp_obj.rotxFix: + f.write("{},4\n".format(disp_obj.Name)) + elif not disp_obj.rotxFree: + f.write("{},4,4,{}\n".format(disp_obj.Name, disp_obj.xRotation)) + if disp_obj.rotyFix: + f.write("{},5\n".format(disp_obj.Name)) + elif not disp_obj.rotyFree: + f.write("{},5,5,{}\n".format(disp_obj.Name, disp_obj.yRotation)) + if disp_obj.rotzFix: + f.write("{},6\n".format(disp_obj.Name)) + elif not disp_obj.rotzFree: + f.write("{},6,6,{}\n".format(disp_obj.Name, disp_obj.zRotation)) diff --git a/src/Mod/Fem/femsolver/calculix/con_fixed.py b/src/Mod/Fem/femsolver/calculix/con_fixed.py new file mode 100644 index 0000000000..218a62ef5e --- /dev/null +++ b/src/Mod/Fem/femsolver/calculix/con_fixed.py @@ -0,0 +1,73 @@ +# *************************************************************************** +# * Copyright (c) 2021 Bernd Hahnebach * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM calculix constraint fixed" +__author__ = "Bernd Hahnebach" +__url__ = "https://www.freecadweb.org" + + +def write_node_sets_nodes_constraints_fixed(f, femobj, fix_obj, ccxwriter): + if ccxwriter.femmesh.Volumes \ + and (len(ccxwriter.shellthickness_objects) > 0 or len(ccxwriter.beamsection_objects) > 0): + if len(femobj["NodesSolid"]) > 0: + f.write("*NSET,NSET={}Solid\n".format(fix_obj.Name)) + for n in femobj["NodesSolid"]: + f.write("{},\n".format(n)) + if len(femobj["NodesFaceEdge"]) > 0: + f.write("*NSET,NSET={}FaceEdge\n".format(fix_obj.Name)) + for n in femobj["NodesFaceEdge"]: + f.write("{},\n".format(n)) + else: + f.write("*NSET,NSET=" + fix_obj.Name + "\n") + for n in femobj["Nodes"]: + f.write("{},\n".format(n)) + + +def constraint_fixed_writer(f, femobj, fix_obj, ccxwriter): + if ccxwriter.femmesh.Volumes \ + and (len(ccxwriter.shellthickness_objects) > 0 or len(ccxwriter.beamsection_objects) > 0): + if len(femobj["NodesSolid"]) > 0: + f.write("*BOUNDARY\n") + f.write(fix_obj.Name + "Solid" + ",1\n") + f.write(fix_obj.Name + "Solid" + ",2\n") + f.write(fix_obj.Name + "Solid" + ",3\n") + f.write("\n") + if len(femobj["NodesFaceEdge"]) > 0: + f.write("*BOUNDARY\n") + f.write(fix_obj.Name + "FaceEdge" + ",1\n") + f.write(fix_obj.Name + "FaceEdge" + ",2\n") + f.write(fix_obj.Name + "FaceEdge" + ",3\n") + f.write(fix_obj.Name + "FaceEdge" + ",4\n") + f.write(fix_obj.Name + "FaceEdge" + ",5\n") + f.write(fix_obj.Name + "FaceEdge" + ",6\n") + f.write("\n") + else: + f.write("*BOUNDARY\n") + f.write(fix_obj.Name + ",1\n") + f.write(fix_obj.Name + ",2\n") + f.write(fix_obj.Name + ",3\n") + if ccxwriter.beamsection_objects or ccxwriter.shellthickness_objects: + f.write(fix_obj.Name + ",4\n") + f.write(fix_obj.Name + ",5\n") + f.write(fix_obj.Name + ",6\n") + f.write("\n") diff --git a/src/Mod/Fem/femsolver/calculix/con_force.py b/src/Mod/Fem/femsolver/calculix/con_force.py new file mode 100644 index 0000000000..23a7cabc57 --- /dev/null +++ b/src/Mod/Fem/femsolver/calculix/con_force.py @@ -0,0 +1,45 @@ +# *************************************************************************** +# * Copyright (c) 2021 Bernd Hahnebach * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM calculix constraint force" +__author__ = "Bernd Hahnebach" +__url__ = "https://www.freecadweb.org" + + +def write_nodeloads_constraints_force(f, femobj, force_obj, ccxwriter): + direction_vec = femobj["Object"].DirectionVector + for ref_shape in femobj["NodeLoadTable"]: + f.write("** " + ref_shape[0] + "\n") + for n in sorted(ref_shape[1]): + node_load = ref_shape[1][n] + if (direction_vec.x != 0.0): + v1 = "{:.13E}".format(direction_vec.x * node_load) + f.write("{},1,{}\n".format(n, v1)) + if (direction_vec.y != 0.0): + v2 = "{:.13E}".format(direction_vec.y * node_load) + f.write("{},2,{}\n".format(n, v2)) + if (direction_vec.z != 0.0): + v3 = "{:.13E}".format(direction_vec.z * node_load) + f.write("{},3,{}\n".format(n, v3)) + f.write("\n") + f.write("\n") diff --git a/src/Mod/Fem/femsolver/calculix/con_heatflux.py b/src/Mod/Fem/femsolver/calculix/con_heatflux.py new file mode 100644 index 0000000000..20699ba4d4 --- /dev/null +++ b/src/Mod/Fem/femsolver/calculix/con_heatflux.py @@ -0,0 +1,55 @@ +# *************************************************************************** +# * Copyright (c) 2021 Bernd Hahnebach * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM calculix constraint heatflux" +__author__ = "Bernd Hahnebach" +__url__ = "https://www.freecadweb.org" + + +def write_faceheatflux_constraints_heatflux(f, femobj, heatflux_obj, ccxwriter): + if heatflux_obj.ConstraintType == "Convection": + heatflux_key_word = "FILM" + heatflux_facetype = "F" + # SvdW: add factor to force heatflux to units system of t/mm/s/K + heatflux_values = "{},{}".format( + heatflux_obj.AmbientTemp, + heatflux_obj.FilmCoef * 0.001 + ) + elif heatflux_obj.ConstraintType == "DFlux": + heatflux_key_word = "DFLUX" + heatflux_facetype = "S" + heatflux_values = "{}".format(heatflux_obj.DFlux * 0.001) + + f.write("*{}\n".format(heatflux_key_word)) + for ref_shape in femobj["HeatFluxFaceTable"]: + elem_string = ref_shape[0] + face_table = ref_shape[1] + f.write("** Heat flux on face {}\n".format(elem_string)) + for i in face_table: + # OvG: Only write out the VolumeIDs linked to a particular face + f.write("{},{}{},{}\n".format( + i[0], + heatflux_facetype, + i[1], + heatflux_values + )) diff --git a/src/Mod/Fem/femsolver/calculix/con_planerotation.py b/src/Mod/Fem/femsolver/calculix/con_planerotation.py new file mode 100644 index 0000000000..f55b33b9dc --- /dev/null +++ b/src/Mod/Fem/femsolver/calculix/con_planerotation.py @@ -0,0 +1,73 @@ +# *************************************************************************** +# * Copyright (c) 2021 Bernd Hahnebach * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM calculix constraint planerotation" +__author__ = "Bernd Hahnebach" +__url__ = "https://www.freecadweb.org" + + +from femmesh import meshtools + + +def write_node_sets_nodes_constraints_planerotation(f, femobj, fric_obj, ccxwriter): + # write nodes to file + if not ccxwriter.femnodes_mesh: + ccxwriter.femnodes_mesh = ccxwriter.femmesh.Nodes + # info about ccxwriter.constraint_conflict_nodes: + # is used to check if MPC and constraint fixed and + # constraint displacement share same nodes + # because MPC"s and constraints fixed and + # constraints displacement can't share same nodes. + # Thus call write_node_sets_constraints_planerotation has to be + # after constraint fixed and constraint displacement + l_nodes = femobj["Nodes"] + f.write("*NSET,NSET={}\n".format(fric_obj.Name)) + # Code to extract nodes and coordinates on the PlaneRotation support face + nodes_coords = [] + for node in l_nodes: + nodes_coords.append(( + node, + ccxwriter.femnodes_mesh[node].x, + ccxwriter.femnodes_mesh[node].y, + ccxwriter.femnodes_mesh[node].z + )) + node_planerotation = meshtools.get_three_non_colinear_nodes(nodes_coords) + for i in range(len(l_nodes)): + if l_nodes[i] not in node_planerotation: + node_planerotation.append(l_nodes[i]) + MPC_nodes = [] + for i in range(len(node_planerotation)): + cnt = 0 + for j in range(len(ccxwriter.constraint_conflict_nodes)): + if node_planerotation[i] == ccxwriter.constraint_conflict_nodes[j]: + cnt = cnt + 1 + if cnt == 0: + MPC = node_planerotation[i] + MPC_nodes.append(MPC) + for i in range(len(MPC_nodes)): + f.write("{},\n".format(MPC_nodes[i])) + + +def constraint_planerotation_writer(f, femobj, fric_obj, ccxwriter): + f.write("*MPC\n") + f.write("PLANE,{}\n".format(fric_obj.Name)) diff --git a/src/Mod/Fem/femsolver/calculix/con_pressure.py b/src/Mod/Fem/femsolver/calculix/con_pressure.py new file mode 100644 index 0000000000..7ceafce246 --- /dev/null +++ b/src/Mod/Fem/femsolver/calculix/con_pressure.py @@ -0,0 +1,47 @@ +# *************************************************************************** +# * Copyright (c) 2021 Bernd Hahnebach * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM calculix constraint pressure" +__author__ = "Bernd Hahnebach" +__url__ = "https://www.freecadweb.org" + + +def write_faceloads_constraints_pressure(f, femobj, prs_obj, ccxwriter): + rev = -1 if prs_obj.Reversed else 1 + f.write("*DLOAD\n") + for ref_shape in femobj["PressureFaces"]: + # the loop is needed for compatibility reason + # in deprecated method get_pressure_obj_faces_depreciated + # the face ids where per ref_shape + f.write("** " + ref_shape[0] + "\n") + for face, fno in ref_shape[1]: + if fno > 0: # solid mesh face + f.write("{},P{},{}\n".format(face, fno, rev * prs_obj.Pressure)) + # on shell mesh face: fno == 0 + # normal of element face == face normal + elif fno == 0: + f.write("{},P,{}\n".format(face, rev * prs_obj.Pressure)) + # on shell mesh face: fno == -1 + # normal of element face opposite direction face normal + elif fno == -1: + f.write("{},P,{}\n".format(face, -1 * rev * prs_obj.Pressure)) diff --git a/src/Mod/Fem/femsolver/calculix/con_sectionprint.py b/src/Mod/Fem/femsolver/calculix/con_sectionprint.py new file mode 100644 index 0000000000..2a67a8bcb2 --- /dev/null +++ b/src/Mod/Fem/femsolver/calculix/con_sectionprint.py @@ -0,0 +1,40 @@ +# *************************************************************************** +# * Copyright (c) 2021 Bernd Hahnebach * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM calculix constraint sectionprint" +__author__ = "Bernd Hahnebach" +__url__ = "https://www.freecadweb.org" + + +def write_surfacefaces_constraints_sectionprint(f, femobj, sectionprint_obj, ccxwriter): + f.write("*SURFACE, NAME=SECTIONFACE{}\n".format(sectionprint_obj.Name)) + for i in femobj["SectionPrintFaces"]: + f.write("{},S{}\n".format(i[0], i[1])) + + +def constraint_sectionprint_writer(f, femobj, sectionprint_obj, ccxwriter): + f.write( + "*SECTION PRINT, SURFACE=SECTIONFACE{}, NAME=SECTIONPRINT{}\n" + .format(sectionprint_obj.Name, sectionprint_obj.Name) + ) + f.write("SOF, SOM, SOAREA\n") diff --git a/src/Mod/Fem/femsolver/calculix/con_temperature.py b/src/Mod/Fem/femsolver/calculix/con_temperature.py new file mode 100644 index 0000000000..c985deeccd --- /dev/null +++ b/src/Mod/Fem/femsolver/calculix/con_temperature.py @@ -0,0 +1,47 @@ +# *************************************************************************** +# * Copyright (c) 2021 Bernd Hahnebach * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM calculix constraint temperature" +__author__ = "Bernd Hahnebach" +__url__ = "https://www.freecadweb.org" + + +def write_node_sets_nodes_constraints_temperature(f, femobj, temp_obj, ccxwriter): + f.write("*NSET,NSET={}\n".format(temp_obj.Name)) + for n in femobj["Nodes"]: + f.write("{},\n".format(n)) + + +def constraint_temperature_writer(f, femobj, temp_obj, ccxwriter): + NumberOfNodes = len(femobj["Nodes"]) + if temp_obj.ConstraintType == "Temperature": + f.write("*BOUNDARY\n") + f.write("{},11,11,{}\n".format(temp_obj.Name, temp_obj.Temperature)) + f.write("\n") + elif temp_obj.ConstraintType == "CFlux": + f.write("*CFLUX\n") + f.write("{},11,{}\n".format( + temp_obj.Name, + temp_obj.CFlux * 0.001 / NumberOfNodes + )) + f.write("\n") diff --git a/src/Mod/Fem/femsolver/calculix/con_tie.py b/src/Mod/Fem/femsolver/calculix/con_tie.py new file mode 100644 index 0000000000..07c4ffe97b --- /dev/null +++ b/src/Mod/Fem/femsolver/calculix/con_tie.py @@ -0,0 +1,48 @@ +# *************************************************************************** +# * Copyright (c) 2021 Bernd Hahnebach * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM calculix constraint tie" +__author__ = "Bernd Hahnebach" +__url__ = "https://www.freecadweb.org" + + +def write_surfacefaces_constraints_tie(f, femobj, tie_obj, ccxwriter): + # slave DEP + f.write("*SURFACE, NAME=TIE_DEP{}\n".format(tie_obj.Name)) + for i in femobj["TieSlaveFaces"]: + f.write("{},S{}\n".format(i[0], i[1])) + # master IND + f.write("*SURFACE, NAME=TIE_IND{}\n".format(tie_obj.Name)) + for i in femobj["TieMasterFaces"]: + f.write("{},S{}\n".format(i[0], i[1])) + + +def constraint_tie_writer(f, femobj, tie_obj, ccxwriter): + tolerance = str(tie_obj.Tolerance.getValueAs("mm")).rstrip() + f.write( + "*TIE, POSITION TOLERANCE={}, ADJUST=NO, NAME=TIE{}\n" + .format(tolerance, tie_obj.Name) + ) + ind_surf = "TIE_IND{}".format(tie_obj.Name) + dep_surf = "TIE_DEP{}".format(tie_obj.Name) + f.write("{},{}\n".format(dep_surf, ind_surf)) diff --git a/src/Mod/Fem/femsolver/calculix/con_transform.py b/src/Mod/Fem/femsolver/calculix/con_transform.py new file mode 100644 index 0000000000..8fb348fffb --- /dev/null +++ b/src/Mod/Fem/femsolver/calculix/con_transform.py @@ -0,0 +1,64 @@ +# *************************************************************************** +# * Copyright (c) 2021 Bernd Hahnebach * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM calculix constraint transform" +__author__ = "Bernd Hahnebach" +__url__ = "https://www.freecadweb.org" + + +from femtools import geomtools + + +def write_node_sets_nodes_constraints_transform(f, femobj, trans_obj, ccxwriter): + if trans_obj.TransformType == "Rectangular": + f.write("*NSET,NSET=Rect{}\n".format(trans_obj.Name)) + elif trans_obj.TransformType == "Cylindrical": + f.write("*NSET,NSET=Cylin{}\n".format(trans_obj.Name)) + for n in femobj["Nodes"]: + f.write("{},\n".format(n)) + + +def constraint_transform_writer(f, femobj, trans_obj, ccxwriter): + trans_name = "" + trans_type = "" + if trans_obj.TransformType == "Rectangular": + trans_name = "Rect" + trans_type = "R" + coords = geomtools.get_rectangular_coords(trans_obj) + elif trans_obj.TransformType == "Cylindrical": + trans_name = "Cylin" + trans_type = "C" + coords = geomtools.get_cylindrical_coords(trans_obj) + f.write("*TRANSFORM, NSET={}{}, TYPE={}\n".format( + trans_name, + trans_obj.Name, + trans_type, + )) + f.write("{:f},{:f},{:f},{:f},{:f},{:f}\n".format( + coords[0], + coords[1], + coords[2], + coords[3], + coords[4], + coords[5], + )) diff --git a/src/Mod/Fem/femsolver/calculix/writer.py b/src/Mod/Fem/femsolver/calculix/writer.py index c65c2d6d20..9e00868761 100644 --- a/src/Mod/Fem/femsolver/calculix/writer.py +++ b/src/Mod/Fem/femsolver/calculix/writer.py @@ -31,7 +31,6 @@ __url__ = "https://www.freecadweb.org" # import io import codecs -import math import os import six import sys @@ -44,7 +43,6 @@ from FreeCAD import Units from .. import writerbase from femmesh import meshtools from femtools import constants -from femtools import geomtools # Interesting forum topic: https://forum.freecadweb.org/viewtopic.php?&t=48451 @@ -265,7 +263,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter): # femobj --> dict, FreeCAD document object is femobj["Object"] the_obj = femobj["Object"] f.write("** {}\n".format(the_obj.Label)) - sets_writer_method(the_file, femobj, the_obj) + sets_writer_method(the_file, femobj, the_obj, self) if write_after != "": f.write(write_after) @@ -322,428 +320,211 @@ class FemInputWriterCcx(writerbase.FemInputWriter): # femobj --> dict, FreeCAD document object is femobj["Object"] the_obj = femobj["Object"] f.write("** {}\n".format(the_obj.Label)) - constraint_writer_method(f, femobj, the_obj) + constraint_writer_method(f, femobj, the_obj, self) if write_after != "": f.write(write_after) # ******************************************************************************************** # constraints fixed def write_node_sets_constraints_fixed(self, f): + from .con_fixed import write_node_sets_nodes_constraints_fixed self.write_constraints_sets( f, femobjs=self.fixed_objects, analysis_types="all", # write for all analysis types sets_getter_method=self.get_constraints_fixed_nodes, write_name="constraints_fixed_node_sets", - sets_writer_method=self.write_node_sets_nodes_constraints_fixed, + sets_writer_method=write_node_sets_nodes_constraints_fixed, caller_method_name=sys._getframe().f_code.co_name, ) def write_constraints_fixed(self, f): + from .con_fixed import constraint_fixed_writer self.write_constraints_data( f, femobjs=self.fixed_objects, analysis_types="all", # write for all analysis types constraint_title_name="Fixed Constraints", - constraint_writer_method=self.constraint_fixed_writer, + constraint_writer_method=constraint_fixed_writer, caller_method_name=sys._getframe().f_code.co_name, ) - def write_node_sets_nodes_constraints_fixed(self, f, femobj, fix_obj): - if self.femmesh.Volumes \ - and (len(self.shellthickness_objects) > 0 or len(self.beamsection_objects) > 0): - if len(femobj["NodesSolid"]) > 0: - f.write("*NSET,NSET={}Solid\n".format(fix_obj.Name)) - for n in femobj["NodesSolid"]: - f.write("{},\n".format(n)) - if len(femobj["NodesFaceEdge"]) > 0: - f.write("*NSET,NSET={}FaceEdge\n".format(fix_obj.Name)) - for n in femobj["NodesFaceEdge"]: - f.write("{},\n".format(n)) - else: - f.write("*NSET,NSET=" + fix_obj.Name + "\n") - for n in femobj["Nodes"]: - f.write("{},\n".format(n)) - - def constraint_fixed_writer(self, f, femobj, fix_obj): - if self.femmesh.Volumes \ - and (len(self.shellthickness_objects) > 0 or len(self.beamsection_objects) > 0): - if len(femobj["NodesSolid"]) > 0: - f.write("*BOUNDARY\n") - f.write(fix_obj.Name + "Solid" + ",1\n") - f.write(fix_obj.Name + "Solid" + ",2\n") - f.write(fix_obj.Name + "Solid" + ",3\n") - f.write("\n") - if len(femobj["NodesFaceEdge"]) > 0: - f.write("*BOUNDARY\n") - f.write(fix_obj.Name + "FaceEdge" + ",1\n") - f.write(fix_obj.Name + "FaceEdge" + ",2\n") - f.write(fix_obj.Name + "FaceEdge" + ",3\n") - f.write(fix_obj.Name + "FaceEdge" + ",4\n") - f.write(fix_obj.Name + "FaceEdge" + ",5\n") - f.write(fix_obj.Name + "FaceEdge" + ",6\n") - f.write("\n") - else: - f.write("*BOUNDARY\n") - f.write(fix_obj.Name + ",1\n") - f.write(fix_obj.Name + ",2\n") - f.write(fix_obj.Name + ",3\n") - if self.beamsection_objects or self.shellthickness_objects: - f.write(fix_obj.Name + ",4\n") - f.write(fix_obj.Name + ",5\n") - f.write(fix_obj.Name + ",6\n") - f.write("\n") - # ******************************************************************************************** # constraints displacement def write_node_sets_constraints_displacement(self, f): + from .con_displacement import write_node_sets_nodes_constraints_displacement self.write_constraints_sets( f, femobjs=self.displacement_objects, analysis_types="all", # write for all analysis types sets_getter_method=self.get_constraints_displacement_nodes, write_name="constraints_displacement_node_sets", - sets_writer_method=self.write_node_sets_nodes_constraints_displacement, + sets_writer_method=write_node_sets_nodes_constraints_displacement, caller_method_name=sys._getframe().f_code.co_name, ) def write_constraints_displacement(self, f): + from .con_displacement import constraint_displacement_writer self.write_constraints_data( f, femobjs=self.displacement_objects, analysis_types="all", # write for all analysis types constraint_title_name="Displacement constraint applied", - constraint_writer_method=self.constraint_displacement_writer, + constraint_writer_method=constraint_displacement_writer, caller_method_name=sys._getframe().f_code.co_name, write_after="\n", ) - def write_node_sets_nodes_constraints_displacement(self, f, femobj, disp_obj): - f.write("*NSET,NSET={}\n".format(disp_obj.Name)) - for n in femobj["Nodes"]: - f.write("{},\n".format(n)) - - def constraint_displacement_writer(self, f, femobj, disp_obj): - f.write("*BOUNDARY\n") - if disp_obj.xFix: - f.write("{},1\n".format(disp_obj.Name)) - elif not disp_obj.xFree: - f.write("{},1,1,{}\n".format(disp_obj.Name, disp_obj.xDisplacement)) - if disp_obj.yFix: - f.write("{},2\n".format(disp_obj.Name)) - elif not disp_obj.yFree: - f.write("{},2,2,{}\n".format(disp_obj.Name, disp_obj.yDisplacement)) - if disp_obj.zFix: - f.write("{},3\n".format(disp_obj.Name)) - elif not disp_obj.zFree: - f.write("{},3,3,{}\n".format(disp_obj.Name, disp_obj.zDisplacement)) - - if self.beamsection_objects or self.shellthickness_objects: - if disp_obj.rotxFix: - f.write("{},4\n".format(disp_obj.Name)) - elif not disp_obj.rotxFree: - f.write("{},4,4,{}\n".format(disp_obj.Name, disp_obj.xRotation)) - if disp_obj.rotyFix: - f.write("{},5\n".format(disp_obj.Name)) - elif not disp_obj.rotyFree: - f.write("{},5,5,{}\n".format(disp_obj.Name, disp_obj.yRotation)) - if disp_obj.rotzFix: - f.write("{},6\n".format(disp_obj.Name)) - elif not disp_obj.rotzFree: - f.write("{},6,6,{}\n".format(disp_obj.Name, disp_obj.zRotation)) - # ******************************************************************************************** # constraints planerotation def write_node_sets_constraints_planerotation(self, f): + from .con_planerotation import write_node_sets_nodes_constraints_planerotation self.write_constraints_sets( f, femobjs=self.planerotation_objects, analysis_types="all", # write for all analysis types sets_getter_method=self.get_constraints_planerotation_nodes, write_name="constraints_planerotation_node_sets", - sets_writer_method=self.write_node_sets_nodes_constraints_planerotation, + sets_writer_method=write_node_sets_nodes_constraints_planerotation, caller_method_name=sys._getframe().f_code.co_name, ) def write_constraints_planerotation(self, f): + from .con_planerotation import constraint_planerotation_writer self.write_constraints_data( f, femobjs=self.planerotation_objects, analysis_types="all", # write for all analysis types constraint_title_name="PlaneRotation Constraints", - constraint_writer_method=self.constraint_planerotation_writer, + constraint_writer_method=constraint_planerotation_writer, caller_method_name=sys._getframe().f_code.co_name, ) - def write_node_sets_nodes_constraints_planerotation(self, f, femobj, fric_obj): - # write nodes to file - if not self.femnodes_mesh: - self.femnodes_mesh = self.femmesh.Nodes - # info about self.constraint_conflict_nodes: - # is used to check if MPC and constraint fixed and - # constraint displacement share same nodes - # because MPC"s and constraints fixed and - # constraints displacement can't share same nodes. - # Thus call write_node_sets_constraints_planerotation has to be - # after constraint fixed and constraint displacement - l_nodes = femobj["Nodes"] - f.write("*NSET,NSET={}\n".format(fric_obj.Name)) - # Code to extract nodes and coordinates on the PlaneRotation support face - nodes_coords = [] - for node in l_nodes: - nodes_coords.append(( - node, - self.femnodes_mesh[node].x, - self.femnodes_mesh[node].y, - self.femnodes_mesh[node].z - )) - node_planerotation = meshtools.get_three_non_colinear_nodes(nodes_coords) - for i in range(len(l_nodes)): - if l_nodes[i] not in node_planerotation: - node_planerotation.append(l_nodes[i]) - MPC_nodes = [] - for i in range(len(node_planerotation)): - cnt = 0 - for j in range(len(self.constraint_conflict_nodes)): - if node_planerotation[i] == self.constraint_conflict_nodes[j]: - cnt = cnt + 1 - if cnt == 0: - MPC = node_planerotation[i] - MPC_nodes.append(MPC) - for i in range(len(MPC_nodes)): - f.write("{},\n".format(MPC_nodes[i])) - - def constraint_planerotation_writer(self, f, femobj, fric_obj): - f.write("*MPC\n") - f.write("PLANE,{}\n".format(fric_obj.Name)) - # ******************************************************************************************** # constraints contact def write_surfaces_constraints_contact(self, f): + from .con_contact import write_surfacefaces_constraints_contact self.write_constraints_sets( f, femobjs=self.contact_objects, analysis_types="all", # write for all analysis types sets_getter_method=self.get_constraints_contact_faces, write_name="constraints_contact_surface_sets", - sets_writer_method=self.write_surfacefaces_constraints_contact, + sets_writer_method=write_surfacefaces_constraints_contact, caller_method_name=sys._getframe().f_code.co_name, ) def write_constraints_contact(self, f): + from .con_contact import constraint_contact_writer self.write_constraints_data( f, femobjs=self.contact_objects, analysis_types="all", # write for all analysis types constraint_title_name="Contact Constraints", - constraint_writer_method=self.constraint_contact_writer, + constraint_writer_method=constraint_contact_writer, caller_method_name=sys._getframe().f_code.co_name, ) - def write_surfacefaces_constraints_contact(self, f, femobj, contact_obj): - # slave DEP - f.write("*SURFACE, NAME=DEP{}\n".format(contact_obj.Name)) - for i in femobj["ContactSlaveFaces"]: - f.write("{},S{}\n".format(i[0], i[1])) - # master IND - f.write("*SURFACE, NAME=IND{}\n".format(contact_obj.Name)) - for i in femobj["ContactMasterFaces"]: - f.write("{},S{}\n".format(i[0], i[1])) - - def constraint_contact_writer(self, f, femobj, contact_obj): - f.write( - "*CONTACT PAIR, INTERACTION=INT{},TYPE=SURFACE TO SURFACE\n" - .format(contact_obj.Name) - ) - ind_surf = "IND" + contact_obj.Name - dep_surf = "DEP" + contact_obj.Name - f.write("{},{}\n".format(dep_surf, ind_surf)) - f.write("*SURFACE INTERACTION, NAME=INT{}\n".format(contact_obj.Name)) - f.write("*SURFACE BEHAVIOR,PRESSURE-OVERCLOSURE=LINEAR\n") - slope = contact_obj.Slope - f.write("{} \n".format(slope)) - friction = contact_obj.Friction - if friction > 0: - f.write("*FRICTION \n") - stick = (slope / 10.0) - f.write("{}, {} \n".format(friction, stick)) - # ******************************************************************************************** # constraints tie def write_surfaces_constraints_tie(self, f): + from .con_tie import write_surfacefaces_constraints_tie self.write_constraints_sets( f, femobjs=self.tie_objects, analysis_types="all", # write for all analysis types sets_getter_method=self.get_constraints_tie_faces, write_name="constraints_tie_surface_sets", - sets_writer_method=self.write_surfacefaces_constraints_tie, + sets_writer_method=write_surfacefaces_constraints_tie, caller_method_name=sys._getframe().f_code.co_name, ) def write_constraints_tie(self, f): + from .con_tie import constraint_tie_writer self.write_constraints_data( f, femobjs=self.tie_objects, analysis_types="all", # write for all analysis types constraint_title_name="Tie Constraints", - constraint_writer_method=self.constraint_tie_writer, + constraint_writer_method=constraint_tie_writer, caller_method_name=sys._getframe().f_code.co_name, ) - def write_surfacefaces_constraints_tie(self, f, femobj, tie_obj): - # slave DEP - f.write("*SURFACE, NAME=TIE_DEP{}\n".format(tie_obj.Name)) - for i in femobj["TieSlaveFaces"]: - f.write("{},S{}\n".format(i[0], i[1])) - # master IND - f.write("*SURFACE, NAME=TIE_IND{}\n".format(tie_obj.Name)) - for i in femobj["TieMasterFaces"]: - f.write("{},S{}\n".format(i[0], i[1])) - - def constraint_tie_writer(self, f, femobj, tie_obj): - tolerance = str(tie_obj.Tolerance.getValueAs("mm")).rstrip() - f.write( - "*TIE, POSITION TOLERANCE={}, ADJUST=NO, NAME=TIE{}\n" - .format(tolerance, tie_obj.Name) - ) - ind_surf = "TIE_IND{}".format(tie_obj.Name) - dep_surf = "TIE_DEP{}".format(tie_obj.Name) - f.write("{},{}\n".format(dep_surf, ind_surf)) - # ******************************************************************************************** # constraints sectionprint def write_surfaces_constraints_sectionprint(self, f): + from .con_sectionprint import write_surfacefaces_constraints_sectionprint self.write_constraints_sets( f, femobjs=self.sectionprint_objects, analysis_types="all", # write for all analysis types sets_getter_method=self.get_constraints_sectionprint_faces, write_name="constraints_sectionprint_surface_sets", - sets_writer_method=self.write_surfacefaces_constraints_sectionprint, + sets_writer_method=write_surfacefaces_constraints_sectionprint, caller_method_name=sys._getframe().f_code.co_name, ) def write_constraints_sectionprint(self, f): + from .con_sectionprint import constraint_sectionprint_writer self.write_constraints_data( f, femobjs=self.sectionprint_objects, analysis_types="all", # write for all analysis types constraint_title_name="SectionPrint Constraints", - constraint_writer_method=self.constraint_sectionprint_writer, + constraint_writer_method=constraint_sectionprint_writer, caller_method_name=sys._getframe().f_code.co_name, ) - def write_surfacefaces_constraints_sectionprint(self, f, femobj, sectionprint_obj): - f.write("*SURFACE, NAME=SECTIONFACE{}\n".format(sectionprint_obj.Name)) - for i in femobj["SectionPrintFaces"]: - f.write("{},S{}\n".format(i[0], i[1])) - - def constraint_sectionprint_writer(self, f, femobj, sectionprint_obj): - f.write( - "*SECTION PRINT, SURFACE=SECTIONFACE{}, NAME=SECTIONPRINT{}\n" - .format(sectionprint_obj.Name, sectionprint_obj.Name) - ) - f.write("SOF, SOM, SOAREA\n") - # ******************************************************************************************** # constraints transform def write_node_sets_constraints_transform(self, f): + from .con_transform import write_node_sets_nodes_constraints_transform self.write_constraints_sets( f, femobjs=self.transform_objects, analysis_types="all", # write for all analysis types sets_getter_method=self.get_constraints_transform_nodes, write_name="constraints_transform_node_sets", - sets_writer_method=self.write_node_sets_nodes_constraints_transform, + sets_writer_method=write_node_sets_nodes_constraints_transform, caller_method_name=sys._getframe().f_code.co_name, ) def write_constraints_transform(self, f): + from .con_transform import constraint_transform_writer self.write_constraints_data( f, femobjs=self.transform_objects, analysis_types="all", # write for all analysis types constraint_title_name="Transform Constraints", - constraint_writer_method=self.constraint_transform_writer, + constraint_writer_method=constraint_transform_writer, caller_method_name=sys._getframe().f_code.co_name, ) - def write_node_sets_nodes_constraints_transform(self, f, femobj, trans_obj): - if trans_obj.TransformType == "Rectangular": - f.write("*NSET,NSET=Rect{}\n".format(trans_obj.Name)) - elif trans_obj.TransformType == "Cylindrical": - f.write("*NSET,NSET=Cylin{}\n".format(trans_obj.Name)) - for n in femobj["Nodes"]: - f.write("{},\n".format(n)) - - def constraint_transform_writer(self, f, femobj, trans_obj): - trans_name = "" - trans_type = "" - if trans_obj.TransformType == "Rectangular": - trans_name = "Rect" - trans_type = "R" - coords = geomtools.get_rectangular_coords(trans_obj) - elif trans_obj.TransformType == "Cylindrical": - trans_name = "Cylin" - trans_type = "C" - coords = geomtools.get_cylindrical_coords(trans_obj) - f.write("*TRANSFORM, NSET={}{}, TYPE={}\n".format( - trans_name, - trans_obj.Name, - trans_type, - )) - f.write("{:f},{:f},{:f},{:f},{:f},{:f}\n".format( - coords[0], - coords[1], - coords[2], - coords[3], - coords[4], - coords[5], - )) - # ******************************************************************************************** # constraints temperature def write_node_sets_constraints_temperature(self, f): + from .con_temperature import write_node_sets_nodes_constraints_temperature self.write_constraints_sets( f, femobjs=self.temperature_objects, analysis_types=["thermomech"], sets_getter_method=self.get_constraints_temperature_nodes, write_name="constraints_temperature_node_sets", - sets_writer_method=self.write_node_sets_nodes_constraints_temperature, + sets_writer_method=write_node_sets_nodes_constraints_temperature, caller_method_name=sys._getframe().f_code.co_name, ) def write_constraints_temperature(self, f): + from .con_temperature import constraint_temperature_writer self.write_constraints_data( f, femobjs=self.temperature_objects, analysis_types=["thermomech"], constraint_title_name="Fixed temperature constraint applied", - constraint_writer_method=self.constraint_temperature_writer, + constraint_writer_method=constraint_temperature_writer, caller_method_name=sys._getframe().f_code.co_name, ) - def write_node_sets_nodes_constraints_temperature(self, f, femobj, temp_obj): - f.write("*NSET,NSET={}\n".format(temp_obj.Name)) - for n in femobj["Nodes"]: - f.write("{},\n".format(n)) - - def constraint_temperature_writer(self, f, femobj, temp_obj): - NumberOfNodes = len(femobj["Nodes"]) - if temp_obj.ConstraintType == "Temperature": - f.write("*BOUNDARY\n") - f.write("{},11,11,{}\n".format(temp_obj.Name, temp_obj.Temperature)) - f.write("\n") - elif temp_obj.ConstraintType == "CFlux": - f.write("*CFLUX\n") - f.write("{},11,{}\n".format( - temp_obj.Name, - temp_obj.CFlux * 0.001 / NumberOfNodes - )) - f.write("\n") - # ******************************************************************************************** # constraints initialtemperature def write_constraints_initialtemperature(self, f): @@ -799,180 +580,71 @@ class FemInputWriterCcx(writerbase.FemInputWriter): # ******************************************************************************************** # constraints centrif def write_element_sets_constraints_centrif(self, f): + from .con_centrif import write_element_sets_elements_constraints_centrif self.write_constraints_sets( f, femobjs=self.centrif_objects, analysis_types=["buckling", "static", "thermomech"], sets_getter_method=self.get_constraints_centrif_elements, write_name="constraints_centrif_element_sets", - sets_writer_method=self.write_element_sets_elements_constraints_centrif, + sets_writer_method=write_element_sets_elements_constraints_centrif, caller_method_name=sys._getframe().f_code.co_name, ) def write_constraints_centrif(self, f): + from .con_centrif import constraint_centrif_writer self.write_constraints_data( f, femobjs=self.centrif_objects, analysis_types="all", # write for all analysis types constraint_title_name="Centrif Constraints", - constraint_writer_method=self.constraint_centrif_writer, + constraint_writer_method=constraint_centrif_writer, caller_method_name=sys._getframe().f_code.co_name, ) - def write_element_sets_elements_constraints_centrif(self, f, femobj, centrif_obj): - f.write("*ELSET,ELSET={}\n".format(centrif_obj.Name)) - # use six to be sure to be Python 2.7 and 3.x compatible - if isinstance(femobj["FEMElements"], six.string_types): - f.write("{}\n".format(femobj["FEMElements"])) - else: - for e in femobj["FEMElements"]: - f.write("{},\n".format(e)) - - def constraint_centrif_writer(self, f, femobj, centrif_obj): - - # get some data from the centrif_obj - refobj = centrif_obj.RotationAxis[0][0] - subobj = centrif_obj.RotationAxis[0][1][0] - axis = refobj.Shape.getElement(subobj) - - if axis.Curve.TypeId == "Part::GeomLine": - axiscopy = axis.copy() # apply global placement to copy - axiscopy.Placement = refobj.getGlobalPlacement() - direction = axiscopy.Curve.Direction - location = axiscopy.Curve.Location - else: # no line found, set default - # TODO: No test at all in the writer - # they should all be before in prechecks - location = FreeCAD.Vector(0., 0., 0.) - direction = FreeCAD.Vector(0., 0., 1.) - - # write to file - f.write("*DLOAD\n") - # Why {:.13G} ... - # ccx uses F20.0 FORTRAN input fields, see in dload.f in ccx's source - # https://forum.freecadweb.org/viewtopic.php?f=18&t=22759&#p176578 - # example "{:.13G}".format(math.sqrt(2.)*-1e100) and count chars - f.write( - "{},CENTRIF,{:.13G},{:.13G},{:.13G},{:.13G},{:.13G},{:.13G},{:.13G}\n" - .format( - centrif_obj.Name, - (2. * math.pi * float(centrif_obj.RotationFrequency.getValueAs("1/s"))) ** 2, - location.x, - location.y, - location.z, - direction.x, - direction.y, - direction.z - ) - ) - f.write("\n") - # ******************************************************************************************** # constraints force def write_constraints_force(self, f): + from .con_force import write_nodeloads_constraints_force self.write_constraints_sets( f, femobjs=self.force_objects, analysis_types=["buckling", "static", "thermomech"], sets_getter_method=self.get_constraints_force_nodeloads, write_name="constraints_force_node_loads", - sets_writer_method=self.write_nodeloads_constraints_force, + sets_writer_method=write_nodeloads_constraints_force, caller_method_name=sys._getframe().f_code.co_name, write_before="*CLOAD\n" ) - def write_nodeloads_constraints_force(self, f, femobj, force_obj): - direction_vec = femobj["Object"].DirectionVector - for ref_shape in femobj["NodeLoadTable"]: - f.write("** " + ref_shape[0] + "\n") - for n in sorted(ref_shape[1]): - node_load = ref_shape[1][n] - if (direction_vec.x != 0.0): - v1 = "{:.13E}".format(direction_vec.x * node_load) - f.write("{},1,{}\n".format(n, v1)) - if (direction_vec.y != 0.0): - v2 = "{:.13E}".format(direction_vec.y * node_load) - f.write("{},2,{}\n".format(n, v2)) - if (direction_vec.z != 0.0): - v3 = "{:.13E}".format(direction_vec.z * node_load) - f.write("{},3,{}\n".format(n, v3)) - f.write("\n") - f.write("\n") - # ******************************************************************************************** # constraints pressure def write_constraints_pressure(self, f): + from .con_pressure import write_faceloads_constraints_pressure self.write_constraints_sets( f, femobjs=self.pressure_objects, analysis_types=["buckling", "static", "thermomech"], sets_getter_method=self.get_constraints_pressure_faces, write_name="constraints_pressure_element_face_loads", - sets_writer_method=self.write_faceloads_constraints_pressure, + sets_writer_method=write_faceloads_constraints_pressure, caller_method_name=sys._getframe().f_code.co_name, ) - def write_faceloads_constraints_pressure(self, f, femobj, prs_obj): - rev = -1 if prs_obj.Reversed else 1 - f.write("*DLOAD\n") - for ref_shape in femobj["PressureFaces"]: - # the loop is needed for compatibility reason - # in deprecated method get_pressure_obj_faces_depreciated - # the face ids where per ref_shape - f.write("** " + ref_shape[0] + "\n") - for face, fno in ref_shape[1]: - if fno > 0: # solid mesh face - f.write("{},P{},{}\n".format(face, fno, rev * prs_obj.Pressure)) - # on shell mesh face: fno == 0 - # normal of element face == face normal - elif fno == 0: - f.write("{},P,{}\n".format(face, rev * prs_obj.Pressure)) - # on shell mesh face: fno == -1 - # normal of element face opposite direction face normal - elif fno == -1: - f.write("{},P,{}\n".format(face, -1 * rev * prs_obj.Pressure)) - # ******************************************************************************************** # constraints heatflux def write_constraints_heatflux(self, f): + from .con_heatflux import write_faceheatflux_constraints_heatflux self.write_constraints_sets( f, femobjs=self.heatflux_objects, analysis_types=["thermomech"], sets_getter_method=self.get_constraints_heatflux_faces, write_name="constraints_heatflux_element_face_heatflux", - sets_writer_method=self.write_faceheatflux_constraints_heatflux, + sets_writer_method=write_faceheatflux_constraints_heatflux, caller_method_name=sys._getframe().f_code.co_name, ) - def write_faceheatflux_constraints_heatflux(self, f, femobj, heatflux_obj): - if heatflux_obj.ConstraintType == "Convection": - heatflux_key_word = "FILM" - heatflux_facetype = "F" - # SvdW: add factor to force heatflux to units system of t/mm/s/K - heatflux_values = "{},{}".format( - heatflux_obj.AmbientTemp, - heatflux_obj.FilmCoef * 0.001 - ) - elif heatflux_obj.ConstraintType == "DFlux": - heatflux_key_word = "DFLUX" - heatflux_facetype = "S" - heatflux_values = "{}".format(heatflux_obj.DFlux * 0.001) - - f.write("*{}\n".format(heatflux_key_word)) - for ref_shape in femobj["HeatFluxFaceTable"]: - elem_string = ref_shape[0] - face_table = ref_shape[1] - f.write("** Heat flux on face {}\n".format(elem_string)) - for i in face_table: - # OvG: Only write out the VolumeIDs linked to a particular face - f.write("{},{}{},{}\n".format( - i[0], - heatflux_facetype, - i[1], - heatflux_values - )) - # ******************************************************************************************** # handle elements for constraints fluidsection with Liquid Inlet or Outlet # belongs to write_constraints_fluidsection, should be next method