1

I'm working on a script processing computed strains/deformations for multiple nodes of a finite element analysis (FEA). There are multiple solutions for different, positive input torques. I want to extrapolate this data and simulate the results for negative torques. Whilst doing that the original data changes.

As we are not directly changing any of the original values I think it must be accessed by reference through the function extrapolating the FEA. I've been trying copy.deepcopy, but figured over multiple threads that this does not copy class structures. In other threads it was recommended to inherit but I'm struggling adapting it to my case.

The following code is inside the class containing all nodes on the same radius of the object. All nodes are in a list self._nodes sorted by their angle. Each node has the strains for all torque levels.

class RadialNodeContainer:
    def __init__(self, radius):
        self._r = radius
        self._nodes = []
    def compute_negatives_radial_container(self): # ... see below

class Node:
    def __init__(self, node_id, x, y, z,
                 strain_0nm, strain_100nm, strain_204nm, strain_369nm):
        self._coordinate = Coordinate(x, y, z)
        self._torque_levels = [strain_0nm, strain_100nm,
                               strain_204nm, strain_369nm]
    def get_all_strains_complete(self):
        return copy.deepcopy(self._torque_levels)

class Strain:
    def __init__(self, torque_nm, exx, exy, eyy):
        self._torque = torque_nm
        self._exx = exx
        self._exy = exy
        self._eyy = eyy

The function which causes unwanted changes the original data:

def compute_negatives_radial_container(self):
    points_per_360deg = len(self._nodes)
    jj = points_per_360deg
    corresponding_node_strains = None
    for ii in range(points_per_360deg):
        jj -= 1
        # Mistake is expected below here
        corresponding_node_strains = copy.deepcopy(
                         self._nodes[jj].get_all_strains_complete())                      
        for kk in range(len(corresponding_node_strains)):
            torque = corresponding_node_strains[kk].get_torque_level()
            if torque != 0:
                exx, exy, eyy = corresponding_node_strains[kk].get_raw_strains()
                calculated_negative_strain = Strain(torque_nm=-torque,
                                                    exx=exx,
                                                    exy=-exy,
                                                    eyy=eyy)
                self._nodes[ii].add_torque_level(calculated_negative_strain)

I thought of creating a deepcopy of the list of strain elements (Node -> self._torque_level). Originally this list looks like [Strain(0Nm), Strain(100Nm), ...]. But I can't wrap my head around what part(s) of the code I have to adapt to allow passing a copy of the class instances.

Dmitriy Kisil
  • 2,858
  • 2
  • 16
  • 35
Fabitosh
  • 98
  • 10
  • Can't you simply add a method to Strain to deal with a negative value? Then when later referenced use either a switch in the class or a different method. – Jay M Apr 01 '19 at 07:53

1 Answers1

0

To elaborate. I will expand on this if I have time and it's what the OP is looking for.

I would also recommend using numpy for your arrays rather than lists as mumpy is much faster.

class Strain:
    def __init__(self, torque_nm, exx, exy, eyy):
        self._torque = torque_nm
        self._exx = exx
        self._exy = exy
        self._eyy = eyy
        self._neg = False

    def setNeg(self, neg):
        self._neg = neg

    @propery
    def torque(self):
        return _torque if not self._neg else -self.torque

    @propery
    def exx(self):
        return _exx

    @propery
    def exy(self):
        return _exy if not self._neg else -self._exy

    @propery
    def eyy(self):
        return _eyy
Jay M
  • 3,736
  • 1
  • 24
  • 33
  • Thank you for the proposition. The negatives are extrapolated of strains of nodes at a different location (mirrored over the x-axis) and can't be generated of the strains of the same node. In other words: we take `self._nodes[jj]`-values for the negatives at `self._nodes[ii]`. I thus don't think this approach would work. Thank you for introducing me to @property, very neat! – Fabitosh Apr 01 '19 at 10:09
  • So do the same thing but on the array of data rather than the array points. Have a 'strain_array' class and have it mutate it's outputs based on some switch. Create a subclass of some collection class or use __iter__() special method on your own class. – Jay M Apr 02 '19 at 11:15