Fortran OOP no reasons compilation aborted - visual-studio

So I have a module for an allocatable class array. When I try to access that array from the module where the class is, I get a compilation aborted without reason. I guess its may be related to the module with the array also using the module, so it is in some kind of recursion when I call the module from the module with the class. compilation aborted from VS community 2019
One may ask why I have a dedicated module for the class array, this is actually to prevent recursion with the class. As I have tried having the array in a more general module as global value, but it would lead to a crash related to nested too deep.
The module with the array:
module sys2_moleculesArray
use type3_crossMol_class, only: type3_crossMol
implicit none
class(type3_crossMol),dimension(:),allocatable :: type3_crossMol_tagArray
end module sys2_moleculesArray
parts of the class array:
module type3_crossMol_class
use sys2_paramData
use sys2_type3ParamData
implicit none
...
type :: type3_crossMol
integer(kind=4) :: index,x,y,rotType,checkMol_index
integer,dimension(4,2) :: molBondedTo
integer,dimension(20) :: potentialNeighMol
contains
procedure :: initialise => initialise
procedure :: addAtom => addAtom
procedure :: getPotentialNeigh => getPotentialNeigh
procedure :: test => test
end type type3_crossMol
contains
...
subroutine test(this)
use sys2_type3ParamData, only:cur_type3_mol_number
use sys2_moleculesArray
implicit none
integer :: n
class(type3_crossMol):: this
do n=1,cur_type3_mol_number
print*, "b4 potential",type3_crossMol_tagArray(n)%index
end do
end subroutine test
I guess I can do what I want to do by doing the array manipulation outside the module with the class, but I would like to keep the code sort of organised, with the subroutine inside the class. So any help regarding the issue, at least a more detail reason, would be great!

You apparently have a circular dependency.
module sys2_moleculesArray uses type3_crossMol_class
module type3_crossMol_class uses sys2_moleculesArray
which one should be compiled first?
Weird that VS doesn't have a mechanism to check that, though.

Related

How to pass a list to a subroutine in BASIC-256

I am having difficulty passing a list to a subroutine (embarrassment); I get a compiler error. I have followed the BASIC-256 documentation on arrays (http://doc.basic256.org/doku.php?id=en:arrays) and included the [] brackets in the subroutine argument as required:
subroutine print_list(list) # or subroutine print_list(list[]) <----- **compiler** error occurs here
for element=0 to list[?]-1
print list[element]
next element
end subroutine
subroutine main()
list = {5.9, 6.0, 5.9, 5.7, 5.6, 5.7}
call print_list(list[]) # <----- **compiler** error occurs here
end subroutine
call main()
The compiler complains that I have an error in the subroutine call argument part.
I have tried fixing this by; (i) checking my initialization of the list; (ii) checking the subroutine definition and parameters (compiler doesn't like the square brackets there either); (iii) excluding the [] brackets from the argument and (iv) tried contacting the BASIC-256 Facebook page.
Thank you for your time....
Based on the info on the site, you cannot pass arrays to your own subroutines, only internal (built-in) ones.
If the variables are global in nature, you're fine, just perform whatever actions you want on the array, but if they needed to be local, it can't be done with this particular variation of BASIC.
Having read the documentation thoroughly there is a function called 'ref' that allows you to pass a variable or array by reference to a function or subroutine. Doing this allows me to print the array content.
Here's my previous code re-written to pass the array by reference:
subroutine print_list(list)
for element=0 to list[?]-1
print list[element]
next element
end subroutine
subroutine main()
list = {5.9, 6.0, 5.9, 5.7, 5.6, 5.7}
call print_list(ref(list))
end subroutine
call main()
When passing an array of data you must include an empty set of brackets [] after the variable name. This was added to reduce the confusion between a regular variable and a variable containing an array of values.
So, in your case, change your method signature from subroutine print_list(list) to subroutine print_list(list[]).
Referring to this link in case you have any other questions.

Conditionally defining functions in Ruby

I have some code that is run in one of a few different locations: as a command line tool with debug output, as part of a larger program that doesn't take any output, and in a rails environment.
There are occasions where I need to make slight changes to the code based on its location, and I realized the following style seems to work:
print "Testing nested functions defined\n"
CLI = true
if CLI
def test_print
print "Command Line Version\n"
end
else
def test_print
print "Release Version\n"
end
end
test_print()
This results in:
Testing nested functions defined
Command Line Version
I've never come across functions that are defined conditionally in Ruby. Is this safe to do?
This isn't how I'm structuring most of my code, but there are a few functions that require complete rewrites per-system.
I don't think that is a clean way.
My suggestion is to define the same sets of methods (with different definition bodies) in different modules, and conditionally include the relevant module into the class/module you are going to call the methods from.
module CLI
def test_print
... # definition for CLI
end
end
module SomeOtherMode
def test_print
... # definition for some other mode
end
end
class Foo
include some_condition ? CLI : SomeOtherMode
end
Foo.new.test_print
If you are only going to use only one mode per run, and think that it is a waste to define the modules that end up not being used, then you can take a further step; define respective modules (CLI, SomeOtherMode, ...) in separate files, and use autoload.
autoload :CLI, "path/to/CLI"
autoload :SomeOtherMode, "path/to/SomeOtherMode"
It's a form of meta-programming and is generally safe. The real risk is not if it will work as expected, but in testing all the variations you create.
The example you've given here makes it impossible to execute the alternate version. To properly exercise both methods you need a way to force the injection of one or the other.

Ruby C extension: Is there a way to finalize?

I have been through all the documents on Ruby C extensions that I can find to no good end.
Is there a complement to the Init_... method of initializing a C extension that is called as the interpreter exits?
Ruby code can use Kernel#at_exit.
at_exit { puts "This code runs when Ruby exits." }
The implementation of Kernel#at_exit in eval_jump.c calls a C function, rb_set_end_proc(). This function is public, so you can call it from your own C code. The declaration is
void rb_set_end_proc(void (*)(VALUE), VALUE);
The first argument is a pointer to your C function (to get called when Ruby exits). The second argument is a Ruby value to pass to your C function.
There is no general "interpreter exiting" hook. But Ruby does garbage-collect everything on a normal exit, including Module and Class objects, and there is a way to hook object garbage collection. So you could adapt the following code that applies equally to Ruby interpreted objects or those defined by a C library:
module MyLib
end
ObjectSpace.define_finalizer( MyLib, proc { puts "MyLib unloaded" } )
You will need to take care to avoid assumptions that other Module or Class objects you expect to have available still exist when running this code, you are not in full control of the order in which this will get called on program exit.

Fortran - explicit interface

I'm very new to Fortran, and for my research I need to get a monster of a model running, so I am learning as I am going along. So I'm sorry if I ask a "stupid" question.
I'm trying to compile (Mac OSX, from the command line) and I've already managed to solve a few things, but now I've come across something I am not sure how to fix. I think I get the idea behind the error, but again, not sure how to fix.
The model is huge, so I will only post the code sections that I think are relevant (though I could be wrong). I have a file with several subroutines, that starts with:
!==========================================================================================!
! This subroutine simply updates the budget variables. !
!------------------------------------------------------------------------------------------!
subroutine update_budget(csite,lsl,ipaa,ipaz)
use ed_state_vars, only : sitetype ! ! structure
implicit none
!----- Arguments -----------------------------------------------------------------------!
type(sitetype) , target :: csite
integer , intent(in) :: lsl
integer , intent(in) :: ipaa
integer , intent(in) :: ipaz
!----- Local variables. ----------------------------------------------------------------!
integer :: ipa
!----- External functions. -------------------------------------------------------------!
real , external :: compute_water_storage
real , external :: compute_energy_storage
real , external :: compute_co2_storage
!---------------------------------------------------------------------------------------!
do ipa=ipaa,ipaz
!------------------------------------------------------------------------------------!
! Computing the storage terms for CO2, energy, and water budgets. !
!------------------------------------------------------------------------------------!
csite%co2budget_initialstorage(ipa) = compute_co2_storage(csite,ipa)
csite%wbudget_initialstorage(ipa) = compute_water_storage(csite,lsl,ipa)
csite%ebudget_initialstorage(ipa) = compute_energy_storage(csite,lsl,ipa)
end do
return
end subroutine update_budget
!==========================================================================================!
!==========================================================================================!
I get error messages along the lines of
budget_utils.f90:20.54:
real , external :: compute_co2_storage
1
Error: Dummy argument 'csite' of procedure 'compute_co2_storage' at (1) has an attribute that requires an explicit interface for this procedure
(I get a bunch of them, but they are essentially all the same). Now, looking at ed_state_vars.f90 (which is "used" in the subroutine), I find
!============================================================================!
!============================================================================!
!---------------------------------------------------------------------------!
! Site type:
! The following are the patch level arrays that populate the current site.
!---------------------------------------------------------------------------!
type sitetype
integer :: npatches
! The global index of the first cohort in all patches
integer,pointer,dimension(:) :: paco_id
! The number of cohorts in each patch
integer,pointer,dimension(:) :: paco_n
! Global index of the first patch in this vector, across all patches
! on the grid
integer :: paglob_id
! The patches containing the cohort arrays
type(patchtype),pointer,dimension(:) :: patch
Etc etc - this goes one for another 500 lines or so.
So to get to the point, it seems like the original subroutine needs an explicit interface for its procedures in order to be able to use the (dummy) argument csite. Again, I am SO NEW to Fortran, but I am really trying to understand how it "thinks". I have been searching what it means to have an explicit interface, when (and how!) to use it etc. But I can't figure out how it applies in my case. Should I maybe use a different compiler (Intel?). Any hints?
Edit: So csite is declared a target in all procedures and from the declaration type(site type) contains a whole bunch of pointers, as specified in sitetype. But sitetype is being properly used from another module (ed_state_vars.f90) in all procedures. So I am still confused why it gives me the explicit interface error?
"explicit interface" means that the interface to the procedure (subroutine or function) is declared to the compiler. This allows the compiler to check consistency of arguments between calls to the procedure and the actual procedure. This can find a lot of programmer mistakes. You can do this writing out the interface with an interface statement but there is a far easier method: place the procedure into a module and use that module from any other entity that calls it -- from the main program or any procedure that is itself not in the module. But you don't use a procedure from another procedure in the same module -- they are automatically known to each other.
Placing a procedure into a module automatically makes its interface known to the compiler and available for cross-checking when it is useed. This is easier and less prone to mistakes than writing an interface. With an interface, you have to duplicate the procedure argument list. Then if you revise the procedure, you also have to revise the calls (of course!) but also the interface.
An explicit interface (interface statement or module) is required when you use "advanced" arguments. Otherwise the compiler doesn't know to generate the correct call
If you have a procedure that is useed, you shouldn't describe it with external. There are very few uses of external in modern Fortran -- so, remove the external attributes, put all of your procedures into a module, and use them.
I ran into the same problems you encountered whilst I was trying to install ED2 on my mac 10.9. I fixed it by including all the subroutines in that file in a module, that is:
module mymodule
contains
subroutine update_budget(csite,lsl,ipaa,ipaz)
other subroutines ecc.
end module mymodule
The same thing had to be done to some 10 to 15 other files in the package.
I have compiled all the files and produced the corresponding object files but now I am getting errors about undefined symbols. However I suspect these are independent of the modifications so if someone has the patience this might be a way to solve at least the interface problem.

Fortran dynamic objects

I am trying to create a subroutine that returns data as a pointer:
I want something like that:
subroutine f(p)
type(tra), pointer p
type(tra), target :: instance
p=>instance
do_work(instance)
end subroutine
Strictly speaking I want to implement analogue of c++ "new" operator.
I want then to use such a subroutine as follows:
subroutine other
type(tra), pointer :: p1,p2
call f(p1)
call f(p2)
end subroutine
The above code may not work, as I suppose "instance" inside f is destroyed after f quits, and the next call of f creates "instance" again in the same place in memory.
In particular I find with p1 and p2 pointing to the same objects, but I guess this is compiler-dependent. Is it true?
I think that a possible solution is:
subroutine f(p)
type(tra), pointer p
type(tra), allocatable, target :: instance(:)
p=>instance(1)
do_work(instance(1))
end subroutine
Is this the "official" way of doing things?
Strictly speaking I want to implement analogue of c++ "new" operator.
It is ALLOCATE. The thing you are trying to do should be simply this:
subroutine f(p)
type(tra), pointer :: p
! you can actually leak memory this way! caution required.
if(associated(p)) then
stop "possible memory leak - p was associated"
end
allocate(p)
do_work(p)
end subroutine
The above code may not work, as I suppose "instance" inside f is destroyed after f quits, and the next call of f creates "instance" again in the same place in memory.
No, this is not true. Local subroutine variables are usually "allocated" once (and even initialized only once), see e.g. Fortran 90 spec, chapter 14, especially section 14.7.

Resources