Skip to content

Commit de4b5dd

Browse files
authored
Merge pull request #41 from SCOREC/ac/function-pointer
Test Function Pointer
2 parents d762d4b + f482331 commit de4b5dd

File tree

11 files changed

+362
-33
lines changed

11 files changed

+362
-33
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ set(SOURCES
1616
pmpo_MPMesh.cpp
1717
pmpo_c.cpp
1818
pmpo_createTestMPMesh.cpp
19+
../test/testMPAppIDs.cpp
1920
)
2021

2122
add_library(polyMPO-core ${SOURCES})

src/pmpo_c.cpp

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
#include "pmpo_c.h"
44
#include <stdio.h>
55

6-
using space_t = Kokkos::DefaultExecutionSpace::memory_space;
7-
86
namespace{
97
std::vector<MPMesh_ptr> p_mpmeshes;////store the p_mpmeshes that is legal
108

@@ -59,31 +57,6 @@ void polympo_setMPICommunicator_f(MPI_Fint fcomm){
5957
MPI_Comm_size(comm,&commSize);
6058
}
6159

62-
/**
63-
* Attention: this typedef is LayoutLeft, meaning that the first
64-
* index is the contiguous one. This matches the Fortran and GPU conventions for
65-
* allocations.
66-
*/
67-
//TODO: order of these typedefs to be done later
68-
template<typename DataT>
69-
using kkViewHostU = Kokkos::View<
70-
DataT,
71-
Kokkos::LayoutLeft,
72-
Kokkos::DefaultHostExecutionSpace,
73-
Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
74-
75-
typedef kkViewHostU<double*> kkDblViewHostU;//TODO:put it to mesh.hpp
76-
typedef kkViewHostU<double*[vec2d_nEntries]> kkVec2dViewHostU;//TODO:put it to mesh.hpp
77-
typedef kkViewHostU<double**> kkDbl2dViewHostU;//TODO:put it somewhere else (maybe)
78-
typedef kkViewHostU<int**> kkInt2dViewHostU;//TODO:put it somewhere else (maybe)
79-
typedef kkViewHostU<int*> kkIntViewHostU;//TODO:put it somewhere else (maybe)
80-
81-
template <typename DataT>
82-
auto create_mirror_view_and_copy(DataT array, const int size){
83-
kkViewHostU<DataT> temp_host(array, size);
84-
return Kokkos::create_mirror_view_and_copy(space_t(), temp_host);
85-
}
86-
8760
void polympo_createMPs_f(MPMesh_ptr p_mpmesh,
8861
const int numElms,
8962
const int numMPs, // total number of MPs which is GREATER than or equal to number of active MPs
@@ -218,6 +191,13 @@ void polympo_finishRebuildMPs_f(MPMesh_ptr p_mpmesh)
218191
p_MPs->finishRebuild();
219192
}
220193

194+
void polympo_setAppIDFunc_f(MPMesh_ptr p_mpmesh, IntVoidFunc getNext, void* appIDs) {
195+
checkMPMeshValid(p_mpmesh);
196+
auto p_MPs = ((polyMPO::MPMesh*)p_mpmesh)->p_MPs;
197+
polyMPO::IntFunc getNextAppID = [getNext, appIDs]() { return getNext(appIDs); };
198+
p_MPs->setAppIDFunc(getNextAppID);
199+
}
200+
221201
void polympo_getMPCurElmID_f(MPMesh_ptr p_mpmesh,
222202
const int numMPs,
223203
int* elmIDs){

src/pmpo_c.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22
#define PMO_C_H
33

44
#include <mpi.h>
5+
#include "pmpo_defines.h"
56

67
extern "C" {
78

8-
typedef void* MPMesh_ptr;
9-
109
//initialize and finalize
1110
void polympo_initialize_f();
1211
void polympo_finalize_f();
@@ -23,6 +22,7 @@ void polympo_setMPICommunicator_f(MPI_Fint fcomm);//TODO:is MPI_Fint best? or so
2322
void polympo_createMPs_f(MPMesh_ptr p_mpmesh, const int numElms, const int numMPs, int* mpsPerElm, const int* mp2Elm, const int* isMPActive);
2423
void polympo_startRebuildMPs_f(MPMesh_ptr p_mpmesh, const int numMPs, const int* allTgtMpElmIn, const int* addedMPMask);
2524
void polympo_finishRebuildMPs_f(MPMesh_ptr p_mpmesh);
25+
void polympo_setAppIDFunc_f(MPMesh_ptr p_mpmesh, IntVoidFunc getNext, void* appIDs);
2626
void polympo_getMPCurElmID_f(MPMesh_ptr p_mpmesh, const int numMPs, int* elmIDs);
2727
void polympo_setMPLatLonRotatedFlag_f(MPMesh_ptr p_mpmesh, const int isRotateFlag);
2828

src/pmpo_defines.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,34 @@
22

33
#define MP_ACTIVE 1
44
#define MP_DELETE -1
5+
6+
typedef void* MPMesh_ptr;
7+
//Function that receives void* and returns an int
8+
typedef int (*IntVoidFunc)(void*);
9+
10+
using space_t = Kokkos::DefaultExecutionSpace::memory_space;
11+
12+
/**
13+
* Attention: this typedef is LayoutLeft, meaning that the first
14+
* index is the contiguous one. This matches the Fortran and GPU conventions for
15+
* allocations.
16+
*/
17+
//TODO: order of these typedefs to be done later
18+
template<typename DataT>
19+
using kkViewHostU = Kokkos::View<
20+
DataT,
21+
Kokkos::LayoutLeft,
22+
Kokkos::DefaultHostExecutionSpace,
23+
Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
24+
25+
typedef kkViewHostU<double*> kkDblViewHostU;//TODO:put it to mesh.hpp
26+
typedef kkViewHostU<double*[vec2d_nEntries]> kkVec2dViewHostU;//TODO:put it to mesh.hpp
27+
typedef kkViewHostU<double**> kkDbl2dViewHostU;//TODO:put it somewhere else (maybe)
28+
typedef kkViewHostU<int**> kkInt2dViewHostU;//TODO:put it somewhere else (maybe)
29+
typedef kkViewHostU<int*> kkIntViewHostU;//TODO:put it somewhere else (maybe)
30+
31+
template <typename DataT>
32+
auto create_mirror_view_and_copy(DataT array, const int size){
33+
kkViewHostU<DataT> temp_host(array, size);
34+
return Kokkos::create_mirror_view_and_copy(space_t(), temp_host);
35+
}

src/pmpo_fortran.f90

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,19 @@ subroutine polympo_finishRebuildMPs(mpMesh) &
9797
type(c_ptr), value :: mpMesh
9898
end subroutine
9999
!---------------------------------------------------------------------------
100+
!> @brief Stores pointer to appID data structure and a function to retrieve them used in migration
101+
!> @param mpmesh(in/out) MPMesh object
102+
!> @param getNext(in) Pointer to function that returns next App IDs
103+
!> @param appIDs(in) Pointer to opaque data application data structure (that may contain all available app IDs)
104+
!---------------------------------------------------------------------------
105+
subroutine polympo_setAppIDFunc(mpMesh, getNext, appIDs) &
106+
bind(C, NAME='polympo_setAppIDFunc_f')
107+
use :: iso_c_binding
108+
type(c_ptr), value :: mpMesh
109+
type(c_funptr), value :: getNext
110+
type(c_ptr), value :: appIDs
111+
end subroutine
112+
!---------------------------------------------------------------------------
100113
!> @brief get the current element ID MP array from a polympo array
101114
!> @param mpmesh(in/out) MPMesh object
102115
!> @param numMPs(in) length of array, number of the MPs

src/pmpo_materialPoints.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,18 @@ MaterialPoints::~MaterialPoints() {
6868
delete MPs;
6969
}
7070

71+
void MaterialPoints::rebuild(IntView addedMP2elm, IntView addedMPAppID) {
72+
auto addedSlices = createInternalMemberViews(addedMP2elm.size(), addedMP2elm, addedMPAppID);
73+
IntView curr_elem("curr_elem", MPs->capacity());
74+
auto setElem = PS_LAMBDA(const int& e, const int& mp, const int& mask){
75+
if(mask) curr_elem(mp) = e;
76+
else curr_elem(mp) = -1;
77+
};
78+
parallel_for(setElem, "setElem");
79+
80+
MPs->rebuild(curr_elem, addedMP2elm, addedSlices);
81+
}
82+
7183
void MaterialPoints::startRebuild(IntView tgtElm, int addedNumMPs, IntView addedMP2elm, IntView addedMPAppID, Kokkos::View<const int*> addedMPMask) {
7284
rebuildFields.ongoing = true;
7385
rebuildFields.addedNumMPs = addedNumMPs;
@@ -91,4 +103,8 @@ void MaterialPoints::finishRebuild() {
91103

92104
bool MaterialPoints::rebuildOngoing() { return rebuildFields.ongoing; }
93105

106+
void MaterialPoints::setAppIDFunc(IntFunc getAppIDIn) { getAppID = getAppIDIn; }
107+
108+
int MaterialPoints::getNextAppID() { return getAppID(); }
109+
94110
}

src/pmpo_materialPoints.hpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ typedef double mp_sym_mat3d_t[6];//TODO
2828
typedef double mp_basis_t[maxVtxsPerElm];
2929
typedef double mp_basis_grad2d_t[maxVtxsPerElm*2];
3030
typedef double mp_constv_mdl_param_t[12];
31+
typedef std::function<int()> IntFunc;
3132

3233
enum MaterialPointSlice {
3334
MPF_Status = 0,
@@ -121,13 +122,15 @@ class MaterialPoints {
121122
bool isRotatedFlag = false;
122123
Operating_Mode operating_mode;
123124
RebuildHelper rebuildFields;
125+
IntFunc getAppID;
124126

125127
public:
126128
MaterialPoints() : MPs(nullptr) {};
127129
MaterialPoints(int numElms, int numMPs, DoubleVec3dView positions, IntView mpsPerElm, IntView mp2elm);
128130
MaterialPoints(int numElms, int numMPs, IntView mpsPerElm, IntView mp2elm, IntView mpAppID);
129131
~MaterialPoints();
130132

133+
void rebuild(IntView addedMP2elm, IntView addedMPAppID);
131134
void startRebuild(IntView tgtElm, int addedNumMPs, IntView addedMP2elm, IntView addedMPAppID, Kokkos::View<const int*> addedMPMask);
132135
void finishRebuild();
133136
bool rebuildOngoing();
@@ -140,6 +143,9 @@ class MaterialPoints {
140143
typename std::enable_if<mpSliceData::rank==2>::type
141144
setRebuildMPSlice(mpSliceData mpSliceIn);
142145

146+
void setAppIDFunc(IntFunc getAppIDIn);
147+
int getNextAppID();
148+
143149
void rebuild() {
144150
IntView tgtElm("tgtElm", MPs->capacity());
145151
auto tgtMpElm = MPs->get<MPF_Tgt_Elm_ID>();
@@ -163,12 +169,11 @@ class MaterialPoints {
163169
ps::parallel_for(MPs, swap, "swap");
164170
}
165171
void updateMaxAppID() {
166-
auto mpInfo = ps::createMemberViews<MaterialPointTypes>(MPs->nPtcls());
167-
auto mpAppID_m = ps::getMemberView<MaterialPointTypes, MPF_MP_APP_ID>(mpInfo);
172+
auto mpAppID_m = MPs->get<MPF_MP_APP_ID>();
168173
maxAppID = 0;
169-
Kokkos::parallel_reduce("setMax" , mpAppID_m.size(),
174+
Kokkos::parallel_reduce("setMax" , MPs->nPtcls(),
170175
KOKKOS_LAMBDA(const int i, int & valueToUpdate) {
171-
if ( mpAppID_m(i) > valueToUpdate ) valueToUpdate = mpAppID_m(i) ;
176+
if ( mpAppID_m(i) > valueToUpdate ) valueToUpdate = mpAppID_m(i);
172177
},
173178
Kokkos::Max<int>(maxAppID)
174179
);
@@ -234,6 +239,7 @@ class MaterialPoints {
234239
}
235240
int getCapacity() { return MPs->capacity(); }
236241
int getCount() { return MPs->nPtcls(); }
242+
int getNumElems() { return MPs->nElems(); }
237243
auto getPositions() { return getData<MPF_Cur_Pos_XYZ>(); }
238244

239245
Operating_Mode getOpMode() { return operating_mode; }

test/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ pmpo_add_fortran_exe(testFortranInit testFortranInit.f90)
5252
pmpo_add_fortran_exe(testFortran testFortran.f90)
5353
pmpo_add_fortran_exe(testFortranReadMPAS testFortranReadMPAS.f90)
5454
pmpo_add_fortran_exe(testFortranMPMeshModule testFortranMPMeshModule.f90)
55+
pmpo_add_fortran_exe(testFortranMPAppIDs testFortranMPAppIDs.f90)
5556
pmpo_add_fortran_exe(testFortranMPAdvection testFortranMPAdvection.f90)
5657
pmpo_add_fortran_exe(testFortranCreateRebuildMPs testFortranCreateRebuildMPs.f90)
5758

@@ -75,6 +76,7 @@ pmpo_add_test(test_rebuild ./testRebuild)
7576
pmpo_add_test(testFortranInit ./testFortranInit)
7677
pmpo_add_test(testFortran ./testFortran)
7778
pmpo_add_test(testFortranMPMeshModule ./testFortranMPMeshModule)
79+
pmpo_add_test(testFortranMPAppIDs ./testFortranMPAppIDs)
7880

7981
#set NC file for test
8082
set(TEST_NC_FILE_PLANAR "${CMAKE_SOURCE_DIR}/test/sample_mpas_meshes/planar_nonuniform_cvt_for_square_673elms.nc")

test/queue.f90

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
! Adapted from : https://github.com/mapmeld/fortran-machine/blob/5e5e6bbdab353149047971a3f872238a2a4b716e/flibs-0.9/flibs/src/datastructures/queues.f90
2+
3+
! queues.f90 --
4+
! Include file for defining queues with a fixed capacity
5+
! Queues as implemented here are simply arrays where
6+
! data are inserted at the end and retrieved from the
7+
! top.
8+
!
9+
type QUEUE_STRUCT
10+
logical :: full
11+
integer :: start
12+
integer :: end
13+
integer, dimension(:), pointer :: data
14+
end type QUEUE_STRUCT
15+
16+
!
17+
! Define the subroutines and functions
18+
!
19+
contains
20+
21+
! queue_create --
22+
! Create and initialise a queue
23+
! Arguments:
24+
! queue Pointer to new queue
25+
! capacity The number of data that can be stored
26+
! Note:
27+
! There is no check that the capacity is positive!
28+
!
29+
subroutine queue_create( queue, capacity )
30+
type(QUEUE_STRUCT), pointer :: queue
31+
integer :: capacity
32+
33+
allocate( queue )
34+
allocate( queue%data(0:capacity) )
35+
36+
queue%full = .false.
37+
queue%start = 1
38+
queue%end = 0
39+
end subroutine queue_create
40+
41+
! queue_destroy --
42+
! Destroy a queue
43+
! Arguments:
44+
! queue Pointer to the queue to be destroyed
45+
!
46+
subroutine queue_destroy( queue )
47+
type(QUEUE_STRUCT), pointer :: queue
48+
49+
deallocate( queue%data )
50+
deallocate( queue )
51+
end subroutine queue_destroy
52+
53+
! queue_empty --
54+
! Check if the queue is empty
55+
! Arguments:
56+
! queue Pointer to the queue
57+
! Result:
58+
! logical indicating if the queue is
59+
! empty or not
60+
!
61+
logical function queue_empty( queue )
62+
type(QUEUE_STRUCT), intent(in) :: queue
63+
64+
queue_empty = (.not. queue%full) .and. &
65+
queue%end .eq. queue%start - 1
66+
67+
end function queue_empty
68+
69+
! queue_retrieve_data
70+
! Return the data stored at the top,
71+
! and remove them from the queue
72+
! Arguments:
73+
! queue Queue to be examined
74+
! Result:
75+
! Data stored at the top, afterwards
76+
! removed
77+
!
78+
function queue_retrieve_data( queue ) result(data)
79+
type(QUEUE_STRUCT) :: queue
80+
integer :: data
81+
82+
if (queue_empty(queue)) then
83+
print *, "ERROR: Queue is empty"
84+
call exit
85+
endif
86+
87+
data = queue%data(queue%start)
88+
89+
if ( .not. queue_empty(queue) ) then
90+
queue%start = queue%start + 1
91+
if ( queue%start .gt. size(queue%data) ) then
92+
queue%start = 1
93+
endif
94+
queue%full = .false.
95+
endif
96+
97+
end function queue_retrieve_data
98+
99+
! queue_append_data
100+
! Append data to the end of the queue
101+
! Arguments:
102+
! queue Queue to which to add the data
103+
! data The data to be added
104+
!
105+
subroutine queue_append_data( queue, data)
106+
type(QUEUE_STRUCT) :: queue
107+
integer, intent(in) :: data
108+
109+
if (queue%full) then
110+
print *, "ERROR: Queue is full"
111+
call exit
112+
endif
113+
114+
queue%end = queue%end + 1
115+
if ( queue%end .gt. size(queue%data) ) then
116+
queue%end = 1
117+
endif
118+
if ( queue%start .eq. queue%end+1 ) then
119+
queue%full = .true.
120+
endif
121+
if ( queue%end .eq. size(queue%data) .and. &
122+
queue%start .eq. 1 ) then
123+
queue%full = .true.
124+
endif
125+
queue%data(queue%end) = data
126+
127+
end subroutine queue_append_data

0 commit comments

Comments
 (0)