Skip to content

Commit e80e2cc

Browse files
authored
Merge pull request #27 from UCL-ARC/4-add-garden-tests
4 add veggies and pFUnit tests
2 parents 49930ff + 1fe8c4a commit e80e2cc

27 files changed

+1552
-127
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22
*.mod
33
*.DS_Store
44
build/
5+
build-cmake/
6+
*Temporary

CMakeLists.txt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,13 @@ enable_testing()
2525
#--------------------------------------#
2626
# test-drive #
2727
#--------------------------------------#
28-
add_subdirectory("testing/test-drive")
28+
if (BUILD_TESTS MATCHES "ON")
29+
add_subdirectory("testing/test-drive")
30+
endif()
31+
32+
#--------------------------------------#
33+
# pFUnit #
34+
#--------------------------------------#
35+
if (BUILD_TESTS MATCHES "ON")
36+
add_subdirectory("testing/pFUnit")
37+
endif()

README.md

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,34 +35,58 @@ There are two src codes within this repository [mesh_generator](./src/mesh_gener
3535

3636
## Building
3737

38-
We are utilising cmake (see [CMakeLists.txt](./CMakeLists.txt)) for our build system. Therefore, to build this repository, please run the following
38+
A bash script is provided for building ([build.sh](./build.sh)). However, there are some instructions below for building without this script.
39+
40+
### CMake
41+
>Note: we have some [PFunit tests](./testing/pFUnit/) which require a local version of PFunit to be pre-built on your device. Once built, the path to the PFunit `installed` dir will need to be passed via `-DCMAKE_PREFIX_PATH`.
42+
43+
One build system we are utilising is cmake (see [CMakeLists.txt](./CMakeLists.txt)). Therefore, to build this repository, please run the following
3944
```sh
40-
cmake -B build
45+
cmake -DCMAKE_PREFIX_PATH=/path/to/pfunit/installed/dir -B build-cmake
4146
```
4247
This will create a [build](./build) directory from within which the project can be compiled...
4348
```sh
44-
cd build
45-
make
49+
cmake --build build-cmake
4650
```
4751
This will produce executables for the two src codes, `fortran-tooling-mesh-generator` and `fortran-tooling-poisson`.
4852

53+
### FPM
54+
To build the project using FPM, from the root of the repo, run
55+
```sh
56+
fpm build
57+
```
58+
4959
## Running the src
5060

5161
### Mesh generator
52-
62+
If you have built using CMake, you can run the mesh generator by directly calling the executable
5363
```sh
5464
./build/fortran-tooling-mesh-generator <box_size> <edge_size>
5565
```
5666

67+
If you have built using FPM, you can also run the mesh generator via FPM
68+
```sh
69+
fpm run mesh_generator -- <box_size> <edge_size>
70+
```
71+
5772
### Poisson solver
73+
If you have built using CMake, you can also run the poisson solver by directly calling the executable
74+
```sh
75+
./build/fortran-tooling-poisson <path_to_mesh_file>
76+
```
5877

78+
If you have built using FPM, you can also run the mesh generator via FPM
5979
```sh
60-
./build/fortran-tooling-poisson # then respond to prompt with the mesh name, likely to be `square_mesh`
80+
fpm run poisson -- <path_to_mesh_file>
6181
```
6282

6383
## Running the tests
84+
If you have built using CMake, you can run the tests by running the following from within the `build-cmake` directory.
85+
```sh
86+
ctest
87+
```
6488

65-
To run the tests, from within the `build` directory, run the following.
89+
If you have built using fpm, you can run the tests by running the following from the root of the repo
6690
```sh
67-
$ ctest
91+
fpm test
6892
```

build.sh

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#!/bin/bash
2+
3+
4+
5+
clean_build=false
6+
build_cmake=false
7+
build_fpm=false
8+
build_tests=true
9+
PFUNIT_INSTALLED_PATH="" # Path to pFUnit/installed directory
10+
run_tests=false
11+
12+
help() {
13+
echo "Usage:"
14+
echo " -h Display this help message."
15+
echo " -c Clean all build artifacts."
16+
echo " -m Build via cmake."
17+
echo " -f Build via fpm."
18+
echo " -s Skip building cmake tests"
19+
echo " -p Path to pFUnit/installed directory."
20+
echo " -t Run tests."
21+
exit 0
22+
}
23+
24+
# check for no input arguments and show help
25+
if [ $# -eq 0 ];
26+
then
27+
./build.sh -h
28+
exit 0
29+
fi
30+
31+
# parse input arguments
32+
while getopts "hcmftp:s" opt
33+
do
34+
case ${opt} in
35+
h ) help;;
36+
c ) clean_build=true;;
37+
m ) build_cmake=true;;
38+
f ) build_fpm=true;;
39+
s ) build_tests=false;;
40+
p ) PFUNIT_INSTALLED_PATH="${OPTARG}";;
41+
t ) run_tests=true;;
42+
\? ) echo "Invalid option: $OPTARG" >&2; exit 1;;
43+
esac
44+
done
45+
shift $((OPTIND -1))
46+
47+
if [ "$clean_build" == "true" ]
48+
then
49+
if [ "$build_cmake" == "true" ]
50+
then
51+
echo "Cleaning cmake build"
52+
rm -rf build-cmake
53+
fi
54+
55+
if [ "$build_fpm" == "true" ]
56+
then
57+
echo "Cleaning fpm build"
58+
rm -rf build
59+
fi
60+
61+
if [ "$build_cmake" == "false" ] && [ "$build_fpm" == "false" ]
62+
then
63+
echo "No build type specified"
64+
fi
65+
fi
66+
67+
# Build cmake version
68+
if [ "$build_cmake" == "true" ]
69+
then
70+
echo "Building using cmake"
71+
if [ "$build_tests" == "true" ]
72+
then
73+
echo "Building tests"
74+
cmake -DCMAKE_PREFIX_PATH="$PFUNIT_INSTALLED_PATH" -DBUILD_TESTS=ON -B build-cmake
75+
else
76+
echo "Skipping tests"
77+
cmake -DBUILD_TESTS=OFF -B build-cmake
78+
fi
79+
cmake --build build-cmake
80+
fi
81+
82+
# Build fpm version
83+
if [ "$build_fpm" == "true" ]
84+
then
85+
if [ "$clean_build" == "true" ]
86+
then
87+
echo "Cleaning fpm build"
88+
rm -rf build
89+
fi
90+
echo "Building using fpm"
91+
fpm build
92+
fi
93+
94+
if [ "$run_tests" == "true" ]
95+
then
96+
tests_run=false
97+
if [ -d "build-cmake" ]; then
98+
echo "Running cmake tests"
99+
tests_run=true
100+
pushd build-cmake
101+
ctest
102+
popd
103+
fi
104+
105+
if [ -d "build" ]; then
106+
echo "Running fpm tests"
107+
tests_run=true
108+
fpm test
109+
fi
110+
111+
if [ "$tests_run" == "false" ]
112+
then
113+
echo "No tests found. Must build first."
114+
fi
115+
fi

fpm.toml

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,11 @@ copyright = "Copyright 2025, UCL ARC"
88
[fortran]
99
source-form = "free"
1010

11-
[profiles.gfortran.linux]
12-
flags = "-ffree-line-length-none"
13-
14-
[build]
15-
auto-executables = true
16-
auto-tests = true
17-
auto-examples = true
18-
19-
[install]
20-
library = false
21-
2211
[dev-dependencies]
2312
test-drive.git = "https://github.com/fortran-lang/test-drive"
2413
test-drive.tag = "v0.5.0"
14+
veggies.git = "https://gitlab.com/everythingfunctional/veggies"
15+
veggies.tag = "main"
2516

2617
[[executable]]
2718
name = "poisson"
@@ -34,6 +25,11 @@ source-dir = "src/mesh_generator"
3425
main = "main.f90"
3526

3627
[[test]]
37-
name = "test-drive-mesh-generator"
28+
name = "test-drive-tests"
3829
source-dir = "testing/test-drive"
39-
main = "main.f90"
30+
main = "main.f90"
31+
32+
[[test]]
33+
name = "veggies-tests"
34+
source-dir = "testing/veggies"
35+
main = "main.f90"

src/mesh_generator/main.f90

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,31 @@ program main
1717
real(kind=real64), dimension(:, :), allocatable :: nodes
1818

1919
! Get command line args (Fortran 2003 standard)
20-
if (command_argument_count() > 0) then
20+
if (command_argument_count() == 2) then
2121
call get_command_argument(1, length=argl)
2222
allocate(character(argl) :: a)
2323
call get_command_argument(1, a)
2424
read(a,*) box_size
25+
deallocate(a)
26+
call get_command_argument(2, length=argl)
27+
allocate(character(argl) :: a)
2528
call get_command_argument(2, a)
2629
read(a,*) edge_size
30+
deallocate(a)
31+
else
32+
write(*,'(A)') "Error: Invalid input"
33+
call get_command_argument(0, length=argl)
34+
allocate(character(argl) :: a)
35+
call get_command_argument(0, a)
36+
write(*,'(A,A,A)') "Usage: ", a, " <box_size> <edge_size>"
37+
deallocate(a)
38+
stop
2739
end if
2840

2941
! Output start message
3042
write(*,'(A)') "Generating mesh using:"
3143
write(*,'(A,1I16)') "box size: ", box_size
32-
write(*,*) " process: ", edge_size
44+
write(*,*) " edge_size: ", edge_size
3345

3446
call calculate_mesh_parameters(box_size, edge_size, num_edges_per_boundary, num_nodes, num_boundary_nodes, num_elements)
3547

src/mesh_generator/mesh_generator.f90

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ subroutine write_mesh_to_file(num_nodes, num_elements, num_boundary_nodes, nodes
146146

147147
if( iostat .ne. 0) then
148148
write(*,'(a)') ' *** Error when opening '//trim(file_name)
149+
stop
149150
else
150151
write(*,'(/,a)') ' *** '//trim(file_name)//' opened'
151152
end if

src/poisson/main.f90

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,49 @@ program main
33

44
implicit none
55

6-
integer :: boundary_index(mxp), element_to_node(3,mxe), &
7-
vb_index(mxe), boundary_node_num(2,mxb), num_side_nodes(4,mxb)
8-
real :: coordinates(2, mxp), nodal_value_of_f(mxp), rhs_vector(mxp), beta(mxp), f_increment(mxp), &
9-
vb1(mxc), vb2(mxc), vb(3,mxc), element_stiffness(6,mxe), &
10-
pre_conditioning_matrix(mxp)
6+
integer :: num_nodes, num_elements, num_boundary_points, element_to_node(3,mxe), vb_index(mxe), boundary_node_num(2,mxb), num_side_nodes(4,mxb)
7+
real :: coordinates(2, mxp), nodal_value_of_f(mxp), vb1(mxc), vb2(mxc), vb(3,mxc)
118
integer :: fname_io = 100, fname_out_io = 101
12-
character*120 :: input_fname, output_fname
9+
10+
!! CLI inputs
11+
integer :: argl
12+
character(len=:), allocatable :: a, input_fname, output_fname
1313

1414
!!
15-
!! *** Asks for I/O file names
16-
!!
17-
write(*,'(10(/),7(a,/),//)') &
18-
' *********************************', &
19-
' *** ***', &
20-
' *** * P O I S S O N * ***', &
21-
' *** ***', &
22-
' *** PCG-FEM HEAT CONDUCTION ***', &
23-
' *** ***', &
24-
' *********************************'
25-
input_fname = textread(' Enter input file name : ')
26-
output_fname = trim(input_fname)//'.out'
15+
!! *** Check for input from user
16+
!!
17+
if (command_argument_count() == 1) then
18+
call get_command_argument(1, length=argl)
19+
allocate(character(argl) :: input_fname)
20+
call get_command_argument(1, input_fname)
21+
allocate(character(argl + 4) :: output_fname)
22+
output_fname = input_fname//'.out'
23+
else
24+
write(*,'(A)') "Error: Invalid input"
25+
call get_command_argument(0, length=argl)
26+
allocate(character(argl) :: a)
27+
call get_command_argument(0, a)
28+
write(*,'(A,A,A)') "Usage: ", a, " <mesh_file_name>"
29+
deallocate(a)
30+
stop
31+
end if
32+
2733
call open_file(input_fname, 'old', fname_io)
2834
call open_file(output_fname, 'new', fname_out_io)
35+
2936

3037
!!
3138
!! *** Reads the triangular mesh and problem constants: Kx,Ky,Q,fp,q
3239
!!
33-
call inp(element_to_node,vb_index,coordinates,boundary_node_num,num_side_nodes,vb,vb1,vb2,fname_io)
40+
call read_input_file(num_nodes,num_elements,num_boundary_points,element_to_node,vb_index,coordinates,boundary_node_num,num_side_nodes,vb,vb1,vb2,fname_io)
3441

3542
!!
3643
!! *** Assembles and solves the system of equations
3744
!!
38-
call pcg(element_to_node,vb_index,coordinates,nodal_value_of_f,boundary_node_num,num_side_nodes,vb,vb1,vb2,element_stiffness,rhs_vector,beta,f_increment,boundary_index,pre_conditioning_matrix)
45+
call pcg(num_nodes,num_elements,num_boundary_points,element_to_node,vb_index,coordinates,boundary_node_num,num_side_nodes,vb,vb1,vb2,nodal_value_of_f)
3946

4047
!!
4148
!! *** Writes the computed solution
4249
!!
43-
call out(element_to_node,coordinates,nodal_value_of_f,fname_out_io)
50+
call write_output_file(num_nodes,num_elements,element_to_node,coordinates,nodal_value_of_f,fname_out_io)
4451
end program main

0 commit comments

Comments
 (0)