 Mark as New
 Bookmark
 Subscribe
 Mute
 Subscribe to RSS Feed
 Permalink
 Report Inappropriate Content
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
! Ifloop 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
! Ifloop 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
! Ifloop 3 = Among elements of contents1 array that satisfy ifloop 1 and ifloop 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)
! Ifloop 4 = If the ifloop 1, ifloop 2, and ifloop 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 ifloop 3 and ifloop 4 are definitely wrong.
For ifloop 3, I tried ANY command but this gives me the error
An arrayvalued 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.
Ifloop 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 ifloops? 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.
Link Copied
 « Previous

 1
 2
 Next »
 Mark as New
 Bookmark
 Subscribe
 Mute
 Subscribe to RSS Feed
 Permalink
 Report Inappropriate Content
Consider using a contained procedure (contained function) as filter, and use CYCLE to improve clarity in coding:
*** Untested code follows:
subroutine YourSubroutineNameHere(your args here)
...
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
next_i: do i=1,nat
if (field1(i).ne.3) cycle ! next i
! Ifloop 1 = If the value of field1 array is 3
do j=1,numelem(i)
if (isNotCandidate(i,j)) cycle
! 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, (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)
! 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).ne.3) cycle ! next k
! Ifloop 1 = If the value of field1 array is 3
do l=1,numelem(k)
if (isNotCandidate(k,l)) cycle ! next l
! Ifloop 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.ne.neighborlist1(k,l)) cycle
! Ifloop3 = 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).ne.3) cycle ! next m
! Ifloop 1 = If the value of field1 array is 3
do n=1,numelem(m)
if (isNotCandidate(m,n)) cycle ! next n
! Ifloop 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)).or.(r2==neighborlist1(m,n))) cycle
! Ifloop3 = 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).ne.3) cycle ! next o
! Ifloop 1 = If the value of field1 array is 3
do p=1,numelem(o)
if (isNotCandidate(o,p)) cycle ! next p
! Ifloop 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)).or.(r2==neighborlist1(o,p)).or.(r3==neighborlist1(o,p))) cycle
! Ifloop3 = 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 ir1kr2mr3or4i. Count +1
ncount=ncount+1
cycle next_i
endif ! if (r4=neighborlist1(i,j)) then
end do ! do p=1,numelem(o)
end do ! do o=m+1,nat
end do ! do n=1,numelem(m)
end do ! do m=k+1,nat
end do ! do l=1,numelem(k)
end do ! do k=i+1,nat
end do ! do j=1,numelem(i)
end do ! do i=1,nat
write(151,40) iframe,ncount
goto 100 ! read in next batch (consider replacing with DO loop exiting on EOF or flag in data file)
! ...
return ! from subroutine
! At bottom of procedure (but not after end ....) insert a contained procedure
contains
logical function isNotCandidate(x, y)
integer :: x, y
isNotCandidate = .not. (((field1(neighborlist1(x,y)).eq.4).and.(neighborlist2(x,y).ge.0.5)).or.((field1(neighborlist1(x,y)).eq.1).and.(neighborlist2(x,y).ge.0.3)))
end function isNotCandidate
end subroutine YourSubroutineNameHere
Also...
The above does not consider (permit) joined rings (where a same neighbor pair is a segment of two or more rings).
A fair amount of work is performed counting the number of rings, you might want to have an array (e.g. integer::ring(8,:)) to store the values of i, r1, k, r2, m, r3, o, r4 in index ncount after incrementing ncount.
Jim Dempsey
 Mark as New
 Bookmark
 Subscribe
 Mute
 Subscribe to RSS Feed
 Permalink
 Report Inappropriate Content
I really appreciate your help and suggestions for my question. May I ask questions about your replies?
1) Example code structures.
I found that the direction of logical operators is opposite from my example. For example, you are using .ne., not .eq., for field1 check. Is there any reason behind this? Or is this just you modified the script to use it as an example?
2) Regarding modifying/changing field 1 to exclude searched atoms
Thanks for the suggestion.
Do you think would it be better to perform this exclusion right after if ifstructure such as
do i=1,nat
if (field1(i).eq.3) then
field1(i).eq.3
...
do m=1,nat
if (field1(m).eq.3) then
field1(m).eq.3
...
r2=neighborlist1(k,l)
field1(r2).eq.3
...
Or, would it be better to exclude all together after the ring is found, such as your
field1([i,r1,k,r2,m,r3,o,r4])=3 (after ncount+1)
example?
3) Regarding the 8shaped ring comment.
I also thought the prevention of reuse of an atom would resolve this issue. That is why I was escaping from the use of the same oxygen by indexing i, k=i+1, m=k+1... But I was not sure (and still I'm not sure) about r1, r2, r3, and r4. That was why I asked the following question in the original post: how can I store/assign the elements of the array to the value except for a specific value(s) I declare? I wrote this in the comment of the example code also.
For example, I really wish to exclude r1 and r2 when I define r3 as r3=neighborlist1(m,n). There are some atoms that include r1, r2, and r3 in the neighborlist1. But if I include r1 and r2 to r3, that will make an 8shape ring. But I don't know how can I exclude r1 and r2 when I define r3 as r3=neighborlist1(m,n). I really don't know how to do that. That is one of the questions that I really wish to know the answer.
If I finish the logic for such escaping from the use of the same atom, including r1, r2, r3, and r4, then my code should be able to prevent an 8shaped ring.
You suggested modifying field1 values. If I use the exclusion you suggested, like
field1([i,r1,k,r2,m,r3,o,r4])=3
or
field1(r2)=3
Would this resolve the situation I asked about the "store/assign the elements of the array to the value except for a specific value"?
Again, thank you so much for your suggestions.
 Mark as New
 Bookmark
 Subscribe
 Mute
 Subscribe to RSS Feed
 Permalink
 Report Inappropriate Content
>>I found that the direction of logical operators is opposite from my example. For example, you are using .ne., not .eq., for field1 check. Is there any reason behind this?
I though the code example was selfobvious. You had:
do loopIndexing
if (satisfyingExpression) then
...
do otherLoopIndexing
... etc nested several layers deep
end do otherLoopIndexing
end do loopIndexing
in your case you span many statements (with increasing IF level nesting) before it becomes obvious that the nonmatching expression simply advances the loop indexing.
Whereas in my suggestion, CYCLE is used on the nonmatching expression, thus eliminating the IF nesting. This makes the code much easier to read by eliminating the IF nesting.
>>2) (when to flag field1 entry with "don't consider"
This really needs to be done after identifying a ring *** provided that you are not also counting double rings (where a segment of one ring, is also a segment of another ring).
>>3 Regarding the 8shaped ring comment.
I also thought the prevention of reuse of an atom would resolve this issue.
The question I asked was if you wanted to permit the counting of 8shape rings (not how best to exclude counting such rings).
If you require that no atom be (counted as) a member of multiple rings, then set all ring atoms to the "exclude flag". Doing so takes the CYCLE on the next DO I iteration (very fast path).
Note, if you are looking for double/triple/... rings and/or rings of different lengths, then consider changing the ring detection algorithm to a recursive method then have a list of array of ring finds where you store the ring path integer :: rings(maxAtomsInRing, nAtoms/3). You would need to terminate recursion at maxAtomeInRing (and preclude counting larger rings, that are not of interest), The ring attoms are stored: first, next, ..., last, 0,0,...,0,ncount). Or in place of an integer array, store the list of indexes as (allocatable) CHARACTERs.
Jim Dempsey
 Subscribe to RSS Feed
 Mark Topic as New
 Mark Topic as Read
 Float this Topic for Current User
 Bookmark
 Subscribe
 Printer Friendly Page
 « Previous

 1
 2
 Next »