zerothi / fdict Goto Github PK
View Code? Open in Web Editor NEWFortran type-free variable and type-free dictionary
Home Page: http://zerothi.github.io/fdict
License: Mozilla Public License 2.0
Fortran type-free variable and type-free dictionary
Home Page: http://zerothi.github.io/fdict
License: Mozilla Public License 2.0
This enables concatenating different dictionaries without disrupting either of the dictionaries and allows entries to refer to the same value.
Note that this requires a certain amount of restructuring as then the linked list is not easily retained.
There are a few issues that should be resolved to make importing find_package
and FetchContent
equivalent:
fdict
-> fdict::fdict
FDICT_INSTALL
, FDICT_SHARED_LIBS
to control how fdict
is being builtfdictConfig.cmake
using return(PROPAGATE)
or set(PARENT_SCOPE)
I used cmake 27 (on ROCKY 8 OS) to compile siesta-master. All libraries were fetched from gitlab automatically by the code. I see following error:
[ 27%] Building Fortran object Src/easy-fdict/CMakeFiles/siesta-libfdict.dir/dictionary.f90.o
[ 27%] Linking Fortran static library libsiesta-libfdict.a
[ 27%] Built target siesta-libfdict
gmake: *** [Makefile:146: all] Error 2
my cmake command:
cmake -S. -B_build -DCMAKE_INSTALL_PREFIX=/home/reza/siesta_master -DWITH_DFTD3=OFF -DWITH_LIBXC=OFF -DWITH_FLOOK=OFF -DSIESTA_TOOLCHAIN=/home/reza/siesta-master/Config/cmake/toolchains/intel.cmake -DWITH_MPI=ON -DSCALAPACK_LIBRARY="-L/opt/intel_2020/compilers_and_libraries_2020.4.304/linux/mkl/lib/intel64 -lmkl_scalapack_lp64 -lmkl_blacs_intelmpi_lp64 -ldl -lm"
I used intel cluster studio 2020 on a SMP HP server with 44 real core.
my build command:
cmake --build _build -j 44
Any idea?
Thanks
Reza
There needs to be API documentation
Is it possible to do, e.g. what are minimum changes need to extect dictionary_t
to make it strongly typed and give a compilation error if the wrong constructor, assign, contains interfaces are used.
The current makefile script is rather fragile (albeit easily customizable).
I wish to extend this to easier enable automatic installation.
Hi!
Sorry for that (maybe) stupid question but I'm trying to compile the library with ifort
and I have no clue how. I've tried to do FC=intel
and FC=ifort
within the setup.make
but without success. What am I doing wrong?
Thanks!
What is the main advantage of using fypp
over the built-in preprocessor (can be enabled by renaming f90
-> F90
)? It would be nice to reduce the dependencies required for the library user, especially those that can not be automated with FetchContent
.
Some useful tooling that could be implemented. Let me know if you want some help with any of these:
Currently it is not possible to have pointers to character(len=*)
.
The problem with this is that the pointer should itself have the corresponding same length specification, otherwise a compiler error will be issued.
It is not so clear what the api for the dictionary
and variable
are. Ideally there should be a table matching the C++/Python interface to the fortran one. Basic API that should be documented:
Those are dictionary
, but for variable
, that does not have a clear C++/Python counterpart, so I'm not sure what needs to be documented.
Hello,
File variable.f90
won't compile when using the Cray Fortran compiler (version 14.0.2):
$ ftn --version
Cray Fortran : Version 14.0.2
$ make FC=ftn FC_SERIAL=ftn
VPATH="." ./setup.sh --default
VPATH="." ./src/variable.sh
gfortran -E -P -x c -I./src -I./src -I. ./src/variable_pp.F90 | sed -f ./src/filter.sed > variable.f90
ftn -c -o variable.o variable.f90
pa1_1 = transfer(this%enc,pa1_1)
^
ftn-928 ftn: ERROR ASSOCIATD_VAR, File = variable.f90, Line = 1511, Column = 1
"PA1_1" is TYPE (PTA1) with a pointer component, so must not be referenced in an assignment statement in a pure subprogram.
pa1_2 = transfer(rhs%enc,pa1_2)
^
ftn-928 ftn: ERROR ASSOCIATD_VAR, File = variable.f90, Line = 1512, Column = 1
"PA1_2" is TYPE (PTA1) with a pointer component, so must not be referenced in an assignment statement in a pure subprogram.
ps0_1 = transfer(this%enc,ps0_1)
^
ftn-928 ftn: ERROR ASSOCIATD_VAR, File = variable.f90, Line = 1516, Column = 1
"PS0_1" is TYPE (PTS0) with a pointer component, so must not be referenced in an assignment statement in a pure subprogram.
[...]
p = transfer(this%enc,p)
^
ftn-928 ftn: ERROR ASSOCIATD_L_C3, File = variable.f90, Line = 3297, Column = 5
"P" is TYPE (PT) with a pointer component, so must not be referenced in an assignment statement in a pure subprogram.
p = transfer(this%enc,p)
^
ftn-928 ftn: ERROR ASSOCIATD_R_C3, File = variable.f90, Line = 3312, Column = 5
"P" is TYPE (PT) with a pointer component, so must not be referenced in an assignment statement in a pure subprogram.
ftn-214 ftn: LIMIT ASSOCIATD_R_C3, File = variable.f90, Line = 3312
The maximum number, 100, of fatal errors has been exceeded.
make: *** [smeka/Makefile.compiler:194: variable.o] Error 1
The explanation of the reported error is:
$ explain ftn-928
Error : "%s" is TYPE (%s) with a pointer component, so must not be referenced
in an assignment statement in a %s subprogram.
A constraint to PURE procedures, prohibits the following:
In a pure subprogram any variable which is in common or accessed
by host or use associate, is a dummy argument to a pure function, is
a dummy argument with INTENT(IN) to a pure subroutine or an object that is
storage associated with any such variable, shall not be used in the
following context:
As the expr of an assignment-stmt in which the variable is of a derived
type if the derived type has a pointer component at any level of
component selection.
By definition, an elemental subprogram is pure, unless IMPURE is specified,
so the above constraints also apply to dummy arguments and variables within
elemental subprograms as long as IMPURE is not specified for the subprogram.
I am not sure that the Cray Compiler is right about this one. While I agree on the marked variables satisfying the requirement stated in the fourth paragraph, variable this
is not "the expr" but an argument to an intrinsic (and hence pure) transformational function, used "in the expr".
I read a few times the original constraint, C1594 of Fortran 2018, and my impression is the same.
Further to that, I tried a MWE (fails with Cray)
module m
implicit none
type :: t
character(len=1), dimension(:), allocatable :: enc
end type t
contains
pure function a(this) result(r)
type(t), intent(in) :: this
logical :: r
type :: pta1
character(len=1), pointer :: p(:) => null()
end type pta1
type(pta1) :: q
q = transfer(this%enc,q)
r = .false.
end function a
end module m
with the NAG Compiler 7.1 (whose strictness is the only comparable to Cray's) and it compiled without issues.
This prevents compilation of SIESTA on LUMI using the Cray Compiler. I guess it would be OK to conditionally comment out the PURE
keyword as a workaround, while we clarify the issue with HPE?
I must say that I compiled and installed the library following the initial guidelines in the readme section of this repository:
FC=gfortran FFLAGS = -g
make
.make PREFIX=/path/to/fdict install
My fortran project, however, is compiled with ifort in a bash file as follows:
ifort -O3 -openmp -c -traceback *.f90 ifort -O3 -openmp -o project_name *.o
I tried modifying the bash file to link the library as follows:
ifort -O3 -openmp -c -I$"/path/to/include/" -traceback *.f90 ifort -O3 -openmp -o project_name *.o $"/path/to/lib/libfdict.a"
However I get this error: This module file was not generated by any release of this compiler. [DICTIONARY] use dictionary
The same error is shown for use variable
.
P.S.: I know you recommended using the code below in a makefile to link the library to the program, but I do not understand how to do it. In what folder do I create this makefile? How does this interact with my program?
FDICT_PATH = /path/to/fdict/parent FDICT_LIBS = -L$(FDICT_PATH) -lfdict FDICT_INC = -I$(FDICT_PATH)
Thank you
Hi,
I do not have much experience with coding in Fortran, so I apologize in advance for the basic level question.
In my case, I have an input file that I read in a subroutine. Each line has this format: 'key1', 'value11', 'value12'. I need to read a new file of this type (being provided by an external program) a few times while the program runs. I would like to store the info from the file in a dictionary to use the key values later in a quick manner.
A subroutine is called to read the new file whenever needed. Now to deal with the dictionary part I have understood that I can either create a new dictionary every time I read the file or I can create it once and then just keep updating it (which is the case when I use pointers). Is the latter more computationally efficient?
Below is my attempt to create the dictionary in the same subroutine where I read the file.
subroutine ...
use dictionary
type(dict) :: dict_1
type(dict) :: dict_2
open(file='input_file.dat', file = 30, status='old') !
read(30,*)
do j=1,no_of_lines
read(30,*) key_string , value1, value2
dict_1= dict_1// (key_string .kv. value1)
dict_2= dict_2// (key_string .kv. value2)
enddo
My doubts are regarding how to:
(1) create one dictionary instead of two to store the info?
(2) create pointers based on the key strings? (Can I easily convert the key_string from string to a variable to make it a pointer?)
(3) call a value from the key later on in the code?
The following snippet clarifies
type(dictionary_t) :: d
d = ('a' .kv. 1) // ('b' .kv. 2) ! no leak
d = d // ('a' .kv. 2) ! leak
d = d // ('c' .kv. 3) ! no leak
I have to see if this may be by passed in some way...
First off thank you for this project! It is EXACTLY what I wanted and much better than my homemade attempt.
I have figured out how to use assign/associate from your tests but would have greatly appreciated a small example of each in the README.md for dictionaries the same way you did for variables. I was confused the .key. and .value. operators instead which only work on dictionaries of one element.
And thank you again. Learned a lot studying this.
It would be nice to have a c_ptr available in the dictionary. This would allow a better coupling using a dictionary and, say, flook
or aotus
.
First of all: awesome work!
A dict of a dict, in current implementation, seems to work flawlessly by reference (pointers). The problem in my use-case is that I need to create a new sub-dict and then assign to a main dict inside a subroutine.
subroutine (...)
(...)
new_dict = ( &
& ('key1' .kv. 'value1') // &
& ('key2' .kv. 'value2') &
&)
main_dict = (new_entry .kvp. new_dict)
(...)
end subroutine (...)
That works in the main program but when in a subroutine or loop this simple don't work and I don't know why... my guess it's some variable is pointing to the variable new_dict then when the subroutine ends all data is thrown away since the new_dict variable is deallocated and now points to some garbage in memory.
There is a way to achieve automatic generation of dicts in current stage of development or a new function needs to be implemented?
Nice project !!
In order to compile on my Mac OS X 10.9.5 (gfortran 5.2) I add to replace cpp
---> fpp
on line 17 of the Makefile.
Also, the free
system command seems not to be present (on bash
or zsh
) on Mac OS, hence the memory tests will give the output
Running with deallocation
sh: free: command not found
Finally, there was a small bug in dictionary_pp.F90: the lines 306 and 307 must be inverted, i.e.
chash = ld%hash
ld => this%first
becomes
ld => this%first
chash = ld%hash
One cannot retrieve a single precision value with a double precision.
It is not fully clear what should be the case for:
Should all work? Currently they don't, the type has to be explicitly correct.
Why not overload the operator(=) instead using subroutines like assign and associate?
[Why did you choose this way? (I'm curious if I can help...)]
integer :: numb
type(Var) :: val
numb = 1
val = numb ! Eq: call assign(val, numb)
numb = val ! Eq: call assign(numb, val)
interface operator(=)
module procedure assign_X_to_Y
(...)
end interface
Thank you zerothi, for making this awesome library. This is exactly what I need for a project. Unfortunately, I'm new to both Fortran and CMake. I've reviewed as much as I can on CMake for Windows, but I'm struggling to install and link this library to my VS Code project. Please could you outline what you mean by the normal CMake procedure?
Thanks again!
Error given is that there are multiple rules for the same object. This error occurs when importing the project with FetchContent
:
CMake Error:
Running
'/usr/bin/ninja' '-C' '/home/lecris/mpsd/Projects/octopus/cmake-build-debug' '-t' 'recompact'
failed with:
ninja: warning: phony target '_deps/fdict-build/src/fdict.fypp' names itself as an input; ignoring [-w phonycycle=warn]
ninja: error: build.ninja:11776: multiple rules generate
_deps/fdict-build/src/fdict.fypp
Hello,
I am not sure if this is the right place but I am asking for help as I am stuck with final install process of fdict
.
I am on a macOS 10.15 using zsh.
make
has created a libfdict.a
without any error. I have used the gfortran.make
file provided in the arch-makes
directory with optional flags and openmpi flag ON (default and debugging flags OFF).
Running install I am getting the following error message:
mkdir -p ~/FORT/fdict/include
mkdir -p ~/FORT/fdict/lib
mkdir -p ~/FORT/fdict/bin
install-sh -m 755 -t ~/FORT/fdict/lib libfdict.a
/bin/sh: install-sh: command not found
make: *** [smeka-install-lib] Error 127
Will you please help?
My best regards,
Tamoghna
When looping the dictionary one should be able to retrieve the value without specifying the key.
This is easily enabled by adding a new routine that does not take key as argument.
Me again...
I'm trying to get this library to work since hours. I have to admit that I'm always having problems with external libraries.
Anyway, first of all I wanted to point out that building the library into a folder does not work. With
make PREFIX=fdict install
(when I want to build the library into the source folder) gives me the error:
mkdir -p fdict/include
mkdir -p fdict/lib
mkdir -p fdict/bin
install -pm 755 -t fdict/lib libfdict.a
install: cannot stat 'libfdict.a': No such file or directory
smeka/Makefile.install:16: recipe for target 'smeka-install-lib' failed
make: *** [smeka-install-lib] Error 1
I can build the library in the directory using make
only. I tried to do to things from there
test_dict.f90
and the test_utls.f90
to a folder. Having the everything in a different location:test-fdict/
|-lib/ <-- contains library files
|-src/ <-- contains source files (.f90)
dict.make <-- FOBOS make file
fdict-master
when compiling test_fdict.f90Non of the above work (at least not with my FOBOS makefile). Could you help with this?
Currently which(var)
returns which data-type var is. However, to compare one have to hardcode the data-type, which is error prone.
Instead it would be useful to query the type-field of a data-type directly:
type(variable_t) :: var
real(8) :: a
if ( which(a) == which(var) ) then
! now we know that the following will work
call assign(a, var)
end if
Hello!
I wrote a small test program to create a dictionary. However, I am not able to print the dictionary or the key values in the dictionary.
This is the sample program
use dictionary implicit none type(dict) :: sample_dict1 integer :: nx = 101, ny = 201, nt = 10001 sample_dict1 = ('nx'.kv.nx) // ('ny'.kv.ny) // ('nt'.kv.nt) print *, sample_dict1
Please provide a package config as part of the installation process.
here is a simple template
prefix=@prefix@
exec_prefix=${prefix}
bindir=${exec_prefix}/bin
includedir=${prefix}/include
libdir=${exec_prefix}/lib
Name: fdict
Description: Fortran type-free variables and type-free dictionaries
Version: 0.6.0
URL: https://github.com/zerothi/fdict
Cflags: -I${includedir}
Libs: -L${libdir} -lfdict
Everything should be in place, just need to check that using it as a subproject actually works.
I have an input file that I read before creating a dictionary with its contents. Below is a sample of the input file:
3
> this is the number of lines following the header.
"key" "value1" "value2"
"2196_202_4" 15582.0 497
"2196_8038_4" 15582.0 498
"2248_207_4" 15582.0 499
I was trying to read the file and create a dictionary as follows:
type(dict) :: dict1
type(dict) :: dict2
real :: value11
integer :: value12
character :: key1
open(file='input.dat', unit = 30, status='old')
read(30,*) no_lines
read(30,*)
do j=1,no_lines
read(30,*) key1, value11, value12
dict1= dict1// (key1.kv.value11)
dict2= dict2// (key1.kv.value12)
enddo
close(30)
call print(dict1)
However the output I get from the 'print' command is just:
2 [s0] (2041543547)
Not sure what I am doing wrong. Any thoughts?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.