OOP Abaqus Klassen Problem

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Ferrago
User
Beiträge: 4
Registriert: Montag 16. Dezember 2019, 19:16

Hallo,

ich habe eine Frage bezüglich des Aufbaus eines Skripts bzw. der Klassen für Abaqus (FEM-Software).

Ich analysiere ein Bauteil das aus zwei Einzelteilen zusammengesetzt ist. Dafür habe ich zwei Klassen angelegt, wo jeweils das Einzelteil erzeugt wird.

In Abaqus werden dann die Einzelteile (Parts) in einer "Assembly" zusammengefügt. In meinem Fall möchte ich das eine Bauteil aus dem anderen herausschneiden. Für diesen Vorgang mal hier das Skript:

Code: Alles auswählen

def core_cutout(self):
	
	# hier wird die assembly erzeugt
        connAssembly = self._model.rootAssembly
	
        inst_clt = connAssembly.Instance(name = self._name, part = cltPlatePart, dependent = ON)

        inst_lvl = connAssembly.Instance(name = self._name, part = corePart, dependent = ON)
	
	# Verschiebung des corePart
        inst_lvl.translate(vector = (plate_width / 2 - (inner_core_width / 2 + cutout_width), 0, 0))
	
	#Ausschneiden des corePart aus dem cltPlatePart
        connAssembly.InstanceFromBooleanCut(name = 'Cutted Plate', instanceToBeCut = inst_clt, 
        cuttingInstances = (inst_lvl, ), originalInstances = DELETE)
Da die zwei Einzelteile cltPlatePart und corePart in den dazugehörigen Klassen definiert worden, erhalte ich logischerweise folgenden Error:

"global name 'cltPlatePart' is not defined"


Nun meine Fragen....

Wie kann ich eine Funktionen außerhalb einer Klasse ausführen und dabei auf die in den Klassen definierten Objekte zugreifen? Oder ist der Aufbau an sich schon falsch/ungeeignet?

Hat das etwas mit Inheritance oder Composition zu tun? Die bisherigen Beispiele die ich dazu gesehen habe, haben mir leider nicht wirklich weiter geholfen.


Ich hoffe ich habe das Problem ausführlich genug erklärt um das Problem zu verstehen.


Vielen Dank schon mal für eure Bemühungen!


Gruß Ferrago
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Ferrago: Du musst *über* die Objekte auf denen diese Attribute definiert sind auf die Attribute zugreifen. Dazu musst Du das/die Objekt(e) als Argumente an die Methode übergeben.

`plate_width`, `inner_core_width`, und `cutout_width` kommen auch auf magische Weise aus dem ”nichts” — alles was eine Funktion/Methode ausser Konstanten benötigt, sollte als Argument(e) übergeben werden.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Ferrago
User
Beiträge: 4
Registriert: Montag 16. Dezember 2019, 19:16

Wie übergebe ich die Objekte in dem Fall an die Methode? Bei plate_width, inner_core_width und cutout_width handelt es sich um Variabeln die ich außerhalb der Klassen definiert habe. Das würde ich dann wie folgt machen oder?

Code: Alles auswählen

def core_cutout(self, plate_width, inner_core_width, cutout_width):

self._plate_width  = plate_width
self._inner_core_width = inner_core_width 
self._cutout_width = cutout_width
Bei cltPlatePart handelt es sich um ein Objekt (Quader) das in einer Klasse wie folgt erzeugt wurde:

Code: Alles auswählen

        cltPlateProfileSketch.rectangle(point1 = (0.0, 0.0), point2 = (plate_width, plate_length))

        # creating a Part object and placing it in the parts repository
        cltPlatePart = self._model.Part(name = self._name, dimensionality =THREE_D, type = DEFORMABLE_BODY)

        # creating a Feature object
        cltPlatePart.BaseSolidExtrude(sketch = cltPlateProfileSketch, depth = floor_hight)
In einer außerhalb der Klassen erzeugten Methode werden dann die in den Klassen definierten Methoden ausgeführt:

Code: Alles auswählen

def compute_global_model(model):

    # create clt plate
    clt = cltPlate(model = model, name = "CLT-Plate", pos = (0, 0, 0))
    clt.set_geom_params(plate_length, plate_width, floor_hight, layer_depth, n_layers)
    clt.gen_geometry()

Ich verstehe immer noch nicht wie ich die Objekte in die Methode "core_cutout" bekomme. Und zusätzlich frage ich mich noch wo ich die Methode dann unterbringe und wie ich sie ausführe?
Die anderen Methoden beziehen sich ja immer auf eine spezifische Klasse, z.B "cltPlate".
Da ich jetzt zwei Objekte aus zwei unterschiedlichen Klassen habe, weiß ich nicht wie ich das machen kann.



Sorry falls ich bestimmte Begriffe durcheinander werfe. Kann das alles noch nicht so gut zuordnen. Hoffe man versteht mein Problem.
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Ferrago: Die Übergabe an sich sieht so aus, aber Du solltest die Argumente dann nicht an `self` binden. Oder anders: falls das Attribute sein sollten, dann sollten sie in der `__init__()` eingeführt werden und nicht in `core_cutout()`.

Variablen ausserhalb von Klassen oder besser gesagt Funktionen und Methoden sollte es gar nicht geben. Auf Modulebene und in Klassen gehören in aller Regel nur Konstanten, die per Konvention KOMPLETT_GROSS geschrieben werden.

`cltPlatePart` wird (hoffentlich) nicht in einer Klasse erzeugt, sondern in einer Methode‽ Und von dort kann es dann bei Aufrufen als Argument übergeben werden. Oder als Rückgabewert an den Aufrufer der Methode. Oder man setzt es als (öffentliches) Attribut auf dem Objekt auf dem die Methode aufgerufen wurde. Dann aber entweder in der `__init__()` oder in der `__init__()` wurde zumindest das Attribut mit einem Platzhalter als Wert angelegt – dafür ist `None` da. Was Du da jetzt am sinnvollsten machst, kann man nicht pauschal beantworten.

Methoden die ausserhalb von Klassen definiert werden sind keine Methoden sondern Funktionen.

Klassen erkennt man normalerweise daran das sie in MixedCase benannt sind, also mit einem grossen Anfangsbuchstaben. Der gesamte Code hält sich nicht an die üblichen Namenskonventionen. Das ist teilweise verwirrend zu lesen. Schau Dir mal den Style Guide for Python Code an.

Wenn man nicht weiss in welcher Klasse man eine Methode unterbringen soll, dann vielleicht in keiner? Oder einer neuen? Auch das kann man nicht pauschal beantworten.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Ferrago
User
Beiträge: 4
Registriert: Montag 16. Dezember 2019, 19:16

@ __blackjack__ danke für deine Antworten! Allerdings fällt es mir immer noch sehr schwer deine Ausführung zu verstehen. Wäre es möglich das Ganze mit einem Beispiel Code zu erklären?

Bei plate_width etc. handelt es sich um Werte einer Parameterstudie. In dem Fall kann ich sie außerhalb der Klassen definieren oder? Entsprechend der Namenskonventionen müsste ich sie dann groß schreiben, wenn ich das richtig verstanden habe?

Das Objekt "cltPlatePart" wird in einer Methode innerhalb der Klasse "CltPlate" erzeugt.
Das Objekt "lvlCorePart" wird in einer Methode innerhalb der Klasse "LvlCore" erzeugt.

Nun möchte ich den "lvlCorePart" aus dem "cltPlatePart" ausschneiden.
Dafür sehe ich drei Möglichkeiten...

-Ich mache das ganze in einer der bestehenden Klassen, z.B. in der Klasse "CltPlate"

-Ich erzeuge eine neue Klasse

-Ich mache das ganze mit einer Funktion außerhalb der Klassen.

Bei allen drei Varianten habe ich immer noch das Problem, dass ich nicht weiß wie ich die Objekte übergebe?

Ich wäre sehr dankbar wenn mir jemand anhand eines Beispiels erklären kann wie das ganze funktioniert.
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Ferrago: Wenn `plate_width` & Co Konstanten sind und keine Variablen, dann ja, auf Modulebene, in der Regel gleich nach den Importanweisungen und komplett in Grossbuchstaben benannt.

Was heisst denn Objekt "a" wird in einer Methode innerhalb der Klasse "X" erzeugt? Das wird da an einen lokalen Namen "a" gebunden, und dann? Was passiert weiter damit? Ist das Teil eines "X"-Objekts? Oder das Ergebnis oder Teil des Ergebnis der Methode? Wenn das nach dem Aufruf der Methode noch benötigt wird, muss man es entweder an das "X"-Objekt binden, als Attribut oder in einer Datenstruktur die als Attribut auf "X"-Objekten definiert ist, falls "a" zum Zustand von "X"-Objekten gehört. Falls es nicht zum Zustand gehört die ein "X"-Objekt ausmachen, dann ist es ein Rückgabewert der an den Aufrufer zurückgegeben wird. In beiden Fällen hat der Aufrufer Zugriff auf das "a"-Objekt, entweder weil er es als (Teil) des Rückgabewertes bekommt, oder weil er über das "X"-Objekt darauf zugreifen kann. Für letzteren Fall braucht man eventuell noch eine Methode auf "X" wenn man nicht direkt in die Datenstruktur durchgreifen will, falls das "a" nicht als einfaches Attribut gesetzt wurde.

Also Variante 1, das "a" gehört nicht zum Zustand von "X", die Methode benötigt aber den Zustand von "X" (sonst wäre es keine Methode):

Code: Alles auswählen

class X:
    def method_that_creates_a(self):
        # Hier muss noch irgendetwas passieren das mit dem aktuellen Zustand von
        # dem `X`-Objekt zu tun hat, sonst ist der Entwurf als Methode falsch!
        return A(...)
Oder Variante 2, das "a" gehört zum Zustand von "X" und die Methode sollte auch den aktuellen Zustand von "X" benötigen (sonst ist es wahrscheinlich keine Methode):

Code: Alles auswählen

class X:
    def __init__(self):
        self.a = None  # Oder bereits hier ein `A`-Object.

    def method_that_creates_a(self):
        # Hier muss noch irgendetwas passieren das mit dem aktuellen Zustand von
        # dem `X`-Objekt zu tun hat, sonst ist der Entwurf als Methode ziemlich
        # wahrscheinlich falsch!
        self.a = A(...)
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Ferrago
User
Beiträge: 4
Registriert: Montag 16. Dezember 2019, 19:16

Vielen Danke für deine Hilfe!

Es hat geklappt.

Gruß Ferrago
Antworten