Prev: buy cheap Ambien without prescription, order Ambien cod fedex, prescription Ambien paypal
Next: calling readline(3c) from fortran
From: Enthalpy on 28 Mar 2010 18:37 Hello! Thanks for all the answers, they're stimulating. My initial post was not so "direct" because I was trying to investigate the options to carry out my task. Let me say that I'd like to keep as efficient as possible my code together with the ability to select at runtime the set of equations from a number of implemented procedures. So I'd discard (at least for now) the fascinating option to use/write an interpreter as suggested by Glen and Jugoslav because of the detrimental effect on the performance and (not least) because of the complexity that it would imply for my limited coding abilities. The solutions suggested by Eli and Arjen are also interesting but not cross-platform. I also store these options for a potential "plan B", since I'm coding on a GNU/Linux box but I'm planning to make the program available also for Windows OSs (with the minimum effort, hopefully). So I went back on my initial idea to use pointers to select at runtime the necessary items (unknowns, equations, parameters) and then I bumped into the necessity to use the pointers to procedures F03 feature. I'm on Ubuntu Karmic 9.10 and I use the GNU compilers (gfortran and g95) at these version $ gfortran -v Using built-in specs. Target: i486-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.1-4ubuntu9' --with-bugurl=file:///usr/share/doc/gcc-4.4/ README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/ usr --enable-shared --enable-multiarch --enable-linker-build-id --with- system-zlib --libexecdir=/usr/lib --without-included-gettext --enable- threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program- suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-targets=all --disable-werror --with- arch-32=i486 --with-tune=generic --enable-checking=release -- build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu Thread model: posix gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu9) $ g95 -v Using built-in specs. Target: Configured with: ../configure --enable-languages=c Thread model: posix gcc version 4.0.3 (g95 0.91!) Feb 26 2008 Unfortunately, gfortran (at the version packaged on Ubuntu Karmic) doesn't support procedure pointers, so I have just g95 to play with. I think I need an /array/ of procedure pointers, but I unpleasantly realised they are not supported by the F03 standard since the DIMENSION attribute is not applicable together with the PROCEDURE one (correct me if I'm wrong, I'd be pleased to learn that). Exemplifying, it should *not* be valid the following line: PROCEDURE (prototype), DIMENSION(:), POINTER :: fp I'm really disappointed that even F03 is missing this feature. I found an "ACM SIGPLAN Fortran Forum" article with a suggestive title "Note on creating an array of procedure pointers" (http://doi.acm.org/ 10.1145/1520752.1520753) but unfortunately I'm just a student and I cannot afford the price of the paper (my ACM web account seems not to be enough); if someone would be so generous to email it to me, I would be very grateful to him/her... Anyway I tried another solution: to encapsulate in a derived type the procedure pointer and then build an array of the aforementioned derived type: TYPE :: arr_fptr PROCEDURE (prototype), POINTER :: fp END TYPE arr_fptr ABSTRACT INTERFACE FUNCTION prototype() INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND(15,100) REAL(dp) :: prototype END FUNCTION prototype END INTERFACE TYPE(arr_fptr), DIMENSION(5), SAVE :: funcp but it fails at the first assignment funcp(1)%fp => maci_mflow_tg() ! maci_mflow_tg is function with no actual/dummy arguments (parameters are passed via module association). It is an implemented equation. with the following error: "Any component to the right of a parent or component of nonzero rank must not have the POINTER attribute." Finally I came out with the solution to use a linked list of pointers to procedures (please note this is just a *crude* version, without the ISTAT clause --- for example --- and other good programming practices that I'll add once the code will work correctly): TYPE :: eqns_list PROCEDURE (prototype), POINTER :: fp TYPE(eqns_list), POINTER :: next END TYPE eqns_list ABSTRACT INTERFACE FUNCTION prototype() INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND(15,100) REAL(dp) :: prototype END FUNCTION prototype END INTERFACE TYPE(eqns_list), POINTER, SAVE :: head, tail, temp ALLOCATE(head) tail => head NULLIFY(tail%next) tail%fp => maci_mflow_tg() ALLOCATE(tail%next) tail => tail%next NULLIFY(tail%next) tail%fp => maci_Tc() ALLOCATE(tail%next) tail => tail%next NULLIFY(tail%next) tail%fp => maci_lvlv() ALLOCATE(tail%next) tail => tail%next NULLIFY(tail%next) tail%fp => maci_pmec() ALLOCATE(tail%next) tail => tail%next NULLIFY(tail%next) tail%fp => maci_mu() (snip) temp => head DO i = 1 IF ( .NOT. ASSOCIATED(temp) ) EXIT funcv(i) = temp%fp() i = i + 1 temp => temp%next END DO (snip) But even this very reasonable option ends up in a compile time error: tail%fp => maci_mflow_tg() 1 Error: Different types in pointer assignment at (1) (snip) Could you help me with that, please? Do you have any suggestion to improve the efficiency of the code I posted above? Is there a better way to achieve the same goal preserving efficiency and portability? Thank you very much. PS: The unknowns are selected using a derived type: TYPE :: arr_ptr REAL(dp), DIMENSION(:), POINTER :: p END TYPE arr_ptr TYPE(arr_ptr), SAVE :: xp ALLOCATE( xp%p(5) ) xp%p(1) = lvlv xp%p(2) = ps xp%p(3) = pc xp%p(4) = mu xp%p(5) = Tc Again, just a crude implementation, refinement is necessary if the code proves to work.
From: James Van Buskirk on 28 Mar 2010 21:02 "Enthalpy" <epagone(a)email.it> wrote in message news:bb55b7e1-cf18-4238-96a0-7faad68232b5(a)x12g2000yqx.googlegroups.com... > Anyway I tried another solution: to encapsulate in a derived type the > procedure pointer and then build an array of the aforementioned > derived type: > TYPE :: arr_fptr > PROCEDURE (prototype), POINTER :: fp > END TYPE arr_fptr > ABSTRACT INTERFACE > FUNCTION prototype() > INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND(15,100) > REAL(dp) :: prototype > END FUNCTION prototype > END INTERFACE > TYPE(arr_fptr), DIMENSION(5), SAVE :: funcp > but it fails at the first assignment > funcp(1)%fp => maci_mflow_tg() ! maci_mflow_tg is function with no > actual/dummy arguments (parameters are passed via module association). > It is an implemented equation. > with the following error: "Any component to the right of a parent or > component of nonzero rank must not have the POINTER attribute." Unless maci_mflow_tg is a function returning a procedure pointer result, you want funcp(1)%fp => maci_mflow_tg above, without the parentheses. -- write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, & 6.0134700243160014d-154/),(/'x'/)); end
From: Tobias Burnus on 29 Mar 2010 03:01 Hello, Enthalpy wrote: > gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu9) > > Unfortunately, gfortran (at the version packaged on Ubuntu Karmic) > doesn't support procedure pointers That's not completely true. GCC 4.4.x supports procedure pointers - except for functions returning procedure pointers and for procedure-pointer components. (The latter is what you use.) GCC 4.5 also supports the remaining bits - including PASS. > TYPE :: arr_fptr > PROCEDURE (prototype), POINTER :: fp > END TYPE arr_fptr > ABSTRACT INTERFACE > FUNCTION prototype() Add a NOPASS in the PROCEDURE statement as "prototype" does not have "type(arr_fptr)" as first argument. While g95 does not seem to care, gfortran 4.5, ifort 11.1 and the standard do ;-) Tobias
From: Enthalpy on 29 Mar 2010 09:00 James, This is the maci_mflow_tg function: REAL(dp) FUNCTION maci_mflow_tg() maci_mflow_tg = eta_m_t * eta_is_t * Ts * (ONE - ( pa/ps )**( (k-ONE)/ k ) ) - ( Tc-Ta )/eta_m_c END FUNCTION maci_mflow_tg I tried to "point" it without the parentheses TYPE :: arr_fptr PROCEDURE (prototype), POINTER :: fp => NULL() END TYPE arr_fptr ABSTRACT INTERFACE FUNCTION prototype() INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND(15,100) REAL(dp) :: prototype END FUNCTION prototype END INTERFACE TYPE(arr_fptr), DIMENSION(5), SAVE :: funcp (snip) funcp(1)%fp => maci_mflow_tg funcp(2)%fp => maci_Tc funcp(3)%fp => maci_lvlv funcp(4)%fp => maci_pmec funcp(5)%fp => maci_mu and it compiles correctly, many thanks! Deleting the parentheses corrects also the linked list "version" :D . Just a question, still. How can I nullify the procedure pointer, when needed (could it be necessary, indeed??)? Compilation fails either if I use the funcp(:)%fp => NULL() and NULLIFY( funcp(:)%fp ) lines. Output of g95: funcp(:)%fp => NULL() 1 Error: Component to the right of a part reference with nonzero rank must not have the POINTER attribute at (1) By the way, the url at the head of your post returns a 502 error; what is that link about? Tobias, On Mar 29, 9:01 am, Tobias Burnus <bur...(a)net-b.de> wrote: (snip) > That's not completely true. GCC 4.4.x supports procedure pointers - > except for functions returning procedure pointers and for > procedure-pointer components. (The latter is what you use.) GCC 4.5 also > supports the remaining bits - including PASS. thanks for pointing out this; trying to shorten the previous post my sentences became not so clear and prone to misunderstandings. > > TYPE :: arr_fptr > > PROCEDURE (prototype), POINTER :: fp > > END TYPE arr_fptr > > ABSTRACT INTERFACE > > FUNCTION prototype() > > Add a NOPASS in the PROCEDURE statement as "prototype" does not have > "type(arr_fptr)" as first argument. While g95 does not seem to care, > gfortran 4.5, ifort 11.1 and the standard do ;-) > > Tobias I thought the PASS/NOPASS attribute was necessary just when the CONTAINS statement is present in a derived type definition (Chapman, "Fortran 95-2003 for scientists and engineers (3rd ed.)"); am I wrong? All, some posts ago I've got no solution to my problem, instead now I have (potentially) two options: the linked list and the array of derived type procedure pointers. Which one do you suggest me to implement according to (sorted by importance): 1. performance; 2. reliability; 3. code maintenance (in other words, clarity); 4. neatness. Thanks again for your patience. Emanuele
From: James Van Buskirk on 29 Mar 2010 10:19
"Enthalpy" <epagone(a)email.it> wrote in message news:3ab7e1de-e269-483b-8c6b-f9eb90acd698(a)30g2000yqi.googlegroups.com... > Just a question, still. How can I nullify the procedure pointer, when > needed (could it be necessary, indeed??)? > Compilation fails either if I use the > funcp(:)%fp => NULL() Yeah, vector pointer assignment and nullification don't work. You could write out a DO loop that nullifies the pointers one at a time, or a subroutine that accepts funcp(:) as an INTENT(OUT) argument: subroutine nullp(fparg) type(arr_fptr), intent(out) :: fparg(:) end subroutine nullp And then when you call nullp(funcp) default initialization that you have written will nullify everybody (I think). But you probably would prefer something like: funcp = arr_fptr(NULL())) which should do the trick via intrinsic assignment. No time to test today, though. -- write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, & 6.0134700243160014d-154/),(/'x'/)); end |