Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
27093 Discussions

How can I check "if the array contains element A and does not contains element B"?

Yeon__Jejoon
Novice
1,365 Views

I have an array that includes 2D arrays. I wish to set some elements of a specific array to a specific variable based on some conditions. 

All arrays are read from the input file. I read the columns and stored them into the arrays. Input columns look like this: 

open(1,file="rawdata.txt",status='old')

nat=9000 ! integer

do i=1,nat
read (1,*) field1(i),numelem(i),(contents1(i,j),j=1,numelem(i)),(contents2(i,j),j=1,numelem(i))
enddo

Here, numelem(i) array provides the total number of elements of the secondary array contents1 and contents2 so I used it. 

 

Now, I wish to perform 

...


r1 = 3 ! this is an integer number I gather from other arrays 

r2 = 5 ! this is an integer number I gather from other arrays 

do i=1,nat

if (field1(i).eq.3) then 

! If-loop 1 = If the value of field1 array is 3

do j=1,numelem(i) 

if (((field1(contents1(i,j)).eq.4).and.(contents2(i,j).ge.0.5)).or.((field1(contents1(i,j)).eq.1).and.(contents2(i,j).ge.0.3))) then

! If-loop 2 = If the value of field1 array at contents1(i,j)-th index is 4 and corresponding contents2(i,j) value is greater than 0.5. Or, if the value of field1 array at contents1(i,j)-th index is 1 and corresponding conetents2(i,j) value is greater than 0.3 then 

if ((r1/=contents1(i,j)).and.(r2==contents1(i,j))) then

! If-loop 3 = Among elements of contents1 array that satisfy if-loop 1 and if-loop 2, check if the r1 is not included among the selected elements of contents1 array, and r2 is included in the selected elements of contents1 array. 

if (contents1(i,j)/=r2) then

r3 = contents1(i,j)

! If-loop 4 = If the if-loop 1, if-loop 2, and if-loop 3 are satisfied, then assign/store the elements of contents1(i,j) to new variable r3, except the element r2. 

...

 

But I don't think I wrote properly to get what I want. Especially, I think if-loop 3 and if-loop 4 are definitely wrong. 

For if-loop 3, I tried ANY command but this gives me the error

An array-valued argument is required in this context.

So I just used if loop and logical operator /= and ==. But I'm not sure if I'm doing this correctly. 

 

If-loop 4 is wrong, assign/store the elements of the array to a variable except for a specific element. But I'm not sure how can I achieve this... 

 

Is there any better way to achieve such loops without using a lot of if-loops? Data size is really huge, I wish to reduce the number of if loops, but I'm not sure if there are any better ways. 

 

0 Kudos
23 Replies
Arjen_Markus
Valued Contributor III
1,211 Views

I do not think the ANY function is what you, because it examines the array as a whole and produces a single logical result. Instead, it might be that the WHERE construct brings you a bit further:

where ( array == 2.0 ) 
    array = 1.0
elsewhere
    array = - array
endwhere

The above, complete contrived code is equivalent to (assuming array is a one-dimensional array)

do i = 1,size(array)
    if ( array(i) == 2.0 ) then
        array(i) = 1.0
    else
        array(i) = - array(i)
    endif
enddo

This may or may not be useful in your case.

But of course, this is merely syntax. It may also be possible to use the MERGE function, but I have not studied the description you gave of the problem in enough detail. (It is rather detailed ;))

 

jimdempseyatthecove
Black Belt
1,198 Views

>>Is there any better way to achieve such loops without using a lot of if-loops? Data size is really huge

When you use ANY, WHERE, etc... their elegance is only effective in situations when the entirety of the arrays have an action behavior of:

IF(condition) doThis else doThat

Your (?incomplete) code snip-it (and "Data size is really huge") suggest that you would be best served by following the OHIO method (Only Handle It Once) by implementing nested IF statements in an optimal filter reduction order. IOW iterate the data once and nest your IF statements in order of highest probability of exclusion of any store operations.

Before we can make meaningful comments on your code, you need to post the actual code.

Note, in the posted code above, line 24 is in confluence by line 20. I do not suspect your actual code is representative of this.

Jim Dempsey

Yeon__Jejoon
Novice
1,184 Views

Before we can make meaningful comments on your code, you need to post the actual code.

>> Actual code is pretty much similar to "snippets" I uploaded in the original post. Read input file -> loops to count the occurrence of the event -> print out. But just with more similar loops. I didn't write the whole code because it becomes too long. But let me try in this reply. 

1) This code is not correct, I shortened it a bit and I removed all variable declaration and format parts. But you can see the whole logic in here.

2) I'm working in chemistry, and the objective of the script is to find the "ring" structure of atoms from the data which contains the neighbor list. The whole thing begins from the "i-th" oxygen atom. I check the neighbors of oxygen atom i, and if some elements of neighborlist array satisfy the if loop conditions, then store it to r2, and check the next "k-th" oxygen atom, and repeat. In the end, I wish to count the number of occurrences of the ring of "i-r1-k-r2-m-r3-o-r4-i". This will be like "oxygen-other-oxygen-other-oxygen-other-oxygen-other-original oxygen". 

3) This example is just for the ring of 4 oxygens. I need to do the same up to 16 oxygens. That means I need to use similar loops 16 times. So I'm not sure if this is the efficient way of doing this. 

4) To escape from the memory issue, I split the original raw data into pieces and apply the script piece by piece, part by part. 

5) I explained what I want to do and what these loops are doing in the comment of the following example script, and I also wrote what I don't know how to do or not clear if I'm doing correctly.

For example, I'm not sure if my way of checking if specific numbers included/excluded or not is correct (line 47, 68, 90),  and I really don't know how can I store elements of the array to a variable except some specific number (line 51, 72, 94). These are also mentioned in the original questions. 

 

open(1,file="rawdata.txt",status='old')
iframe=0
  100  continue
iframe=iframe+1

nat=9000 ! integer

do i=1,nat
  read (1,*)
  field1(i),numelem(i),(neighborlist1(i,j),j=1,numelem(i)),(neighborlist2(i,j),j=1,numelem(i))
enddo

r1=0
r2=0
r3=0
r4=0
ncount=0


! First do loop for the first oxygen
do i=1,nat
  if (field1(i).eq.3) then
! If-loop 1 = If the value of field1 array is 3
  do j=1,numelem(i)
    if (((field1(neighborlist1(i,j)).eq.4).and.(neighborlist2(i,j).ge.0.5)).or.((field1(neighborlist1(i,j)).eq.1).and.(neighborlist2(i,j).ge.0.3))) then
! If-loop 2 = If the value of field1 array at neighborlist1(i,j)-th index is
! 4 and corresponding neighborlist2(i,j) value is greater than 0.5. Or, if
! the value of field1 array at neighborlist1(i,j)-th index is 1 and
! corresponding neighborlist2(i,j) value is greater than 0.3 then
    r1=neighborlist1(i,j)
! If 2 if loops are satisfied, then store the element of neighborlist1(i,j)
! to integer variable r1.



! Second do loop for the second oxygen. Use i+1 for indexing to prevent
! the counting of the same oxygen atom i.
    do k=i+1,nat
      if (field1(k).eq.3) then
! If-loop 1 = If the value of field1 array is 3
      do l=1,numelem(k)
      if (((field1(neighborlist1(k,l)).eq.4).and.(neighborlist2(k,l).ge.0.5)).or.((field1(neighborlist1(k,l)).eq.1).and.(neighborlist2(k,l).ge.0.3))) then
! If-loop 2 = If the value of field1 array at neighborlist1(k,l)-th index is
! 4 and corresponding neighborlist2(k,l) value is greater than 0.5. Or, if
! the value of field1 array at neighborlist1(k,l)-th index is 1 and
! corresponding neighborlist2(k,l) value is greater than 0.3 then
      if (r1==neighborlist1(k,l)) then
! If-loop3 = If the neighborlist1(k,l) contains the r1 =>
! This means the i, r1, and k, three elements are connected.
! But I'm not sure if this is a proper way to check include/exclude
      r2=neighborlist1(k,l) ! but only if the r2 is not r1
! If all three loops are satisfied, then store the element of neighborlist1(
! k,l) to the r2. While doing this, I wish to exclude r1 from r2.
! But I don't know how to do this.


! Third do loop for the third oxygen. Use k+1 for indexing to prevent
! the counting of the same oxygen i and k
      do m=k+1,nat
        if (field1(m).eq.3) then
! If-loop 1 = If the value of field1 array is 3
        do n=1,numelem(m)
          if (((field1(neighborlist1(m,n)).eq.4).and.(neighborlist2(m,n).ge.0.5)).or.((field1(neighborlist1(m,n)).eq.1).and.(neighborlist2(m,n).ge.0.3))) then
! If-loop 2 = If the value of field1 array at neighborlist1(m,n)-th index is
! 4 and corresponding neighborlist2(m,n) value is greater than 0.5. Or, if
! the value of field1 array at neighborlist1(m,n)-th index is 1 and
! corresponding neighborlist2(m,n) value is greater than 0.3 then
          if ((r1/=neighborlist1(m,n)).and.(r2==neighborlist1(m,n))) then
! If-loop3 = If the neighborlist1(m,n) contains the r2 but not r1 =>
! This means the i, r1, k, and r2, four elements are connected.
! But I'm not sure if this is a proper way to check include/exclude
          r3=neighborlist1(m,n) ! but only if the r3 is not r2
! If all three loops are satisfied, then store the element of neighborlist1(
! m,n) to the r3. While doing this, I wish to exclude r2 from r3.
! But I don't know how to do this.



! Fourth do loop for the fourth oxygen. Use m+1 for indexing to prevent
! the counting of the same oxygen i, k, and m
          do o=m+1,nat
            if (field1(o).eq.3) then
! If-loop 1 = If the value of field1 array is 3
            do p=1,numelem(o)
              if (((field1(neighborlist1(o,p)).eq.4).and.(neighborlist2(o,p).ge.0.5)).or.((field1(neighborlist1(o,p)).eq.1).and.(neighborlist2(o,p).ge.0.3))) then
! If-loop 2 = If the value of field1 array at neighborlist1(o,p)-th index is
! 4 and corresponding neighborlist2(o,p) value is greater than 0.5. Or, if
! the value of field1 array at neighborlist1(o,p)-th index is 1 and
! corresponding neighborlist2(o,p) value is greater than 0.3 then
              if ((r1/=neighborlist1(o,p)).and.(r2/=neighborlist1(o,p)).and.(r3==neighborlist1(o,p))) then
! If-loop3 = If the neighborlist1(o,p) contains the r3 but not r1 & r2  =>
! This means the i, r1, k, r2, m, and r3, six elements are connected.
! But I'm not sure if this is a proper way to check include/exclude
              r4=neighborlist1(o,p) ! but only if the r4 is not r3
! If all three loops are satisfied, then store the element of neighborlist1(
! o,p) to the r4. While doing this, I wish to exclude r3 from r4.
! But I don't know how to do this.
              if (r4=neighborlist1(i,j)) then
! Now, if the neighborlist1(i,j), the neighbor list of atom i contains r4
! That means we found the ring of i-r1-k-r2-m-r3-o-r4-i. Count +1
              ncount=ncount+1


! endifs and enddos for all loops
write(151,40) iframe,ncount
goto 100

 

 

 

 

 

 Hope this helps. 

JohnNichols
Valued Contributor II
1,171 Views

Can I quietly suggest, that you add a small copy of the data file, not to long.  You add enough code to get the snippet running without people having to make assumptions, and you provide a concise summary in 2 paragraphs at year 10 level science of what you are trying to do in the code.  

This is what I would tell a master's student who came to me with this problem. 

Yeon__Jejoon
Novice
1,163 Views

Can I quietly suggest, that you add a small copy of the data file, not to long.  You add enough code to get the snippet running without people having to make assumptions, and you provide a concise summary in 2 paragraphs at year 10 level science of what you are trying to do in the code.  

This is what I would tell a master's student who came to me with this problem. 

>> I think my original question post provide the snippet and concise summary of the problem. I'm not sure if my way of checking if specific elements are included and not included in the array or not is a proper method (If-loop 3 part), and I really don't know how to store/assign elements of an array to a variable except some specific value (If-loop 4 part) 

May I ask which part of the original question is not clear to you? I could provide a new version in the reply. 

If my way of explanation was not a great way, sorry for that. I couldn't find a better way to express this as I don't have much experience in coding and ask a question about the logic of the coding.  

Regarding the data file, it is a bit complicated... just copy and paste would not work as an example, I need to modify values to make a "proper" example. So I didn't provide. But let me try in here: 

 4 8 3005 3232 5290 8778 4762 6888 339 58          0.922         0.016         0.022         0.931         0.050         0.929         0.943         0.034
 3 4 7673 4048 8709 6011          0.000         0.955         0.770         0.010         
 3 6 1001 4278 8644 2038 8529 5038          0.000         0.001         0.001         0.935         0.052         0.930         

 

Then, "jimdempseyatthecove" asked me to share "actual code", so I tried to provide "actual code" in the reply. Not the entire full code but just a part for the loops. 

JohnNichols
Valued Contributor II
1,148 Views

What is the actual problem you are trying to solve,  I am tracking the placement of billiard balls on a table after a shot? 

You provide code, but it helps if we understand the work of the code. 

The first 100 lines of the text file should be enough to see what is happening? 

In 1989 Consul published some interesting code on a Poisson Process, the code was reviewed and published, but a interesting error had escaped Consul and the reviewers, it made a difference. 

Looking for errors in code is the start, but you need to see the actual run to get all the potential errors.  

I think I understand what you are trying to do, but I am not sure.   make this actually work as a program and then we can use write statements to look at the results.  

open(1,file="rawdata.txt",status='old')
iframe=0
  100  continue
iframe=iframe+1

nat=9000 ! integer

do i=1,nat
  read (1,*)
  field1(i),numelem(i),(neighborlist1(i,j),j=1,numelem(i)),(neighborlist2(i,j),j=1,numelem(i))
enddo

r1=0
r2=0
r3=0
r4=0
ncount=0


! First do loop for the first oxygen
do i=1,nat
  if (field1(i).eq.3) then
! If-loop 1 = If the value of field1 array is 3
  do j=1,numelem(i)
    if (((field1(neighborlist1(i,j)).eq.4).and.(neighborlist2(i,j).ge.0.5)).or.((field1(neighborlist1(i,j)).eq.1).and.(neighborlist2(i,j).ge.0.3))) then
! If-loop 2 = If the value of field1 array at neighborlist1(i,j)-th index is
! 4 and corresponding neighborlist2(i,j) value is greater than 0.5. Or, if
! the value of field1 array at neighborlist1(i,j)-th index is 1 and
! corresponding neighborlist2(i,j) value is greater than 0.3 then
    r1=neighborlist1(i,j)
! If 2 if loops are satisfied, then store the element of neighborlist1(i,j)
! to integer variable r1.



! Second do loop for the second oxygen. Use i+1 for indexing to prevent
! the counting of the same oxygen atom i.
    do k=i+1,nat
      if (field1(k).eq.3) then
! If-loop 1 = If the value of field1 array is 3
      do l=1,numelem(k)
      if (((field1(neighborlist1(k,l)).eq.4).and.(neighborlist2(k,l).ge.0.5)).or.((field1(neighborlist1(k,l)).eq.1).and.(neighborlist2(k,l).ge.0.3))) then
! If-loop 2 = If the value of field1 array at neighborlist1(k,l)-th index is
! 4 and corresponding neighborlist2(k,l) value is greater than 0.5. Or, if
! the value of field1 array at neighborlist1(k,l)-th index is 1 and
! corresponding neighborlist2(k,l) value is greater than 0.3 then
      if (r1==neighborlist1(k,l)) then
! If-loop3 = If the neighborlist1(k,l) contains the r1 =>
! This means the i, r1, and k, three elements are connected.
! But I'm not sure if this is a proper way to check include/exclude
      r2=neighborlist1(k,l) ! but only if the r2 is not r1
! If all three loops are satisfied, then store the element of neighborlist1(
! k,l) to the r2. While doing this, I wish to exclude r1 from r2.
! But I don't know how to do this.


! Third do loop for the third oxygen. Use k+1 for indexing to prevent
! the counting of the same oxygen i and k
      do m=k+1,nat
        if (field1(m).eq.3) then
! If-loop 1 = If the value of field1 array is 3
        do n=1,numelem(m)
          if (((field1(neighborlist1(m,n)).eq.4).and.(neighborlist2(m,n).ge.0.5)).or.((field1(neighborlist1(m,n)).eq.1).and.(neighborlist2(m,n).ge.0.3))) then
! If-loop 2 = If the value of field1 array at neighborlist1(m,n)-th index is
! 4 and corresponding neighborlist2(m,n) value is greater than 0.5. Or, if
! the value of field1 array at neighborlist1(m,n)-th index is 1 and
! corresponding neighborlist2(m,n) value is greater than 0.3 then
          if ((r1/=neighborlist1(m,n)).and.(r2==neighborlist1(m,n))) then
! If-loop3 = If the neighborlist1(m,n) contains the r2 but not r1 =>
! This means the i, r1, k, and r2, four elements are connected.
! But I'm not sure if this is a proper way to check include/exclude
          r3=neighborlist1(m,n) ! but only if the r3 is not r2
! If all three loops are satisfied, then store the element of neighborlist1(
! m,n) to the r3. While doing this, I wish to exclude r2 from r3.
! But I don't know how to do this.



! Fourth do loop for the fourth oxygen. Use m+1 for indexing to prevent
! the counting of the same oxygen i, k, and m
          do o=m+1,nat
            if (field1(o).eq.3) then
! If-loop 1 = If the value of field1 array is 3
            do p=1,numelem(o)
              if (((field1(neighborlist1(o,p)).eq.4).and.(neighborlist2(o,p).ge.0.5)).or.((field1(neighborlist1(o,p)).eq.1).and.(neighborlist2(o,p).ge.0.3))) then
! If-loop 2 = If the value of field1 array at neighborlist1(o,p)-th index is
! 4 and corresponding neighborlist2(o,p) value is greater than 0.5. Or, if
! the value of field1 array at neighborlist1(o,p)-th index is 1 and
! corresponding neighborlist2(o,p) value is greater than 0.3 then
              if ((r1/=neighborlist1(o,p)).and.(r2/=neighborlist1(o,p)).and.(r3==neighborlist1(o,p))) then
! If-loop3 = If the neighborlist1(o,p) contains the r3 but not r1 & r2  =>
! This means the i, r1, k, r2, m, and r3, six elements are connected.
! But I'm not sure if this is a proper way to check include/exclude
              r4=neighborlist1(o,p) ! but only if the r4 is not r3
! If all three loops are satisfied, then store the element of neighborlist1(
! o,p) to the r4. While doing this, I wish to exclude r3 from r4.
! But I don't know how to do this.
              if (r4=neighborlist1(i,j)) then
! Now, if the neighborlist1(i,j), the neighbor list of atom i contains r4
! That means we found the ring of i-r1-k-r2-m-r3-o-r4-i. Count +1
              ncount=ncount+1


! endifs and enddos for all loops
write(151,40) iframe,ncount
goto 100

 

jimdempseyatthecove
Black Belt
1,115 Views

From your comments about the missing endif and end do statements I (we) assume you mean this:

 

open(1,file="rawdata.txt",status='old')
iframe=0
100  continue
iframe=iframe+1

nat=9000 ! integer

do i=1,nat
  read (1,*)
  field1(i),numelem(i),(neighborlist1(i,j),j=1,numelem(i)),(neighborlist2(i,j),j=1,numelem(i))
enddo

r1=0
r2=0
r3=0
r4=0
ncount=0


! First do loop for the first oxygen
do i=1,nat
  if (field1(i).eq.3) then
    ! If-loop 1 = If the value of field1 array is 3
    do j=1,numelem(i)
      if (((field1(neighborlist1(i,j)).eq.4).and.(neighborlist2(i,j).ge.0.5)).or.((field1(neighborlist1(i,j)).eq.1).and.(neighborlist2(i,j).ge.0.3))) then
        ! If-loop 2 = If the value of field1 array at neighborlist1(i,j)-th index is
        ! 4 and corresponding neighborlist2(i,j) value is greater than 0.5. Or, if
        ! the value of field1 array at neighborlist1(i,j)-th index is 1 and
        ! corresponding neighborlist2(i,j) value is greater than 0.3 then
        r1=neighborlist1(i,j)
        ! If 2 if loops are satisfied, then store the element of neighborlist1(i,j)
        ! to integer variable r1.

        ! Second do loop for the second oxygen. Use i+1 for indexing to prevent
        ! the counting of the same oxygen atom i.
        do k=i+1,nat
          if (field1(k).eq.3) then
            ! If-loop 1 = If the value of field1 array is 3
            do l=1,numelem(k)
              if (((field1(neighborlist1(k,l)).eq.4).and.(neighborlist2(k,l).ge.0.5)).or.((field1(neighborlist1(k,l)).eq.1).and.(neighborlist2(k,l).ge.0.3))) then
                ! If-loop 2 = If the value of field1 array at neighborlist1(k,l)-th index is
                ! 4 and corresponding neighborlist2(k,l) value is greater than 0.5. Or, if
                ! the value of field1 array at neighborlist1(k,l)-th index is 1 and
                ! corresponding neighborlist2(k,l) value is greater than 0.3 then
                if (r1==neighborlist1(k,l)) then
                  ! If-loop3 = If the neighborlist1(k,l) contains the r1 =>
                  ! This means the i, r1, and k, three elements are connected.
                  ! But I'm not sure if this is a proper way to check include/exclude
                  r2=neighborlist1(k,l) ! but only if the r2 is not r1
                  ! If all three loops are satisfied, then store the element of neighborlist1(
                  ! k,l) to the r2. While doing this, I wish to exclude r1 from r2.
                  ! But I don't know how to do this.

                  ! Third do loop for the third oxygen. Use k+1 for indexing to prevent
                  ! the counting of the same oxygen i and k
                  do m=k+1,nat
                    if (field1(m).eq.3) then
                      ! If-loop 1 = If the value of field1 array is 3
                      do n=1,numelem(m)
                        if (((field1(neighborlist1(m,n)).eq.4).and.(neighborlist2(m,n).ge.0.5)).or.((field1(neighborlist1(m,n)).eq.1).and.(neighborlist2(m,n).ge.0.3))) then
                          ! If-loop 2 = If the value of field1 array at neighborlist1(m,n)-th index is
                          ! 4 and corresponding neighborlist2(m,n) value is greater than 0.5. Or, if
                          ! the value of field1 array at neighborlist1(m,n)-th index is 1 and
                          ! corresponding neighborlist2(m,n) value is greater than 0.3 then
                          if ((r1/=neighborlist1(m,n)).and.(r2==neighborlist1(m,n))) then
                            ! If-loop3 = If the neighborlist1(m,n) contains the r2 but not r1 =>
                            ! This means the i, r1, k, and r2, four elements are connected.
                            ! But I'm not sure if this is a proper way to check include/exclude
                            r3=neighborlist1(m,n) ! but only if the r3 is not r2
                            ! If all three loops are satisfied, then store the element of neighborlist1(
                            ! m,n) to the r3. While doing this, I wish to exclude r2 from r3.
                            ! But I don't know how to do this.

                            ! Fourth do loop for the fourth oxygen. Use m+1 for indexing to prevent
                            ! the counting of the same oxygen i, k, and m
                            do o=m+1,nat
                              if (field1(o).eq.3) then
                                ! If-loop 1 = If the value of field1 array is 3
                                do p=1,numelem(o)
                                  if (((field1(neighborlist1(o,p)).eq.4).and.(neighborlist2(o,p).ge.0.5)).or.((field1(neighborlist1(o,p)).eq.1).and.(neighborlist2(o,p).ge.0.3))) then
                                    ! If-loop 2 = If the value of field1 array at neighborlist1(o,p)-th index is
                                    ! 4 and corresponding neighborlist2(o,p) value is greater than 0.5. Or, if
                                    ! the value of field1 array at neighborlist1(o,p)-th index is 1 and
                                    ! corresponding neighborlist2(o,p) value is greater than 0.3 then
                                    if ((r1/=neighborlist1(o,p)).and.(r2/=neighborlist1(o,p)).and.(r3==neighborlist1(o,p))) then
                                      ! If-loop3 = If the neighborlist1(o,p) contains the r3 but not r1 & r2  =>
                                      ! This means the i, r1, k, r2, m, and r3, six elements are connected.
                                      ! But I'm not sure if this is a proper way to check include/exclude
                                      r4=neighborlist1(o,p) ! but only if the r4 is not r3
                                      ! If all three loops are satisfied, then store the element of neighborlist1(
                                      ! o,p) to the r4. While doing this, I wish to exclude r3 from r4.
                                      ! But I don't know how to do this.
                                      if (r4=neighborlist1(i,j)) then
                                        ! Now, if the neighborlist1(i,j), the neighbor list of atom i contains r4
                                        ! That means we found the ring of i-r1-k-r2-m-r3-o-r4-i. Count +1
                                        ncount=ncount+1

                                        ! endifs and enddos for all loops
                                      endif ! if (r4=neighborlist1(i,j)) then
                                    endif ! if ((r1/=neighborlist1(o,p)).and.(r2/=neighborlist1(o,p)).and.(r3==neighborlist1(o,p))) then
                                  endif ! if (((field1(neighborlist1(o,p)).eq.4).and.(neighborlist2(o,p).ge.0.5)).or.((field1(neighborlist1(o,p)).eq.1).and.(neighborlist2(o,p).ge.0.3))) then
                                end do ! do p=1,numelem(o)
                              endif ! if (field1(o).eq.3) then
                            end do ! do o=m+1,nat
                          endif ! if ((r1/=neighborlist1(m,n)).and.(r2==neighborlist1(m,n))) then
                        endif ! if (((field1(neighborlist1(m,n)).eq.4).and.(neighborlist2(m,n).ge.0.5)).or.((field1(neighborlist1(m,n)).eq.1).and.(neighborlist2(m,n).ge.0.3))) then
                      end do ! do n=1,numelem(m)
                    endif ! if (field1(m).eq.3) then
                  end do ! do m=k+1,nat
                endif ! if (r1==neighborlist1(k,l)) then
              endif ! if (((field1(neighborlist1(k,l)).eq.4).and.(neighborlist2(k,l).ge.0.5)).or.((field1(neighborlist1(k,l)).eq.1).and.(neighborlist2(k,l).ge.0.3))) then
            end do ! do l=1,numelem(k)
          endif ! if (field1(k).eq.3) then
        end do ! do k=i+1,nat
      endif ! if (((field1(neighborlist1(i,j)).eq.4).and.(neighborlist2(i,j).ge.0.5)).or.((field1(neighborlist1(i,j)).eq.1).and.(neighborlist2(i,j).ge.0.3))) then
    end do ! do j=1,numelem(i)
  endif ! if (field1(i).eq.3) then
end do ! do i=1,nat
write(151,40) iframe,ncount
goto 100

 

I left your code as was excepting for inserting indentations such as to make the reading of the code easier. Then added the missing endif and end do statements.

 

Should this not reflect your code, please say so.

 

*** Intel Moderator ***

Please inform your webmaster (webmashter) that while inserting language formatted text (e.g. Fortran as above), it is equally important for the readers to be able to copy the formatted text. While Select works "Copy" (Ctrl-C nor Right-Click to get pop-up menue with Paste) does not work. (it deselects the text). Please fix this omission from your web page.

Jim Dempsey

Yeon__Jejoon
Novice
1,058 Views

Thank you, and yes I didn't include endifs and enddos and variable definitions and formats, because I thought they are not related to the question and make the post too long. 

And, I will try to provide a better example next time. Sorry for the inconvenience. 

Yeon__Jejoon
Novice
1,059 Views

You provide code, but it helps if we understand the work of the code. The first 100 lines of the text file should be enough to see what is happening? 

Looking for errors in code is the start, but you need to see the actual run to get all the potential errors.  

>> Regarding the error, the script I wrote does not create an error, but it just prints out 0. In my opinion, print 0 is related to the wrong if-structure (if-structure 3 and if-structure 4). I'm searching for other better logic to get what I want. 

The thing I'm curious is: 

1) I want to check if a specific element A (for example) is included and if a specific element B (for example) is not included in the array. If these include/exclude condition is achieved, then go to next part. I used if-structures like

if ((r1/=neighborlist1(m,n)).and.(r2==neighborlist1(m,n))) then

But I don't know if this is a generally good way to check. 
2) I really don't know how can I assign/set a specified value from array to a variable, except a specific element of that array. 

 

Andreas_Z_
Novice
1,139 Views

Your issues with the implementation in Fortran aside...

The description of one of the goals of your program in the Chemistry context sounds like a problem for which elegant, flexible and quite efficient methods and API already exist within accessible tools from the cheminformatics community.

For example, we use the Epam Indigo API (in Python) to do pattern matching and searches of molecular substructures customized to our specific needs. This can be done using the Simplified molecular-input line-entry system (SMILES) description of a molecule (or a whole list of molecules) and a set of SMARTS to identify and count the structural features we are interested in. While it takes a little time to learn how to apply SMARTS in the beginning, for a Chemistry project, it may be worth the time investment, as it will allow you to write (and in future easily extend) tools for parsing of molecular structures, reactions etc.

While I use Fortran for a lot of other things, for this particular type of application in Chemistry, I suggest you to turn to the Indigo API and/or similar other tools based on the OpenBabel project (written in Python or C/C++). If necessary, you could call your Python program from within a Fortran program (e.g. via command-line execution of a Python script). 

Yeon__Jejoon
Novice
1,058 Views

I don't have that much Python experience as well and I'm already too busy with my other works and writings so... now I'm not sure if I have time to learn more new things about coding and scripting in the near future. But thanks to let me know. I will check these. Speaking of "time investment", do you have a good website link to learn these things you mentioned? 

And, isn't OpenBabel a tool to convert files? I'm OK with converting files and others, but some analyses surely require high level of logic and coding skill... 

Andreas_Z_
Novice
1,002 Views

There are several webpages with information, tutorials and examples for the use of SMARTS on the daylight site, which are very useful. Also, OpenBabel is more than a file converter, it supports SMILES and SMARTS (see here).

However, if you go the route of coding your application in Python, I would use the Epam Indigo toolkit (instead of OpenBable directly); the Indigo website also offers examples and a description of the methods implemented (including code snippets), such as iterating over neighbors of atoms and a method for ignoring/unignoring atoms that have been matched with a certain SMARTS, so that you can avoid matching them again with the same or a different SMARTS (unless desired). That feature allows you to use a while-loop and subsequently identifying all matches for a certain SMARTS (before moving on to the next SMARTS).
In the applications for which we use the Indigo tools, the "ignore atom" feature finds application quite frequently.  For example, to completely represent a molecule by a set of functional groups, making sure that in the end all atoms have been matched once (and only once) to a certain substructure (functional group).
Another useful feature is the highlight/unhighlight option for atoms together with the Indigo renderer for generating images of molecule structures with the highlighted atoms in a different color (allowing for a quick visual check of whether the used SMARTS and substructure matching code do what you intended or not).

Yeon__Jejoon
Novice
928 Views

Thanks for your suggestions. The Indigo toolkit really looks interesting. 

I don't work in biochemistry, I work with metals and ceramics... maybe that is why I'm not familiar with SMARTS and SMILES format. I thought OpenBabel is a tool to convert different formats of geometry or data files for other files, XYZ, LAMMPS data, POSCAR... But anyway, thanks to let me know. 

I will definitely check the Epam Indigo toolkit. Hopefully, I could make a little bit of time during this summer, hopefully... 

mecej4
Black Belt
1,163 Views

Yeon__Jejoon: I fail to understand what you are trying to do from your description.

Fairly early in your post, you said: "But I don't think I wrote properly to get what I want. Especially, I think if-loop 3 and if-loop 4 are definitely wrong. " I find it quite confusing to read that kind of statement -- if you did not explain what you want, how are we to judge if what you call "loops" (but are not actually not loops, just IF constructs) are right or wrong?

Let us start with using the correct names for entities:

  • an IF .. ENDIF block is not a loop;
  • ANY is an intrinsic function, not a command;
  • etc.

Then, proceed to give a general description that a computer programmer/scientist/mathematician would understand, instead of writing a description that only a molecular chemist can understand.

Yeon__Jejoon
Novice
1,156 Views

Fairly early in your post, you said: "But I don't think I wrote properly to get what I want. Especially, I think if-loop 3 and if-loop 4 are definitely wrong. " I find it quite confusing to read that kind of statement -- if you did not explain what you want, how are we to judge if what you call "loops" (but are not actually not loops, just IF constructs) are right or wrong?

>> Honestly I really thought my explanations are well enough for the problem of computer science, as I explained what I wish to do in the comment of the script. And I also wrote 

" So I just used if loop and logical operator /= and ==. But I'm not sure if I'm doing this correctly. " 

"If-loop 4 is wrong, assign/store the elements of the array to a variable except for a specific element. But I'm not sure how can I achieve this... "

May I ask which part was the issue for you? But I admit

"Is there any better way to achieve such loops without using a lot of if-loops? Data size is really huge, I wish to reduce the number of if loops, but I'm not sure if there are any better ways. " This is really wrong. I shouldn't ask like this. 

but are not actually not loops, just IF constructs

>> Obviously, I'm really not good at coding and Fortran. Thanks to let me know. 

mecej4
Black Belt
1,083 Views

A few months ago, there was a post in which a question about deeply nested DO loops was discussed, by "roy437". After some back-and-forth, in that thread it was seen that a Constraint Satisfaction Solver, such as AMPL, was a more efficient tool for obtaining a solution(s) to CSAT problems than deeply nested loops that implement an exhaustive search.

Yeon__Jejoon
Novice
1,048 Views

Thanks to let me know, that link is a very interesting topic and related to one of my problems too. I will read more in-depth too, but I'm not sure if I have time to learn AMPL and other tools in any near future... that is the in fact a huge problem I wish to learn a lot more things but too many other problems to solve...  

jimdempseyatthecove
Black Belt
1,078 Views

Also, in your example code (and my reformatting), when you find a match (and increment ncount), you probably should stop searching for the i index (unless you can have multiple rings joined together at one point).

And, possibly, once you discover a ring, consider setting field1([i,r1,k,r2,m,r3,o,r4])=-3 or some other restorable value to exclude it from the ring search.

Jim Dempsey

Yeon__Jejoon
Novice
1,048 Views

Thank you so much for your suggestion. May I ask how can I achieve stop searching and exclude a value/variable from the search? Could you suggest to me any other examples regarding these comments? 

jimdempseyatthecove
Black Belt
1,011 Views

>>May I ask how can I achieve stop searching and exclude a value/variable from the search?

This was suggested in my post 5-27-2021 05:32 AM... You already have an integer array field1. When the contained value is .NOT. 3, you skip the further testing. The suggestion made was to change the 3 ("possible candidate") into something else. I suggested -3 under the assumption that the field1 array does not contain negative values. you could also use "field1(i) = field1(i) + 90000" or something like that, such that after the counting you can easily restore the field1 array to its original values.

NOTE the above suggested method would exclude a double ring, e.g. something that looks like an 8 from the search. Your problem statement did not address this situation.

Jim Dempsey

Reply