LinuxQuestions.org
View the Most Wanted LQ Wiki articles.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices



Reply
 
Search this Thread
Old 05-15-2012, 12:49 PM   #1
EdinburghLad
LQ Newbie
 
Registered: May 2012
Posts: 2

Rep: Reputation: Disabled
BASH: IF statement not working?


Hi,

I'm trying to write a script which will generate the sum of the van der waal (VDW) radii for two atoms, then determine if a calculated bond distance is less than this sum and therefore whether the two atoms are bonded.

The script determines whether any atom is bonded to any other atom so runs as a loop within a loop (with outer loop counter FirstAtom and inner loop counter SecondAtom). In order to calculate the VDW sum the script needs to know which type of atom it is, so I wrote the fairly extensive IF statements you see in the code below to read from the AtomType array (which stores the atomic symbols) and then, depending on which atomic symbols they were, allocate a value to VDWa and VDWb, which are then added to get SumVDW. Finally the BondTest statement gives a boolean output for whether the atoms are bonded or not and writes it out to a file.

The problem is that when I run it, regardless of what the AtomType is, it always returns the "H" value for VDWa and VDWb. I've been staring at this for about two hours now and cant see where I've gone wrong, any help would be appreciated! (also if I haven't explained it well feel free to berate me and ask for more information!)

(ignore stuff in orange, it works fine)

Code:
FirstAtom=1
SecondAtom=1
#
while [[ $FirstAtom -le $NoAtoms ]]; do
        if [ ${AtomType[$FirstAtom]}="H" ]; then
               VDWa=1.2
        elif [ ${AtomType[$FirstAtom]}="C" ]; then
               VDWa=1.7
        elif [ ${AtomType[$FirstAtom]}="S" ]; then
               VDWa=1.8
        elif [ ${AtomType[$FirstAtom]}="N" ]; then
               VDWa=1.55
        elif [ ${AtomType[$FirstAtom]}="Pt" ]; then
               VDWa=1.75
        elif [ ${AtomType[$FirstAtom]}="As" ]; then
               VDWa=1.85
        fi
#
                while [[ $SecondAtom -le $NoAtoms ]]; do
                        Xd[$SecondAtom]=`echo "scale=4; (${Xc[$FirstAtom]}-${Xc[$SecondAtom]})^2" | bc -l`
                        Yd[$SecondAtom]=`echo "scale=4; (${Yc[$FirstAtom]}-${Yc[$SecondAtom]})^2" | bc -l`
                        Zd[$SecondAtom]=`echo "scale=4; (${Zc[$FirstAtom]}-${Zc[$SecondAtom]})^2" | bc -l`
                        Dist=`echo "scale=2; sqrt(${Xd[$SecondAtom]}+${Yd[$SecondAtom]}+${Zd[$SecondAtom]})" | bc -l`
#
                        echo ${AtomType[$SecondAtom]}
                        if [ ${AtomType[$SecondAtom]}="H" ]; then
                                VDWb=1.2
                        elif [ ${AtomType[$SecondAtom]}="C" ]; then
                                VDWb=1.7
                        elif [ ${AtomType[$SecondAtom]}="S" ]; then
                                VDWb=1.8
                        elif [ ${AtomType[$SecondAtom]}="N" ]; then
                                VDWb=1.55
                        elif [ ${AtomType[$SecondAtom]}="Pt" ]; then
                                VDWb=1.75
                        elif [ ${AtomType[$SecondAtom]}="As" ]; then
                                VDWb=1.85
                        fi
#
                        SumVDW=`echo "$VDWa + $VDWb" | bc -l`
                        echo $VDWb
#
                        BondTest=`echo "$Dist <= $SumVDW" | bc -l`
                                echo -e $Bondtest "\t" >> Column[$FirstAtom].txt
#
#
                Dist=0
                VDWa=0
                VDWb=0
                let "SecondAtom=$SecondAtom+1"
        done
SecondAtom=1
let "FirstAtom=$FirstAtom+1"
done
 
Old 05-15-2012, 01:21 PM   #2
Snark1994
Senior Member
 
Registered: Sep 2010
Location: Wales, UK
Distribution: Arch
Posts: 1,632
Blog Entries: 3

Rep: Reputation: 345Reputation: 345Reputation: 345Reputation: 345
I believe the issue is that there's no whitespace around the '=', though there may be other issues as well. You may also want to consider a 'case' statement rather than lots of 'if/elif's, as it's easier to read.

(Also, bash may not be the best language to do arithmetic-heavy operations in - something like python might be a better choice)

Last edited by Snark1994; 05-15-2012 at 01:22 PM.
 
Old 05-15-2012, 01:30 PM   #3
pan64
Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian i686 (solaris)
Posts: 5,159

Rep: Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364Reputation: 1364
yes, you need a lot of spaces to separate variables, equal sign and [ and ] . Also it was suggested to use [[ and ]] instead of [ and ].
From the other hand you can write a better code with case:
Code:
case ${AtomType[$FirstAtom]} in
   H) VDWb=1.2 ;;
   C) VDWb=1.7 ;;
 ....
(similar works for the second atom too)
 
Old 05-15-2012, 06:17 PM   #4
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 943Reputation: 943Reputation: 943Reputation: 943Reputation: 943Reputation: 943Reputation: 943Reputation: 943
It would be much, much easier to write in awk.

Here is a hopefully useful example:
Code:
#!/usr/bin/awk -f

BEGIN {
    # Use any newline convention for record separators.
    RS = "(\r\n|\n\r|\r|\n)"

    # Fields are separated by whitespace.
    FS = "[\t\v\f ]+"

    # Table of Van der Waals radiis
    VdWr["H"] = 1.2
    VdWr["C"] = 1.7
    VdWr["S"] = 1.8
    VdWr["N"] = 1.55
    VdWr["Pt"] = 1.75
    VdWr["As"] = 1.85

    # Table of the squared distances to compare against
    for (t1 in VdWr)
        for (t2 in VdWr)
            VdWrr[t1 "-" t2] = (VdWr[t1] + VdWr[t2])^2
}

# This will be run once per record.
(NF >= 4) {
    # We have at least four fields in this record ($1 $2 $3 $4).
    # Assume it is "Type X Y Z", and remember the atom.
    atoms++
    atype[atoms]  = $1
    xcoord[atoms] = $2
    ycoord[atoms] = $3
    zcoord[atoms] = $4
}

# This is only run after all input is processed.
#
END {
    # Find all bonded pairs, and output them as
    # Type X Y Z  Type X Y Z  distance
    #
    for (i = 1; i < atoms; i++) {
        for (j = i + 1; j <= atoms; j++) {
            dx = xcoord[i] - xcoord[j]
            dy = ycoord[i] - ycoord[j]
            dz = zcoord[i] - zcoord[j]
            dd = dx^2 + dy^2 + dz^2
            if (dd <= VdWrr[atype[i] "-" atype[j]])
                printf("%s %s %s %s  %s %s %s %s  %.6f\n", atype[i], xcoord[i], ycoord[i], zcoord[i], atype[j], xcoord[j], ycoord[j], zcoord[j], sqrt(dd))
        }
    }
}
If you have a lot of data, see if you have mawk installed; if so, use #!/usr/bin/mawk -f for the first line instead. It seems to be the fastest awk variant for this kind of processing, much faster than GNU awk (gawk).
 
1 members found this post helpful.
Old 05-15-2012, 07:47 PM   #5
jlinkels
Senior Member
 
Registered: Oct 2003
Location: Bonaire
Distribution: Debian Wheezy/Jessie/Sid, Linux Mint DE
Posts: 4,244

Rep: Reputation: 546Reputation: 546Reputation: 546Reputation: 546Reputation: 546Reputation: 546
Dunno how you define array AtomType[]. Might be very relevant in this case. But I can't replay your script now.

Run your script with bash -x /path/to/your/script and see where it fails. Should be obvious. If not, post the output where we see the values of AtomType[$FirstAtom] and how the comparison fails. Indeed is a case statement better in terms of programming style, but the if/elif should show nicely why the comparison fails.

jlinkels
 
Old 05-15-2012, 08:46 PM   #6
EdinburghLad
LQ Newbie
 
Registered: May 2012
Posts: 2

Original Poster
Rep: Reputation: Disabled
Reply

Solved! It was just a white space error, thanks guys, I hate tiny bits of annoying syntax. To those who suggested I code in a different language I would usually use fortran, which I'm a bit more familiar with, unfortunately I seem to be on the one system in the world without a decent compiler and no admin privileges to install one! Anyhow the script works beautifully and has already shown where my research is going wrong, so thanks guys!
 
Old 05-15-2012, 09:26 PM   #7
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 943Reputation: 943Reputation: 943Reputation: 943Reputation: 943Reputation: 943Reputation: 943Reputation: 943
Quote:
Originally Posted by EdinburghLad View Post
To those who suggested I code in a different language I would usually use fortran, which I'm a bit more familiar with, unfortunately I seem to be on the one system in the world without a decent compiler and no admin privileges to install one!
I suspected exactly that. That's why I suggested awk. It is always available (except perhaps on Windows systems).

If you ever generate test lattices, initial coordinates for nanoclusters, or duplicate molecules (with translation and rotation and optionally mirroring), to be fed to a simulation of some kind, you'll find that awk is superior tool for that. While it is nowhere as fast as compiled code, you can do in a single line or just a few lines something that would take you a couple of hours to write in Fortran.

(For rotations, I suggest using the quaternion approach to construct the rotation matrix: let the user specify some rotation axis, and an angle to rotate around that axis. Euler angles are difficult to generate uniformly ("random orientation"), and suffer from gimbal lock. The rotation axis and angle are trivial in comparison.)

Also, if you ran that shell script on anything more than a handful of atoms on a cluster where I was the administrator, I would be quite livid about the CPU wastage: calling bc to compute each interatomic distance.. I hope you at least run that code only on your own workstation, not on a cluster.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
How to get some bash scripts into a simple bash script with some echo and if statement. y0_gesh Programming 3 03-01-2012 10:46 AM
Bash If statement huntaz556 Linux - Newbie 9 10-25-2011 10:07 AM
Strange if statement behaviour when using bash/bash script freeindy Programming 7 08-04-2008 07:00 AM
bash if statement jstu Programming 7 02-15-2008 08:48 PM
Bash: Print usage statement & exit; otherwise continue using Bash shorthand operators stefanlasiewski Programming 9 02-07-2006 06:20 PM


All times are GMT -5. The time now is 09:39 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration