plantFEM std library
Welcome to a tutorial for plantFEM std library.
The std library contains following classes and modules (std).
Are you from Python? click here!
modules
Followings are major classes.
(1) plantFEM uses iso_fortran_env for basic data types.
For instance, 64-bit Real value and 32-bit Integer value are defined as shown below.
program main
use iso_fortran_env
implicit none
! defining 128-bit Real value
real(real128) :: re128 = 1.0d0
! defining 64-bit Real value
real(real64) :: re64 = 1.0d0
! defining 32-bit Real value
real(real32) :: re32 = 1.0d0
! defining 64-bit Integer value
integer(int64) :: in64 = 1234567890
! defining 32-bit Integer value
integer(int32) :: in32 = 1234567890
! defining 16-bit Integer value
integer(int16) :: in16 = 12345
! defining 8-bit Integer value
integer(int8) :: in8 = 123
print *, re128
print *, re64
print *, re32
print *, in64
print *, in32
print *, in16
print *, in8
end program main
If the script is named as “server.f90” and located in the root repository of the plantfem, the script is executable by this command.
./plantfem run
The result of the script is,
1.00000000000000000000000000000000000
1.0000000000000000
1.00000000
1234567890
1234567890
12345
123
(2) TimeClass is a class for time measurement, which can be used to measure cpu time by creating an instance of type time_.
Ex. Example1
program main
use std
implicit none
type(Time_) :: time
! stop-watch starts!
call time%start()
print *, "Hello!"
! measuring cpu-time.
call time%show()
! reset stop-watch
call time%reset()
print *, "How are you today?"
! measuring cpu-time.
call time%show()
! sleep for 20 sec.
call time%sleep(20)
end program main
If the script is named as “server.f90” and located in the root repository of the plantfem, the script is executable by this command.
./plantfem run
The result of the script is,
Hello!
2.3000000000000017E-005
How are you today?
2.4729999999999999E-003
(3) MathClass is a library for mathematical operations such as matrix calculation and tensor operations. Although “Class” is in the name, but this is just a toolbox of useful functions.
Ex.
program main
use plantFEM
implicit none
real(real64) :: re64=100.0d0
real(real64) :: vec(100)=1.0d0
real(real64) :: vec3(3)=1.0d0
real(real64) :: tensor(3,3)=0.0d0
print *, "100 radian = ", degrees(re64),"degrees"
print *, "100 degrees= ", radian(re64),"radian"
print *, "real64 => string: ", str(re64)
print *, "norm of vec(100) : ", norm(vec)
tensor(:,:) = tensor_product(vec3,vec3)
print *, tensor(1,:)
print *, tensor(2,:)
print *, tensor(3,:)
tensor(:,:)=0.0d0
tensor(1,1)=1.0d0
tensor(2,2)=1.0d0
tensor(3,3)=1.0d0
print *, "det(tensor) : ", det_mat(tensor,size(tensor,1) )
print *, "...etc."
end program main
If the script is named as “server.f90” and located in the root repository of the plantfem, the script is executable by this command.
./plantfem run
The result of the script is,
100 radian = 5729.5779514719952 degrees
100 degrees= 1.7453292519444445 radian
real64 => string: 100.00000000
norm of vec(100) : 10.000000000000000
1.0000000000000000 1.0000000000000000 1.0000000000000000
1.0000000000000000 1.0000000000000000 1.0000000000000000
1.0000000000000000 1.0000000000000000 1.0000000000000000
det(tensor) : 1.0000000000000000
...etc.
(4) IOClass is a class to realize a file operation like Python in Fortran. You can create an instance of type “IO_” for easy file operation.
Ex.
program main
use std ! standard package of SiCroF library
implicit none
! This example utilizes Input-Output Class, where
! You can handle external files.
! How to use:
! First, create the instance
type(IO_) :: f ! file-IO instance
integer(int32) :: i, num ! int i and int num
! #1 create, edit and close files.
! ----> open file(filepath, filename, extention)
call f%open("./","test",".txt")
! write something
call f%write(str(100.0d0) )
write(f%fh,*) 100.0d0
! and close it
call f%close()
! ----> create sequential files (filepath, filename, extention)
! it creates
! ./hello1.txt
! ./hello2.txt
! ./hello3.txt
! ...
! ./hello10.txt
! for i=1; i<11;i++
do i=1,10
! f.open(filepath, filename, extention)
! str(int) => string
call f%open("./","hello"//trim(str(i)),".txt")
! This
call f%write(str(i))
! and this
write(f%fh,*) str(i)
! are same
call f%close()
call f%open("./","hello"//trim(str(i)),".txt")
! read a line
read(f%fh,*) num
! print(num)
print *, num
call f%close()
enddo
end program
If the script is named as “server.f90” and located in the root repository of the plantfem, the script is executable by this command.
./plantfem run
The result of the script is,
1
2
3
4
5
6
7
8
9
10
(5) RandomClass is a class in Fortran to do the same thing as the random class in Python that does pseudo-random number generation.
Ex » Next section
(6) ArrayClass is a toolbox of functions and subroutines that perform array operations, similar to Python’s numpy.
Ex.
program main
use std ! standard package of SiCroF library
implicit none
! This example utilizes Array Class, where
! You can handle external files.
! How to use:
! First, create the instance
real(real64),allocatable :: a(:,:)
real(real64),allocatable :: b(:,:)
real(real64),allocatable :: ab(:,:)
real(real64),allocatable :: copyobj(:,:)
real(real64),allocatable :: ret(:,:)
integer(int32) :: i
type(IO_) :: f
! #1 create array
! ----> allocate array
allocate(ret(3,3) )
! ----> set identity matrix
ret = identity_matrix(3)
! show array on terminal.
print *, "ret = "
call showArray(ret)
! #2 Array Input-Output
! ----> save matrix as "./test.txt" file
call savetxt(ret,"./","test",".txt")
! ----> load a .txt or .csv file.
a = loadtxt("./","test",".txt")
b = loadtxt("./","test",".txt")
! -----> also, you can do it for multiple arrays as
call f%open("./","arrays",".txt")
! save "a" array
call saveArray(f%fh,a)
! save "b" array
call saveArray(f%fh,b)
! save "ret" array
call saveArray(f%fh,ret)
call f%close()
! -----> and,
call f%open("./","arrays",".txt")
! load "a" array
call loadArray(f%fh,a)
! load "b" array
call loadArray(f%fh,b)
! load "ret" array
call loadArray(f%fh,ret)
call f%close()
! -----> It shows the array.
print *, "a = "
call showArray(a)
! -----> copy array
a(1,2)=20.0d0
call copyarray(a,copyobj)
! -----> It shows the array.
print *, "a (original) = "
call showArray(a)
print *, "copy = "
call showArray(copyobj)
! Importance Index 7 / 10 : [******* ]
end program
If the script is named as “server.f90” and located in the root repository of the plantfem, the script is executable by this command.
./plantfem run
The result of the script is,
ret =
1.0000000000000000 0.0000000000000000 0.0000000000000000
0.0000000000000000 1.0000000000000000 0.0000000000000000
0.0000000000000000 0.0000000000000000 1.0000000000000000
a =
1.0000000000000000 0.0000000000000000 0.0000000000000000
0.0000000000000000 1.0000000000000000 0.0000000000000000
0.0000000000000000 0.0000000000000000 1.0000000000000000
a (original) =
1.0000000000000000 20.000000000000000 0.0000000000000000
0.0000000000000000 1.0000000000000000 0.0000000000000000
0.0000000000000000 0.0000000000000000 1.0000000000000000
copy =
1.0000000000000000 20.000000000000000 0.0000000000000000
0.0000000000000000 1.0000000000000000 0.0000000000000000
0.0000000000000000 0.0000000000000000 1.0000000000000000
(7) GraphClass is a class for implementing the graph structure and performing operations. Implementation in progress.
(8) MPIClass is class as a wrapper of MPI in terms of Fortran. You can easily perform MPI parallelization by using its instance.
Ex.
program main
use std ! use standard libary of SiCroF
implicit none
! start
type(MPI_) :: mpid
type(IO_) :: f
integer(int32) :: fh ! file handle (id)
integer(int32) :: val, from
integer(int32) :: send_value(2)
integer(int32),allocatable :: recv_values(:)
! start MPI
call mpid%start()
! >>>>>>>> do parallel
! hello, world
print *, "hello! world, my rank is ", mpid%myrank
! create files
call f%open("./","FileFromRank"//trim(str(mpid%myrank)),".txt")
write(f%fh,*) "MPI is running!"
write(f%fh,*) "My rank is ",mpid%myrank
write(f%fh,*) "Number of process is ",mpid%petot
call f%close()
! ----> broadcast (sync) one data => to all nodes.
val = mpid%myrank
print *, "my value :: ",val, "my rank is : ", mpid%myrank
! broadcast => sync "val" of rank "0" node to all!
from = 0
call mpid%bcast(From=from,val=val)
print *, "Sync! >> my value :: ",val, "my rank is : ", mpid%myrank
! ----> gather all values to rank 0 node
allocate(recv_values(mpid%petot*2) )
send_value(:) = mpid%myrank
recv_values(:) = 0
! gether send_value of all nodes => to "recv_value(:) "
call mpid%gather(sendobj=send_value(1:2),&
recvobj=recv_values(1:),To=0)
if(mpid%myrank == 0)then
print *, "Gathered values : "
print *, recv_values(:)
endif
! Wait all process
call mpid%barrier()
! <<<<<<<< end do parallel
call mpid%end()
! Importance Index 6 / 10 : [****** ]
end program
If the script is named as “server.f90” and located in the root repository of the plantfem, the script is executable by this command.
./plantfem run
The result of the script is,
Number of Core is 1
hello! world, my rank is 0
my value :: 0 my rank is : 0
Sync! >> my value :: 0 my rank is : 0
Gathered values :
0 0
############################################
Computation time (sec.) :: 2.4629099999999999E-004
Number of cores :: 1
############################################
(9) In DictionaryClass, we implemented the Python equivalent of a dictionary class. To be honest, I don’t use it much.
(10) OpenMPClass is class as a wrapper of OpenMP in terms of Fortran. MPIClass is very good and useful, but this class is honestly a lost cause and needs a vision.
(11) LinearSolverClass is a solver for linear equations. It is an original implementation. It is planned to be replaced in the future by the well-known MKL and LAPACK.
Ex.
program main
use LinearSolverClass
implicit none
! Create Ax=B and solve x = A^(-1) B
integer(int32), parameter :: N = 4 ! rank = 3
real(real64) :: t1,t2 ! time measure
real(real64) :: A(1:N,1:N), B(1:N), X(1:N) ! A, x and B
real(real64) :: Val(1:10)
integer(int32) :: index_i(1:10),index_j(1:10)
type(LinearSolver_) :: solver ! linear solver instance.
! creating A, x, and B
A(1,1:4) = (/ 2.0d0, -1.0d0, 0.0d0, 0.0d0 /)
A(2,1:4) = (/ -1.0d0, 2.0d0, -1.0d0, 0.0d0 /)
A(3,1:4) = (/ 0.0d0, 2.0d0, 3.0d0, 1.0d0 /)
A(4,1:4) = (/ 0.0d0, 0.0d0, 1.0d0, 2.0d0 /)
X(1:4) = (/ 0.0d0, 0.0d0, 0.0d0, 0.0d0 /)
B(1:4) = (/ 1.0d0, 2.0d0, 3.0d0, 4.0d0 /)
! CRS-format
Val(1:10) = (/ 2.0d0, -1.0d0, -1.0d0, 2.0d0, -1.0d0, 2.0d0, 3.0d0, &
1.0d0, 1.0d0, 2.0d0/)
index_i(1:10) = (/ 1, 1, 2, 2, 2, 3, 3, 3, 4, 4/)
index_j(1:10) = (/ 1, 2, 1, 2, 3, 2, 3, 4, 3, 4/)
! import Ax=B into the linear solver instance.
call solver%import(a = A, x = X, b = B)
! get a cpu-time
call cpu_time(t1)
! solve Ax=B by Gauss-Jordan
call solver%solve(Solver="GaussJordan")
! get a cpu-time
call cpu_time(t2)
! show result
! X is stored in solver%X(:) (solver.x[])
print *, "Solved by GaussJordan",solver%X(:),"/",t2-t1," sec."
! Similarly ...
X(1:4) = (/ 0.0d0, 0.0d0, 0.0d0, 0.0d0 /)
call solver%import(a = A, x = X, b = B, val=val, index_i=index_i, index_j=index_j)
call cpu_time(t1)
call solver%solve(Solver="GaussSeidel")
call cpu_time(t2)
print *, "Solved by GaussSeidel",solver%X(:),"/",t2-t1," sec."
X(1:4) = (/ 0.0d0, 0.0d0, 0.0d0, 0.0d0 /)
call solver%import(a = A, x = X, b = B, val=val, index_i=index_i, index_j=index_j)
call cpu_time(t1)
call solver%solve(Solver="BiCGSTAB",CRS=.true.)
call cpu_time(t2)
print *, "Solved by BiCGSTAB(CRS)",solver%X(:),"/",t2-t1," sec."
X(1:4) = (/ 0.0d0, 0.0d0, 0.0d0, 0.0d0 /)
call solver%import(a = A, x = X, b = B, val=val, index_i=index_i, index_j=index_j)
call cpu_time(t1)
call solver%solve(Solver="BiCGSTAB",CRS=.false.)
call cpu_time(t2)
print *, "Solved by BiCGSTAB ",solver%X(:),"/",t2-t1," sec."
X(1:4) = (/ 0.0d0, 0.0d0, 0.0d0, 0.0d0 /)
call solver%import(a = A, x = X, b = B)
call cpu_time(t1)
call solver%solve(Solver="GPBiCG")
call cpu_time(t2)
print *, "Solved by GPBiCG ",solver%X(:),"/",t2-t1," sec."
! Importance Index 9 / 10 : [********* ]
end program
If the script is named as “server.f90” and located in the root repository of the plantfem, the script is executable by this command.
./plantfem run
The result of the script is,
Solved by GaussJordan 1.1304347826086956 1.2608695652173914 -0.60869565217391308 2.3043478260869565 / 1.4000000000000123E-005 sec.
Solved by GaussSeidel 1.1304329905708359 1.2608637700010377 -0.60869342176215169 2.3043467108810760 / 1.3500000000000014E-004 sec.
Solved by BiCGSTAB(CRS) 1.1304347826086956 1.2608695652173909 -0.60869565217391319 2.3043478260869570 / 1.1999999999999858E-005 sec.
Solved by BiCGSTAB 1.1304347826086953 1.2608695652173911 -0.60869565217391308 2.3043478260869565 / 9.9999999999995925E-006 sec.
Solved by GPBiCG 1.1304348100123531 1.2608695899884879 -0.60869565841905671 2.3043478274256657 / 3.4999999999999875E-005 sec.
(12) TreeClass is a class for tree graphs. The maintenance is currently suspended. This class is looking for a vision.
(13) ShapeFunctionClass is a class for the shape function. Currently we only use 2D 4-node iso-parametric elements and 3D 8-node iso-parametric elements. We are looking for committers to implement other types of elements.
… and others are miner. TermClass, PhysicsClass, KinematicClass, VertexClass, CSVClass, VectorClass, EquationClass, GeometryClass, RouteOptimization, STLClass and WebserverClass.
HTTPClass is a remnant from when I was trying to set up an http server at plantFEM. It is waiting for your commit.