1
/* Copyright (C) 2006 Imperial College London and others.
3
Please see the AUTHORS file in the main source directory for a full list
7
Applied Modelling and Computation Group
8
Department of Earth Science and Engineering
9
Imperial College London
11
g.gorman@imperial.ac.uk
13
This library is free software; you can redistribute it and/or
14
modify it under the terms of the GNU Lesser General Public
15
License as published by the Free Software Foundation; either
16
version 2.1 of the License.
18
This library is distributed in the hope that it will be useful,
19
but WITHOUT ANY WARRANTY; without even the implied warranty of
20
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21
Lesser General Public License for more details.
23
You should have received a copy of the GNU Lesser General Public
24
License along with this library; if not, write to the Free Software
25
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
29
// Explination of sam options
32
// options[0]: m // Target number of partitions. If this is 0, then
33
// // the number of ranks in MPI_COMM_WORLD is assumed.
34
// options[1]: 1 // clean repartitioning into nparts
35
// 2 // re-partitioning (diffusive) - local optimization
36
// 3 // re-partitioning (directed diffusion) - global optimization
37
// 4 // re-partitioning (repartition-remapping)
38
// options[2]: 1 // homogenious processing power
39
// 2 // hetrogenious processing power
40
// options[3]: 1 // no node weights
41
// 2 // calculate edge weights based on the projected
42
// density of nodes in the future
43
// options[4]: 1 // no edge weights
44
// 2 // calculate edge weights optimizing for adaptivity
45
// 3 // calculate edge weights based on curvature of fields
46
// options[5]: 1 // simple mesh
47
// 2 // mixed formulation
60
#define sam_fc F77_FUNC(sam, SAM)
61
#define sam_init_fc F77_FUNC(sam_init_c, SAM_INIT_C)
62
#define sam_migrate_fc F77_FUNC(sam_migrate_c, SAM_MIGRATE_C)
63
#define sam_query_fc F77_FUNC(sam_query_c, SAM_QUERY_C)
64
#define sam_export_mesh_fc F77_FUNC(sam_export_mesh_c, SAM_EXPORT_MESH_C)
65
#define sam_export_halo_fc F77_FUNC(sam_export_halo_c, SAM_EXPORT_HALO_C)
66
#define sam_export_phalo_fc F77_FUNC(sam_export_phalo_c, SAM_EXPORT_PHALO_C)
67
#define sam_cleanup_fc F77_FUNC(sam_cleanup_c, SAM_CLEANUP_C)
68
#define sam_add_field_fc F77_FUNC(sam_add_field_c, SAM_ADD_FIELD_C)
69
#define sam_pop_field_fc F77_FUNC(sam_pop_field_c, SAM_POP_FIELD_C)
70
#define sam_export_node_ownership_fc F77_FUNC(sam_export_node_ownership_c, SAM_EXPORT_NODE_OWNERSHIP_C)
72
// "Mesh" is the principle object that does everything for SAM.
74
vector<int> decomp_opts;
79
const int* dim, const int *NNodes, const int *NElems, const int *NSElems,
80
const int GATHER[], const int ATOSEN[],
81
const int SCATER[], const int ATOREC[],
82
const int* ncolga, const int* nscate, const int* nprocs,
83
const int ENLIST[], const int *nloc,
84
const int SNLIST[], const int SURFID[], const int *snloc,
85
const samfloat_t NODX[], const samfloat_t NODY[], const samfloat_t NODZ[],
86
samfloat_t Metric[], const samfloat_t FIELDS[], const int *NFIELDS,
87
const int options[], const samfloat_t *fxnl_tol){
97
mesh->mixed_formulation(options[5] == 2);
100
if( mesh->mixed_formulation() )
101
ECHO("Mixed-formulation capabilities have been enabled.");
103
// Slurp in Fluiditys' mesh
104
ECHO("Importing mesh");
105
mesh->import_fluidity(*dim, *NNodes, *NElems, *NSElems, *NNodes,
106
*NFIELDS, NODX, NODY, NODZ, Metric, FIELDS,
108
SNLIST, SURFID, *snloc,
111
ECHO("Mesh imported");
114
decomp_opts.resize(5);
116
decomp_opts[i] = options[i];
118
mesh->set_functional_tol(*fxnl_tol);
120
if( (options[2] == 2)&&(options[3] == 2) ){
121
cout<<"WARNING: It has been requested to load balance the mesh on a system with "
122
<< "heterogeneous point-to-point bandwidth and heterogeneous processing power."
123
<< "This is a non-trivial request. SAM promises to do his best, but don't "
124
<< "expect wonders."<< endl;
130
void sam_migrate_fc(void)
133
assert(mesh != NULL);
135
// Graph partitioning.
136
ECHO("Partitioning mesh...");
137
noddom = mesh->decomp( decomp_opts );
138
ECHO("...partitioned.");
140
// Migrate Mesh according to noddom.
141
ECHO("Migrating mesh...");
142
mesh->migrate( noddom );
143
ECHO("...migrated.");
145
if(mesh->mixed_formulation()){
146
mesh->invent_pressure_mesh();
153
void sam_query_fc(int* NONODS, int* TOTELE, int* STOTEL,
154
int* ncolga, int* nscate, int* pncolga, int* pnscate)
157
assert(mesh != NULL);
159
mesh->do_element_headcount();
160
*NONODS = mesh->node_list.size();
161
*TOTELE = mesh->num_elements("volume");
162
*STOTEL = mesh->num_elements("surface");
164
*ncolga = mesh->get_ncolga();
165
*nscate = mesh->get_nscate();
167
if(mesh->mixed_formulation())
169
*pncolga = mesh->get_pncolga();
170
*pnscate = mesh->get_pnscate();
181
void sam_export_mesh_fc(int* nonods, int* totele, int* stotel, int* nloc, int* snloc,
182
samfloat_t* NODX, samfloat_t* NODY, samfloat_t* NODZ, int* ENLIST, int* SENLIST, int* SURFID)
185
assert(mesh != NULL);
190
for(deque<Node>::iterator in=mesh->node_list.begin(); in != mesh->node_list.end(); ++in){
191
switch(in->get_size_x()){
193
NODZ[i] = in->get_z();
195
NODY[i] = in->get_y();
197
NODX[i] = in->get_x();
200
ERROR("Invalid dimension");
206
int num_elements = mesh->element_list.size();
207
vector<int> elm_owner(num_elements);
208
for(int i=0;i<num_elements;i++){
209
vector<unn_t> enl(mesh->element_list[i].get_enlist());
211
vector<unn_t>::iterator it=enl.begin();
212
int gnn = mesh->unn2gnn(*it);
213
elm_owner[i] = mesh->node_list[gnn].get_future_owner();
215
for(;it!=enl.end();++it){
216
gnn = mesh->unn2gnn(*it);
217
elm_owner[i] = min(elm_owner[i], (int)mesh->node_list[gnn].get_future_owner());
221
int MyRank = MPI::COMM_WORLD.Get_rank();
223
{ // Compress volume element-node lists
225
vector<int> halo_elements;
226
for(int e=0;e<num_elements;e++){
227
unsigned char type = mesh->element_list[e].get_flags();
228
if( type & ELM_VOLUME ){
229
vector<unn_t> enl(mesh->element_list[e].get_enlist());
231
if(elm_owner[e]==MyRank){
232
for(vector<unn_t>::const_iterator it=enl.begin(); it!=enl.end(); ++it){
233
ENLIST[i++] = mesh->unn2gnn(*it) + 1;
236
for(vector<unn_t>::const_iterator it=enl.begin(); it!=enl.end(); ++it){
237
halo_elements.push_back(mesh->unn2gnn(*it) + 1);
242
for(vector<int>::const_iterator it=halo_elements.begin();it!=halo_elements.end();++it){
248
// Compress surface element-node list and write the surface id's.
249
mesh->do_element_headcount();
251
int NewNSElems = mesh->num_elements("surface");
255
vector<int> halo_elements, halo_element_ids;
256
for(int e=0;e<num_elements;e++){
257
unsigned char type = mesh->element_list[e].get_flags();
258
if( type & ELM_SURFACE ){
259
assert(pos<NewNSElems);
261
vector<unn_t> enl( mesh->element_list[e].get_enlist() );
262
const vector<int>& ifields = mesh->element_list[e].get_ifields();
263
if(elm_owner[e]==MyRank){
264
for(vector<unn_t>::const_iterator it = enl.begin(); it != enl.end(); ++it){
265
SENLIST[i++] = mesh->unn2gnn(*it) + 1;
267
SURFID[pos++] = ifields[0];
269
for(vector<unn_t>::const_iterator it = enl.begin(); it != enl.end(); ++it){
270
halo_elements.push_back(mesh->unn2gnn(*it) + 1);
272
halo_element_ids.push_back(ifields[0]);
276
for(vector<int>::const_iterator it=halo_elements.begin();it!=halo_elements.end();++it){
279
for(vector<int>::const_iterator it=halo_element_ids.begin();it!=halo_element_ids.end();++it){
287
void sam_export_halo_fc(int* colgat, int* atosen, int* scater, int* atorec, const int* ncolga, const int* nscate, const int* nprocs, int* pnodes, int* nnodes){
289
assert(mesh != NULL);
291
mesh->export_halo(colgat, atosen, scater, atorec, ncolga, nscate, nprocs);
293
*pnodes = mesh->node_list.psize();
294
*nnodes = mesh->node_list.size();
299
void sam_export_phalo_fc(int* pcolgat, int* patosen, int* pscater, int* patorec, const int* pncolga, const int* pnscate, const int* nprocs, int* ppnodes, int* pnnodes){
301
assert(mesh != NULL);
303
mesh->export_phalo(pcolgat, patosen, pscater, patorec, pncolga, pnscate, nprocs);
304
*ppnodes = mesh->MFnode_list.psize();
305
*pnnodes = mesh->MFnode_list.size();
310
void sam_cleanup_fc(void){
322
void sam_add_field_fc(samfloat_t* field_data, int *nnodes){
324
assert(mesh != NULL);
326
assert(mesh->node_list.size() == (size_t)*nnodes);
327
for(size_t i=0;i<mesh->node_list.size();i++){
328
mesh->node_list[i].append_field(field_data + i, 1);
334
void sam_pop_field_fc(samfloat_t* field_data, int *nnodes){
336
assert(mesh != NULL);
338
assert(mesh->node_list.size() == (size_t)*nnodes);
339
for (size_t i=0;i<mesh->node_list.size();i++){
340
field_data[i] = mesh->node_list[i].pop_field();
346
void sam_export_node_ownership_fc(int* node_ownership, int* nnodes){
347
assert(noddom.size() == *nnodes);
349
for(int i = 0;i < *nnodes;i++){
350
node_ownership[i] = noddom[i];