Calculations performed in Loop()

28 views
Skip to first unread message

Certa Christian

unread,
Jun 14, 2023, 3:44:47 AM6/14/23
to pysph-users

Hello PySPH users,

I have a query regarding the operation of calculations in the Loop() method of an equation. My specific question is: Does the Loop() method perform calculations for each neighboring particle, even if the equation does not take the properties of other particles as input?

To illustrate my query, consider an equation that performs a simple computation only using the properties of the particle indexed by d_idx. Will this calculation only be performed once? Or will it be executed for every neighboring particle as well?

Here is a snippet of code that prompted my question. It's from the solid_mech scheme.

class HookesDeviatoricStressRate(Equation):
    r""" Rate of change of stress

    .. math::
        \frac{dS^{ij}}{dt} = 2\mu\left(\epsilon^{ij} - \frac{1}{3}\delta^{ij}
        \epsilon^{ij}\right) + S^{ik}\Omega^{jk} + \Omega^{ik}S^{kj}

    where

    .. math::

        \epsilon^{ij} = \frac{1}{2}\left(\frac{\partial v^i}{\partial x^j} +
        \frac{\partial v^j}{\partial x^i}\right)\\

        \Omega^{ij} = \frac{1}{2}\left(\frac{\partial v^i}{\partial x^j} -
           \frac{\partial v^j}{\partial x^i} \right)

    """

    def initialize(self, d_idx, d_as00, d_as01, d_as02, d_as11, d_as12,
                   d_as22):
        d_as00[d_idx] = 0.0
        d_as01[d_idx] = 0.0
        d_as02[d_idx] = 0.0

        d_as11[d_idx] = 0.0
        d_as12[d_idx] = 0.0

        d_as22[d_idx] = 0.0

    def loop(self, d_idx, d_s00, d_s01, d_s02, d_s11, d_s12, d_s22, d_v00,
             d_v01, d_v02, d_v10, d_v11, d_v12, d_v20, d_v21, d_v22, d_as00,
             d_as01, d_as02, d_as11, d_as12, d_as22, d_G):

        v00 = d_v00[d_idx]
        v01 = d_v01[d_idx]
        v02 = d_v02[d_idx]

        v10 = d_v10[d_idx]
        v11 = d_v11[d_idx]
        v12 = d_v12[d_idx]

        v20 = d_v20[d_idx]
        v21 = d_v21[d_idx]
        v22 = d_v22[d_idx]

        s00 = d_s00[d_idx]
        s01 = d_s01[d_idx]
        s02 = d_s02[d_idx]

        s10 = d_s01[d_idx]
        s11 = d_s11[d_idx]
        s12 = d_s12[d_idx]

        s20 = d_s02[d_idx]
        s21 = d_s12[d_idx]
        s22 = d_s22[d_idx]

        # strain rate tensor is symmetric
        eps00 = v00
        eps01 = 0.5 * (v01 + v10)
        eps02 = 0.5 * (v02 + v20)

        eps10 = eps01
        eps11 = v11
        eps12 = 0.5 * (v12 + v21)

        eps20 = eps02
        eps21 = eps12
        eps22 = v22

        # rotation tensor is asymmetric
        omega00 = 0.0
        omega01 = 0.5 * (v01 - v10)
        omega02 = 0.5 * (v02 - v20)

        omega10 = -omega01
        omega11 = 0.0
        omega12 = 0.5 * (v12 - v21)

        omega20 = -omega02
        omega21 = -omega12
        omega22 = 0.0

        tmp = 2.0 * d_G[0]
        trace = 1.0 / 3.0 * (eps00 + eps11 + eps22)

        # S_00
        d_as00[d_idx] = tmp*( eps00 - trace ) + \
                        ( s00*omega00 + s01*omega01 + s02*omega02) + \
                        ( s00*omega00 + s10*omega01 + s20*omega02)

        # S_01
        d_as01[d_idx] = tmp*(eps01) + \
                        ( s00*omega10 + s01*omega11 + s02*omega12) + \
                        ( s01*omega00 + s11*omega01 + s21*omega02)

        # S_02
        d_as02[d_idx] = tmp*eps02 + \
                        (s00*omega20 + s01*omega21 + s02*omega22) + \
                        (s02*omega00 + s12*omega01 + s22*omega02)

        # S_11
        d_as11[d_idx] = tmp*( eps11 - trace ) + \
                        (s10*omega10 + s11*omega11 + s12*omega12) + \
                        (s01*omega10 + s11*omega11 + s21*omega12)

        # S_12
        d_as12[d_idx] = tmp*eps12 + \
                        (s10*omega20 + s11*omega21 + s12*omega22) + \
                        (s02*omega10 + s12*omega11 + s22*omega12)

        # S_22
        d_as22[d_idx] = tmp*(eps22 - trace) + \
                        (s20*omega20 + s21*omega21 + s22*omega22) + \
                        (s02*omega20 + s12*omega21 + s22*omega22)

In this code, computations in the loop() method do not involve any property of s_idx particle. So, are these calculations performed only once or for each neighboring particle?

My confusion arises from this excerpt in the documentation which says,

def loop(self, d_idx, s_idx, ...):
    # loop over neighbors for all sources,
    # called once for each pair of particles!

Does this mean that calculations are made once for every pair, even when the calculation does not involve the properties of the neighboring particles?

Any insights or clarifications you could provide would be greatly appreciated. Thank you for your time and assistance.

Best regards,
Christian

Prabhu Ramachandran

unread,
Jun 14, 2023, 4:47:52 AM6/14/23
to Certa Christian, pysph-users
Hello Christian,

The answer depends on how your equation is instantiated. So let us say you have

HookesDeviatoricStressRate(dest='solid', sources=None)

Then this will never compute the neighbors.  However, the loop code will also be called just as if it is an initialize loop.

If you set the sources to something then the neighbors will be computed and the code will be called once for each set of neighbors even if you choose to not use any source properties.

Regards,
Prabhu
--
You received this message because you are subscribed to the Google Groups "pysph-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pysph-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pysph-users/f6fa1e6b-2de2-43fc-b305-36341a51631cn%40googlegroups.com.

Certa Christian

unread,
Jun 14, 2023, 7:35:31 AM6/14/23
to pysph-users
Hello Prabhu,

thank you for your answer. This helps me to understand how to write efficient equations.

Regards,
Christian

Reply all
Reply to author
Forward
0 new messages