Agitateur - Swirler

import medcoupling as mc
import numpy as np

# Get available time steps
data = mc.MEDFileData("agitateur.med")
ts = data.getFields()[0].getTimeSteps()
print(ts)
# Get position of the swirler
fMts = data.getFields()["DISTANCE_INTERFACE_ELEM_BODY_ELEM_DOM"]
f1ts = fMts[(2,-1)]
fMc = f1ts.getFieldAtLevel(mc.ON_CELLS,0)
arr = fMc.getArray()
arr.getMinMaxPerComponent()      # just to see the field variation range per component
ids = arr.findIdsInRange(0.,1.)
f2Mc = fMc[ids]
# Extract pression field on the swirler
pressMts = data.getFields()["PRESSION_ELEM_DOM"]
press1ts = pressMts[(2,-1)]
pressMc = press1ts.getFieldAtLevel(mc.ON_CELLS,0)
pressOnAgitateurMc = pressMc[ids]
#
pressOnAgitateurMc.getMesh().zipCoords()
# Compute pressure on skin
agitateurMesh3DMc = pressOnAgitateurMc.getMesh()
m3DSurf,desc,descI,revDesc,revDescI = agitateurMesh3DMc.buildDescendingConnectivity()
nbOf3DCellSharing = revDescI.deltaShiftIndex()
ids2 = nbOf3DCellSharing.findIdsEqual(1)
agitateurSkinMc = m3DSurf[ids2]
offsetsOfTupleIdsInField = revDescI[ids2]
tupleIdsInField = revDesc[offsetsOfTupleIdsInField]
pressOnSkinAgitateurMc = pressOnAgitateurMc[tupleIdsInField]
pressOnSkinAgitateurMc.setMesh(agitateurSkinMc)
# Force field computation
pressSkin = pressOnSkinAgitateurMc.getArray()
pressSkin *= 1e5                   # conversion from bar to Pa
areaSkin = agitateurSkinMc.getMeasureField(True).getArray()
forceSkin = pressSkin*areaSkin
normalSkin = agitateurSkinMc.buildOrthogonalField().getArray()
forceVectSkin = forceSkin*normalSkin
# Torque computation
singlePolyhedron = agitateurMesh3DMc.buildSpreadZonesWithPoly()
singlePolyhedron.orientCorrectlyPolyhedrons()
centerOfMass = singlePolyhedron.computeCellCenterOfMass()

barySkin=agitateurSkinMc.computeCellCenterOfMass()
posSkin = barySkin-centerOfMass

torquePerCellOnSkin = mc.DataArrayDouble.CrossProduct(posSkin,forceVectSkin)

zeTorque = torquePerCellOnSkin.accumulate()
print("couple = %r N.m" % zeTorque[2])
# Power computation
speedMts = data.getFields()["VITESSE_ELEM_DOM"]
speed1ts = speedMts[(2,-1)]
speedMc = speed1ts.getFieldAtLevel(mc.ON_CELLS,0)
speedOnSkin = speedMc.getArray()[tupleIdsInField]
powerSkin = mc.DataArrayDouble.Dot(forceVectSkin,speedOnSkin)
power = powerSkin.accumulate()[0]
print("power = %r W"%(power))
# Eigen vector computation
x2 = posSkin[:,0]*posSkin[:,0]
x2 = x2.accumulate()[0]
y2 = posSkin[:,1]*posSkin[:,1]
y2 = y2.accumulate()[0]
xy = posSkin[:,0]*posSkin[:,1]
xy = xy.accumulate()[0]
inertiaSkin = np.matrix([[x2,xy],[xy,y2]])
inertiaSkinValues, inertiaSkinVects = np.linalg.eig(inertiaSkin)
pos = max(enumerate(inertiaSkinValues), key=lambda x: x[1])[0]
vect0 = inertiaSkinVects[pos].tolist()[0]
print(vect0)

def computeAngle(locAgitateur1ts):
        fMc = locAgitateur1ts.getFieldAtLevel(mc.ON_CELLS,0)
        arr = fMc.getArray()
        ids = arr.findIdsInRange(0.,1.)
        f2Mc = fMc[ids]
        m3DSurf,desc,descI,revDesc,revDescI = f2Mc.getMesh().buildDescendingConnectivity()
        nbOf3DCellSharing = revDescI.deltaShiftIndex()
        ids2 = nbOf3DCellSharing.findIdsEqual(1)
        agitateurSkinMc = m3DSurf[ids2]
        #
        singlePolyhedron = agitateurMesh3DMc.buildSpreadZonesWithPoly()
        singlePolyhedron.orientCorrectlyPolyhedrons()
        centerOfMass = singlePolyhedron.computeCellCenterOfMass()
        bary = agitateurSkinMc.computeCellCenterOfMass()
        posSkin = bary-centerOfMass
        x2=posSkin[:,0]*posSkin[:,0] ; x2=x2.accumulate()[0]
        y2=posSkin[:,1]*posSkin[:,1] ; y2=y2.accumulate()[0]
        xy=posSkin[:,0]*posSkin[:,1] ; xy=xy.accumulate()[0]
        inertiaSkin = np.matrix([[x2,xy],[xy,y2]])
        inertiaSkinValues,inertiaSkinVects = np.linalg.eig(inertiaSkin)
        pos = max(enumerate(inertiaSkinValues), key=lambda x: x[1])[0]
        vect0 = inertiaSkinVects[pos].tolist()[0]
        return vect0

vects = len(ts)*[None]
for itts,locAgitateur1ts in zip(ts,data.getFields()["DISTANCE_INTERFACE_ELEM_BODY_ELEM_DOM"]):
        angle = computeAngle(locAgitateur1ts)
        vects[itts[0]] = angle
        pass

from math import acos, sqrt
angle2 = len(ts)*[0.]
for pos in list(range(2,len(vects))):
    norm1 = sqrt(vects[pos-1][0]*vects[pos-1][0]+vects[pos-1][1]*vects[pos-1][1])
    norm2 = sqrt(vects[pos][0]*vects[pos][0]+vects[pos][1]*vects[pos][1])
    crs = vects[pos-1][0]*vects[pos][0]+vects[pos-1][1]*vects[pos][1]
    crs /= norm1 ; crs /= norm2 ; crs = min(crs,1.)
    angle2[pos] = acos(crs) #/(ts[pos][2]-ts[pos-1][2])
    pass

omega=sum(angle2)/(ts[-1][2]-ts[0][2])
print(sum(angle2))

print("At timestep (%d,%d) (physical time=%r s) the torque is: %r N.m, power/omega=%r N.m " % (ts[2][0],ts[2][1],ts[2][2],zeTorque[2],power/omega))