BASH, Dihedral angle with four points

后端 未结 3 1401
北海茫月
北海茫月 2021-01-27 02:48

Points:

A -2.08576        1.76533       -0.46417
B -0.95929        0.87554        0.03365
C  0.28069        1.66193        0.42640
D  0.62407        2.22927              


        
3条回答
  •  难免孤独
    2021-01-27 02:58

    EDIT: If your internet search for torsion.awk has brought you here, just skip up above to the accepted answer, as it uses the O.P.s refined algorithm to calculate torsion but still demonstrates converting shell code to awk.

    Previous readers, also note improvements to using this code in the 2nd edit below.


    I Just noticed the "properly" qualifcation at the end ;-/

    Here's your code converted to one awk process.

    I have no experience with this level of math, so can't say that it is really calculating the result you need.

    Also, there are often questions about precision in awk programs which really relates to the underlying c language libraries that are compiled in.

    Anyway, with all of the caveats, here's an basic conversion of your code.

    cat torsion_docd.awk

    #!/bin/awk -f
    
    function acos(x)        { return atan2((1.-x^2)^0.5,x) }
    
    # x1=`awk '{print $2}' LINEA` # x1
    # y1=`awk '{print $3}' LINEA` # y1
    # z1=`awk '{print $4}' LINEA` # z1
    # x2=`awk '{print $2}' LINEB` # x2
    # y2=`awk '{print $3}' LINEB` # y2
    # z2=`awk '{print $4}' LINEB` # z2
    # x3=`awk '{print $2}' LINEC` # x3
    # y3=`awk '{print $3}' LINEC` # y3
    # z3=`awk '{print $4}' LINEC` # z3
    # x4=`awk '{print $2}' LINED` # x4
    # y4=`awk '{print $3}' LINED` # y4
    # z4=`awk '{print $4}' LINED` # z4
    NR==1 {x1=$2; y=$3; z1=$4}
    NR==2 {x2=$2; y=$3; z2=$4}
    NR==3 {x3=$2; y=$3; z3=$4}
    NR==4 {
            x4=$2; y=$3; z4=$4
    
            # all of this code below is only executed when you read in the 4th line
            # becuase then you have all the data
            # v1x=`calc "($x1)-($x2)" | sed 's/^\t//g'`
            # v1y=`calc "($y1)-($y2)" | sed 's/^\t//g'`
            # v1z=`calc "($z1)-($z2)" | sed 's/^\t//g'`
            # v2x=`calc "($x4)-($x3)" | sed 's/^\t//g'`
            # v2y=`calc "($y4)-($y3)" | sed 's/^\t//g'`
            # v2z=`calc "($z4)-($z3)" | sed 's/^\t//g'`
    
            v1x=x1-x2 ; v1y=y1-y2 ; v1z=z1-z2
            v2x=x4-x3 ; v2y=y4-y3 ; v2z=z4-z3
    
            # v1mag=`calc "sqrt(($v1x)**2+($v1y)**2+($v1z)**2)" | sed 's/^\t//g'`
            # v2mag=`calc "sqrt(($v2x)**2+($v2y)**2+($v2z)**2)" | sed 's/^\t//g'`
    
            v1mag=sqrt((v1x)**2+(v1y)**2+(v1z)**2)
            v2mag=sqrt((v2x)**2+(v2y)**2+(v2z)**2)   
    
            # calc "acos((($v1x)/($v1mag))*(($v2x)/($v2mag))+(($v1y)/($v1mag))*(($v2y)/($v2mag))+(($v1z)/($v1mag))*(($v2z)/($v2mag)))*180/3.141
    592653589793" | sed 's/^\t//g' | sed 's/^~//g'
            # calc "acos((($x1)*($x4)+($y1)*($y4)+($z1)*($z4))/(sqrt(($x1)**2+($y1)**2+($z1)**2)*sqrt(($x4)**2+($y4)**2+($z4)**2)))*180/3.14159
    2653589793" | sed 's/^\t//g' | sed 's/^~//g'
    
            print acos(((v1x)/(v1mag))*((v2x)/(v2mag))+((v1y)/(v1mag))*((v2y)/(v2mag))+((v1z)/(v1mag))*((v2z)/(v2mag)))*180/3.141592653589793
            print acos(((x1)*(x4)+(y1)*(y4)+(z1)*(z4))/(sqrt((x1)**2+(y1)**2+(z1)**2)*sqrt((x4)**2+(y4)**2+(z4)**2)))*180/3.141592653589793
    }
    

    And without the conversion documentation, it looks like

    cat torsion.awk

    #!/bin/awk -f
    
    function acos(x)        { return atan2((1.-x^2)^0.5,x) }
    
    NR==1 {x1=$2; y=$3; z1=$4}
    NR==2 {x2=$2; y=$3; z2=$4}
    NR==3 {x3=$2; y=$3; z3=$4}
    NR==4 {
            x4=$2; y=$3; z4=$4
    
            # all of this code below is only executed when you read in the 4th line
            # because then you have all the data
    
            v1x=x1-x2 ; v1y=y1-y2 ; v1z=z1-z2
            v2x=x4-x3 ; v2y=y4-y3 ; v2z=z4-z3
    
            v1mag=sqrt((v1x)**2+(v1y)**2+(v1z)**2)
            v2mag=sqrt((v2x)**2+(v2y)**2+(v2z)**2)   
    
            print acos(((v1x)/(v1mag))*((v2x)/(v2mag))+((v1y)/(v1mag))*((v2y)/(v2mag))+((v1z)/(v1mag))*((v2z)/(v2mag)))*180/3.141592653589793
            print acos(((x1)*(x4)+(y1)*(y4)+(z1)*(z4))/(sqrt((x1)**2+(y1)**2+(z1)**2)*sqrt((x4)**2+(y4)**2+(z4)**2)))*180/3.141592653589793
    }
    

    Note that I added print statements in front of your last 2 lines acos.

    On my machine, I run it as

    awk -f torsion.awk data.txt
    

    EDIT : I've fixed #!/bin/awk at the top of script. So you then need to mark the script as executable with

     chmod +x ./torsion.awk
    

    And then you can run it just as

    `./torsion.awk data.txt
    

    Your system may require a different path to awk as in the she-bang line at the top (#!/bin/awk). Type which awk, and then use that value after the #!. Also, legacy Unix implementations often have other versions of awk installed, so if that is your operating environment, do some research to find out which is the best awk on your system (often times it is gawk).

    # -------------- end edit --------------------
    

    output

    87.6318
    131.872
    

    But given you agreed that -58.7 is your desired output, I'll have leave it to you for how to use the 2 acos calculations.

    In any case, hopefully you can see how much more straight forward is is to use awk for such calculations.

    Of course, hoping that true mathheads to wade in (after a good laugh) and help correct this (or offer their own ideas).

    IHTH

提交回复
热议问题