00001
00002
00003
00004
00005
00006
00007
00008 #if defined (ALBANY_LCM) && defined(ALBANY_ZOLTAN)
00009
00010 #include <algorithm>
00011 #include <cassert>
00012 #include <cstdlib>
00013 #include <fstream>
00014 #include <iomanip>
00015 #include <iterator>
00016 #include <sstream>
00017 #include <string>
00018
00019 #include <boost/graph/adjacency_list.hpp>
00020 #include <boost/graph/connected_components.hpp>
00021
00022 #include "LCMPartition.h"
00023
00024 using Intrepid::Index;
00025 using Intrepid::Vector;
00026 using Teuchos::ArrayRCP;
00027
00028 namespace LCM {
00029
00030
00031
00032
00033 namespace {
00034
00035
00036
00037
00038
00039 void PrintPartitionInfo(
00040 std::ostream & output_stream,
00041 int &changes,
00042 int &num_gid_entries,
00043 int &num_lid_entries,
00044 int &num_import,
00045 ZOLTAN_ID_PTR &import_global_ids,
00046 ZOLTAN_ID_PTR &import_local_ids,
00047 int * &import_procs,
00048 int * &import_to_part,
00049 int &num_export,
00050 ZOLTAN_ID_PTR &export_global_ids,
00051 ZOLTAN_ID_PTR &export_local_ids,
00052 int * &export_procs,
00053 int * &export_to_part )
00054 {
00055
00056 output_stream << "Changes : " << changes << '\n';
00057 output_stream << "Number GID entries: " << num_gid_entries << '\n';
00058 output_stream << "Number LID entries: " << num_lid_entries << '\n';
00059 output_stream << "Number to import : " << num_import << '\n';
00060 output_stream << "Number to export : " << num_export << '\n';
00061
00062 output_stream << "Import GIDs:" << '\n';
00063 for (int i = 0; i < num_import; ++i) {
00064 output_stream << import_global_ids[i] << '\n';
00065 }
00066
00067 output_stream << "Import LIDs:" << '\n';
00068 for (int i = 0; i < num_import; ++i) {
00069 output_stream << import_local_ids[i] << '\n';
00070 }
00071
00072 output_stream << "Import procs:" << '\n';
00073 for (int i = 0; i < num_import; ++i) {
00074 output_stream << import_procs[i] << '\n';
00075 }
00076
00077 output_stream << "Import parts:" << '\n';
00078 for (int i = 0; i < num_import; ++i) {
00079 output_stream << import_to_part[i] << '\n';
00080 }
00081
00082 output_stream << "Export GIDs:" << '\n';
00083 for (int i = 0; i < num_export; ++i) {
00084 output_stream << export_global_ids[i] << '\n';
00085 }
00086
00087 output_stream << "Export LIDs:" << '\n';
00088 for (int i = 0; i < num_export; ++i) {
00089 output_stream << export_local_ids[i] << '\n';
00090 }
00091
00092 output_stream << "Export procs:" << '\n';
00093 for (int i = 0; i < num_export; ++i) {
00094 output_stream << export_procs[i] << '\n';
00095 }
00096
00097 output_stream << "Export parts:" << '\n';
00098 for (int i = 0; i < num_export; ++i) {
00099 output_stream << export_to_part[i] << '\n';
00100 }
00101
00102 }
00103
00104
00105
00106
00107
00108
00109 boost::tuple< Vector<double>, Vector<double>, Vector<double> >
00110 bounds_and_sum_subset(
00111 std::vector< Vector<double> > const & points,
00112 std::set<Index> const & indices)
00113 {
00114 assert(points.size() > 0);
00115 assert(indices.size() > 0);
00116
00117 Index const
00118 first = *indices.begin();
00119
00120 Vector<double>
00121 sum = points[first];
00122
00123 Vector<double>
00124 lower_corner = sum;
00125
00126 Vector<double>
00127 upper_corner = sum;
00128
00129 Index const
00130 N = sum.get_dimension();
00131
00132 for (std::set<Index>::const_iterator it = ++indices.begin();
00133 it != indices.end();
00134 ++it) {
00135
00136 Index const
00137 index = *it;
00138
00139 Vector<double> const &
00140 p = points[index];
00141
00142 sum += p;
00143
00144 for (Index i = 0; i < N; ++i) {
00145 lower_corner(i) = std::min(lower_corner(i), p(i));
00146 upper_corner(i) = std::max(upper_corner(i), p(i));
00147 }
00148
00149 }
00150
00151 return boost::make_tuple(lower_corner, upper_corner, sum);
00152 }
00153
00154
00155
00156
00157
00158
00159 Index
00160 closest_subset(
00161 Vector<double> const & point,
00162 std::vector< ClusterCenter > const & centers,
00163 std::set<Index> const & indices)
00164 {
00165 assert(centers.size() > 0);
00166 assert(indices.size() > 0);
00167
00168 Index const
00169 first = *indices.begin();
00170
00171 double
00172 minimum = norm_square(centers[first].position - point);
00173
00174 Index
00175 index_minimum = first;
00176
00177 for (std::set<Index>::const_iterator it = ++indices.begin();
00178 it != indices.end();
00179 ++it) {
00180
00181 Index const
00182 index = *it;
00183
00184 Vector<double> const &
00185 p = centers[index].position;
00186
00187 double const
00188 s = norm_square(p - point);
00189
00190 if (s < minimum) {
00191 minimum = s;
00192 index_minimum = index;
00193 }
00194
00195 }
00196
00197 return index_minimum;
00198 }
00199
00200
00201
00202
00203
00204
00205
00206 std::pair< std::set<Index>, std::set<Index> >
00207 split_box(
00208 std::vector< Vector<double> > const & points,
00209 std::set<Index> const & indices)
00210 {
00211 assert(points.size() > 0);
00212 assert(indices.size() > 0);
00213
00214
00215
00216
00217 Index const
00218 first = *indices.begin();
00219
00220 Vector<double>
00221 lower_corner = points[first];
00222
00223 Vector<double>
00224 upper_corner = lower_corner;
00225
00226 Index const
00227 N = lower_corner.get_dimension();
00228
00229 for (std::set<Index>::const_iterator it = ++indices.begin();
00230 it != indices.end();
00231 ++it) {
00232
00233 Index const
00234 index = *it;
00235
00236 Vector<double> const &
00237 p = points[index];
00238
00239 for (Index i = 0; i < N; ++i) {
00240 lower_corner(i) = std::min(lower_corner(i), p(i));
00241 upper_corner(i) = std::max(upper_corner(i), p(i));
00242 }
00243
00244 }
00245
00246
00247
00248
00249 Vector<double> const
00250 span = upper_corner - lower_corner;
00251
00252 assert(norm_square(span) > 0.0);
00253
00254 double
00255 maximum_span = span(0);
00256
00257 Index
00258 largest_dimension = 0;
00259
00260 for (Index i = 1; i < N; ++i) {
00261
00262 double const
00263 s = span(i);
00264
00265 if (s > maximum_span) {
00266 maximum_span = s;
00267 largest_dimension = i;
00268 }
00269
00270 }
00271
00272
00273
00274
00275 std::vector<double>
00276 coordinates;
00277
00278 for (std::set<Index>::const_iterator it = indices.begin();
00279 it != indices.end();
00280 ++it) {
00281
00282 Index const
00283 index = *it;
00284
00285 Vector<double> const &
00286 p = points[index];
00287
00288 coordinates.push_back(p(largest_dimension));
00289
00290 }
00291
00292 std::sort(coordinates.begin(), coordinates.end());
00293
00294 double
00295 split_coordinate =
00296 Intrepid::median<double>(coordinates.begin(), coordinates.end());
00297
00298
00299
00300
00301
00302
00303 bool const
00304 box_unchanged =
00305 split_coordinate == lower_corner(largest_dimension) ||
00306 split_coordinate == upper_corner(largest_dimension);
00307
00308 if (box_unchanged == true) {
00309
00310 std::sort(coordinates.begin(), coordinates.end());
00311
00312 split_coordinate =
00313 0.5 * (coordinates[0] + coordinates[coordinates.size() - 1]);
00314
00315 }
00316
00317
00318
00319
00320 std::set<Index>
00321 indices_lower;
00322
00323 std::set<Index>
00324 indices_upper;
00325
00326 Vector<double>
00327 split_limit = upper_corner;
00328
00329 split_limit(largest_dimension) = split_coordinate;
00330
00331 for (std::set<Index>::const_iterator it = indices.begin();
00332 it != indices.end();
00333 ++it) {
00334
00335 Index const
00336 index = *it;
00337
00338 Vector<double> const &
00339 p = points[index];
00340
00341 if (in_box(p, lower_corner, split_limit) == true) {
00342 indices_lower.insert(index);
00343 } else {
00344 indices_upper.insert(index);
00345 }
00346
00347 }
00348
00349 return std::make_pair(indices_lower, indices_upper);
00350 }
00351
00352 }
00353
00354
00355
00356
00357
00358
00359 template<typename Node>
00360 boost::shared_ptr<Node>
00361 BuildKDTree(std::vector< Vector<double> > const & points)
00362 {
00363
00364
00365
00366
00367 Index const
00368 number_points = points.size();
00369
00370 std::set<Index>
00371 points_indices;
00372
00373 for (Index i = 0; i < number_points; ++i) {
00374 points_indices.insert(i);
00375 }
00376
00377 boost::shared_ptr<Node>
00378 dummy;
00379
00380 std::string
00381 name = "0";
00382
00383 boost::shared_ptr<Node>
00384 root = CreateKDTreeNode(name, dummy, points, points_indices);
00385
00386 return root;
00387 }
00388
00389
00390
00391
00392
00393
00394 template<typename Node>
00395 boost::shared_ptr<Node>
00396 CreateKDTreeNode(
00397 std::string const & name,
00398 boost::shared_ptr<Node> parent,
00399 std::vector< Vector<double> > const & points,
00400 std::set<Index> const & points_indices)
00401 {
00402 if (name.length() >=64) {
00403 std::cout << "Name is too long: " << name << '\n';
00404 }
00405
00406
00407
00408
00409 boost::shared_ptr<Node>
00410 node(new Node);
00411
00412 node->name = name;
00413
00414 node->parent = parent;
00415
00416 Index const
00417 count = points_indices.size();
00418
00419 node->count = count;
00420 node->cell_points = points_indices;
00421
00422 switch (count) {
00423
00424
00425 case 0:
00426 break;
00427
00428
00429 case 1:
00430 {
00431 Vector<double> const &
00432 p = points[*points_indices.begin()];
00433 node->lower_corner = p;
00434 node->upper_corner = p;
00435 node->weighted_centroid = p;
00436 }
00437 break;
00438
00439 default:
00440 {
00441 boost::tie(
00442 node->lower_corner,
00443 node->upper_corner,
00444 node->weighted_centroid) =
00445 bounds_and_sum_subset(points, points_indices);
00446
00447 std::set<Index>
00448 indices_left;
00449
00450 std::set<Index>
00451 indices_right;
00452
00453 boost::tie(indices_left, indices_right) =
00454 split_box(points, points_indices);
00455
00456 std::string
00457 name_left = name + "0";
00458
00459 std::string
00460 name_right = name + "1";
00461
00462 node->left =
00463 CreateKDTreeNode(name_left, node, points, indices_left);
00464
00465 node->right =
00466 CreateKDTreeNode(name_right, node, points, indices_right);
00467 }
00468 break;
00469
00470 }
00471
00472 return node;
00473 }
00474
00475
00476
00477
00478 template<typename Node>
00479 KDTree<Node>::KDTree(
00480 std::vector<Vector<double> > const & points,
00481 Index const number_centers)
00482 {
00483 root_ = BuildKDTree<Node>(points);
00484
00485
00486 std::set<Index>
00487 candidate_centers;
00488
00489 for (Index i = 0; i < number_centers; ++i) {
00490 candidate_centers.insert(i);
00491 }
00492
00493 root_->candidate_centers = candidate_centers;
00494
00495 return;
00496 }
00497
00498
00499
00500
00501
00502 template<typename Node, typename Visitor>
00503 void
00504 VisitTreeNode(Node & node, Visitor const & visitor)
00505 {
00506 if (visitor.pre_stop(node) == true) return;
00507
00508 visitor(node);
00509
00510 if (visitor.post_stop(node) == true) return;
00511
00512 VisitTreeNode(node->left, visitor);
00513 VisitTreeNode(node->right, visitor);
00514
00515 return;
00516 }
00517
00518
00519
00520
00521 template<typename Tree, typename Visitor>
00522 void
00523 TraverseTree(Tree & tree, Visitor const & visitor)
00524 {
00525 VisitTreeNode(tree.get_root(), visitor);
00526 return;
00527 }
00528
00529
00530
00531
00532 template<typename Node>
00533 void
00534 OutputVisitor<Node>::operator()(Node const & node) const
00535 {
00536 std::cout << "Node : " << node->name << '\n';
00537 std::cout << "Count : " << node->count << '\n';
00538 std::cout << "Lower corner: " << node->lower_corner << '\n';
00539 std::cout << "Upper corner: " << node->upper_corner << '\n';
00540
00541 Vector<double>
00542 centroid = node->weighted_centroid / node->count;
00543
00544 std::cout << "Centroid : " << centroid << '\n';
00545
00546 return;
00547 }
00548
00549
00550
00551
00552 template<typename Node>
00553 bool
00554 OutputVisitor<Node>::pre_stop(Node const & node) const
00555 {
00556 return node.get() == NULL;
00557 }
00558
00559
00560
00561
00562 template<typename Node>
00563 bool
00564 OutputVisitor<Node>::post_stop(Node const & node) const
00565 {
00566 return false;
00567 }
00568
00569
00570
00571
00572 template<typename Node, typename Center>
00573 FilterVisitor<Node, Center>::FilterVisitor(
00574 std::vector<Vector<double> > & p,
00575 std::vector<Center> & c) :
00576 points(p),
00577 centers(c)
00578 {
00579 }
00580
00581 namespace {
00582
00583 template<typename Center, typename Iterator>
00584 Index
00585 closest_center_from_subset(
00586 Vector<double> const & point,
00587 std::vector<Center> const & centers,
00588 Iterator begin,
00589 Iterator end)
00590 {
00591 assert(std::distance(begin, end) > 0);
00592
00593 Index
00594 closest_index = *begin;
00595
00596 double
00597 minimum_distance = norm_square(point - centers[closest_index].position);
00598
00599 for (Iterator it = ++begin; it != end; ++it) {
00600
00601 Index const
00602 i = *it;
00603
00604 double const
00605 s = norm_square(point - centers[i].position);
00606
00607 if (s < minimum_distance) {
00608 closest_index = i;
00609 minimum_distance = s;
00610 }
00611
00612 }
00613
00614 return closest_index;
00615
00616 }
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627 template<typename Center>
00628 std::pair<Index, std::set<Index> >
00629 box_proximity_to_centers(
00630 Vector<double> const & lower_corner,
00631 Vector<double> const & upper_corner,
00632 std::vector<Center> const & centers,
00633 std::set<Index> const & index_subset)
00634 {
00635 assert(centers.size() > 0);
00636 assert(index_subset.size() > 0);
00637
00638 Vector<double> const
00639 midcell = 0.5 * (lower_corner + upper_corner);
00640
00641
00642
00643 Index
00644 index_closest = *index_subset.begin();
00645
00646 double
00647 minimum = norm_square(midcell - centers[index_closest].position);
00648
00649 for (std::set<Index>::const_iterator
00650 index_iterator = ++index_subset.begin();
00651 index_iterator != index_subset.end();
00652 ++index_iterator) {
00653
00654 Index const
00655 i = *index_iterator;
00656
00657 double const
00658 s = norm_square(midcell - centers[i].position);
00659
00660 if (s < minimum) {
00661 index_closest = i;
00662 minimum = s;
00663 }
00664
00665 }
00666
00667 Vector<double> const &
00668 closest_to_midcell = centers[index_closest].position;
00669
00670 std::set<Index>
00671 indices_candidates;
00672
00673
00674 for (std::set<Index>::const_iterator index_iterator = index_subset.begin();
00675 index_iterator != index_subset.end();
00676 ++index_iterator) {
00677
00678 Index const
00679 i = *index_iterator;
00680
00681 if (i == index_closest) {
00682 indices_candidates.insert(i);
00683 continue;
00684 }
00685
00686 Vector<double> const &
00687 p = centers[i].position;
00688
00689 Vector<double> const
00690 u = p - closest_to_midcell;
00691
00692 Index const
00693 N = u.get_dimension();
00694
00695 Vector<double>
00696 v(N);
00697
00698 for (Index j = 0; j < N; ++j) {
00699
00700 v(j) = u(j) >= 0.0 ? upper_corner(j) : lower_corner(j);
00701
00702 }
00703
00704 if (norm_square(p - v) < norm_square(closest_to_midcell - v)) {
00705 indices_candidates.insert(i);
00706 }
00707
00708 }
00709
00710 return std::make_pair(index_closest, indices_candidates);
00711 }
00712
00713 }
00714
00715
00716
00717
00718 template<typename Node, typename Center>
00719 void
00720 FilterVisitor<Node, Center>::operator()(Node const & node) const
00721 {
00722 bool const
00723 node_is_empty = node->count == 0;
00724
00725 if (node_is_empty == true) {
00726 return;
00727 }
00728
00729 bool const
00730 node_is_leaf = node->count == 1;
00731
00732 if (node_is_leaf == true) {
00733
00734
00735 Index const
00736 point_index = *(node->cell_points.begin());
00737
00738 Vector<double> const &
00739 point = points[point_index];
00740
00741
00742 Index
00743 index_closest =
00744 closest_center_from_subset(
00745 point,
00746 centers,
00747 node->candidate_centers.begin(),
00748 node->candidate_centers.end());
00749
00750
00751 Center &
00752 closest_center = centers[index_closest];
00753
00754 closest_center.weighted_centroid += point;
00755 ++closest_center.count;
00756
00757 node->closest_center_to_midcell = index_closest;
00758
00759 } else {
00760
00761
00762 Index
00763 index_closest_midcell = 0;
00764
00765 std::set<Index>
00766 candidate_indices;
00767
00768 boost::tie(index_closest_midcell, candidate_indices) =
00769 box_proximity_to_centers(
00770 node->lower_corner,
00771 node->upper_corner,
00772 centers,
00773 node->candidate_centers);
00774
00775 node->candidate_centers = candidate_indices;
00776
00777 if (candidate_indices.size() == 1) {
00778
00779 Center &
00780 center = centers[index_closest_midcell];
00781
00782 center.weighted_centroid += node->weighted_centroid;
00783 center.count += node->count;
00784 } else {
00785
00786
00787 node->left->candidate_centers = candidate_indices;
00788 node->right->candidate_centers = candidate_indices;
00789 }
00790
00791 node->closest_center_to_midcell = index_closest_midcell;
00792
00793 }
00794
00795 return;
00796 }
00797
00798
00799
00800
00801 template<typename Node, typename Center>
00802 bool
00803 FilterVisitor<Node, Center>::pre_stop(Node const & node) const
00804 {
00805 bool const
00806 has_no_centers = node->candidate_centers.size() == 0;
00807
00808 return has_no_centers == true;
00809 }
00810
00811
00812
00813
00814 template<typename Node, typename Center>
00815 bool
00816 FilterVisitor<Node, Center>::post_stop(Node const & node) const
00817 {
00818 bool const
00819 node_is_leaf = node->count <= 1;
00820
00821 bool const
00822 has_single_center = node->candidate_centers.size() == 1;
00823
00824 bool const
00825 stop_traversal = node_is_leaf || has_single_center;
00826
00827 return stop_traversal == true;
00828 }
00829
00830
00831
00832
00833 ConnectivityArray::ConnectivityArray() :
00834 type_(Intrepid::ELEMENT::UNKNOWN),
00835 dimension_(0),
00836 discretization_ptr_(Teuchos::null),
00837 tolerance_(0.0),
00838 requested_cell_size_(0.0),
00839 maximum_iterations_(0),
00840 initializer_scheme_(PARTITION::HYPERGRAPH)
00841 {
00842 return;
00843 }
00844
00845
00846
00847
00848
00849
00850 ConnectivityArray::ConnectivityArray(
00851 std::string const & input_file,
00852 std::string const & output_file) :
00853 type_(Intrepid::ELEMENT::UNKNOWN),
00854 dimension_(0),
00855 discretization_ptr_(Teuchos::null),
00856 tolerance_(0.0),
00857 requested_cell_size_(0.0),
00858 maximum_iterations_(0),
00859 initializer_scheme_(PARTITION::HYPERGRAPH)
00860 {
00861
00862 using Albany::StateStruct;
00863
00864
00865
00866 Teuchos::RCP<Teuchos::ParameterList> params =
00867 rcp(new Teuchos::ParameterList("params"));
00868
00869
00870 Teuchos::RCP<Teuchos::ParameterList> disc_params =
00871 Teuchos::sublist(params, "Discretization");
00872
00873
00874 disc_params->set<std::string>("Method", "Exodus");
00875 disc_params->set<std::string>("Exodus Input File Name", input_file);
00876 disc_params->set<std::string>("Exodus Output File Name", output_file);
00877
00878 disc_params->set<int>("Workset Size", 10000);
00879
00880 Teuchos::RCP<Epetra_Comm>
00881 communicator = Albany::createEpetraCommFromMpiComm(Albany_MPI_COMM_WORLD);
00882
00883 Albany::DiscretizationFactory
00884 disc_factory(params, communicator);
00885
00886 ArrayRCP<Teuchos::RCP<Albany::MeshSpecsStruct> >
00887 mesh_specs = disc_factory.createMeshSpecs();
00888
00889 int
00890 workset_size = mesh_specs[0]->worksetSize;
00891
00892
00893
00894
00895 Teuchos::RCP<Albany::StateInfoStruct>
00896 state_info = Teuchos::rcp(new Albany::StateInfoStruct());
00897
00898 StateStruct::FieldDims dims;
00899
00900 dims.push_back(workset_size); dims.push_back(1);
00901
00902 state_info->push_back(Teuchos::rcp(
00903 new StateStruct("Partition", StateStruct::QuadPoint, dims, "scalar")));
00904
00905
00906 Albany::AbstractFieldContainer::FieldContainerRequirements
00907 req;
00908
00909 discretization_ptr_ = disc_factory.createDiscretization(1, state_info, req);
00910
00911 dimension_ = mesh_specs[0]->numDim;
00912
00913
00914 Albany::WorksetArray<ArrayRCP<ArrayRCP<ArrayRCP<int> > > >::type const &
00915 element_connectivity = discretization_ptr_->getWsElNodeEqID();
00916
00917 ArrayRCP<double>
00918 coordinates = discretization_ptr_->getCoordinates();
00919
00920
00921
00922
00923 const CellTopologyData
00924 cell_topology = mesh_specs[0]->ctd;
00925
00926 Index const
00927 dimension = cell_topology.dimension;
00928
00929 assert(dimension == dimension_);
00930
00931 int const
00932 vertices_per_element = cell_topology.vertex_count;
00933
00934 type_ = Intrepid::find_type(dimension, vertices_per_element);
00935
00936
00937 ArrayRCP<int>::size_type
00938 nodes_per_element = element_connectivity[0][0].size();
00939
00940
00941 int const number_equations = element_connectivity[0][0][0].size();
00942 int stride = 1;
00943 if (number_equations > 1) {
00944 if (element_connectivity[0][0][0][0] + 1 ==
00945 element_connectivity[0][0][0][1]) {
00946
00947 stride = number_equations;
00948 }
00949 }
00950
00951
00952
00953
00954 ArrayRCP<double>::size_type
00955 number_nodes = coordinates.size() / dimension;
00956
00957 for (ArrayRCP<double>::size_type
00958 node = 0;
00959 node < number_nodes;
00960 ++node) {
00961
00962 Vector<double> point(0.0, 0.0, 0.0);
00963
00964 for (Index j = 0; j < dimension; ++j) {
00965 point(j) = coordinates[node * dimension + j];
00966 }
00967
00968 nodes_.insert(std::make_pair(node, point));
00969 }
00970
00971
00972
00973
00974 ArrayRCP<ArrayRCP<int> >::size_type
00975 element_number = 0;
00976
00977 ArrayRCP<ArrayRCP<ArrayRCP<int> > >::size_type
00978 workset = 0;
00979
00980 for (workset = 0; workset < element_connectivity.size(); ++workset) {
00981
00982 for (ArrayRCP<ArrayRCP<int> >::size_type
00983 cell = 0;
00984 cell < element_connectivity[workset].size();
00985 ++cell, ++element_number) {
00986
00987 IDList
00988 nodes_element(nodes_per_element);
00989
00990 for (ArrayRCP<int>::size_type
00991 node = 0;
00992 node < vertices_per_element;
00993 ++node) {
00994
00995
00996 nodes_element[node] =
00997 element_connectivity[workset][cell][node][0] / stride;
00998
00999 }
01000
01001 connectivity_.insert(std::make_pair(element_number, nodes_element));
01002
01003 }
01004
01005 }
01006
01007 return;
01008 }
01009
01010
01011
01012
01013
01014 Index
01015 ConnectivityArray::GetNumberNodes() const
01016 {
01017 return nodes_.size();
01018 }
01019
01020
01021
01022
01023 Index
01024 ConnectivityArray::GetNumberElements() const
01025 {
01026 return connectivity_.size();
01027 }
01028
01029
01030
01031
01032 Index
01033 ConnectivityArray::GetDimension() const
01034 {
01035 return dimension_;
01036 }
01037
01038
01039
01040
01041 double
01042 ConnectivityArray::GetTolerance() const
01043 {
01044 return tolerance_;
01045 }
01046
01047
01048
01049
01050 double
01051 ConnectivityArray::GetCellSize() const
01052 {
01053 return requested_cell_size_;
01054 }
01055
01056
01057
01058
01059 Index
01060 ConnectivityArray::GetMaximumIterations() const
01061 {
01062 return maximum_iterations_;
01063 }
01064
01065
01066
01067
01068 void
01069 ConnectivityArray::SetTolerance(double tolerance)
01070 {
01071 tolerance_ = tolerance;
01072 }
01073
01074
01075
01076
01077 void
01078 ConnectivityArray::SetCellSize(double requested_cell_size)
01079 {
01080 requested_cell_size_ = requested_cell_size;
01081 }
01082
01083
01084
01085
01086 void
01087 ConnectivityArray::SetMaximumIterations(Index maximum_iterarions)
01088 {
01089 maximum_iterations_ = maximum_iterarions;
01090 }
01091
01092
01093
01094
01095 void
01096 ConnectivityArray::SetInitializerScheme(PARTITION::Scheme initializer_scheme)
01097 {
01098 initializer_scheme_ = initializer_scheme;
01099 }
01100
01101
01102
01103
01104 PARTITION::Scheme
01105 ConnectivityArray::GetInitializerScheme() const
01106 {
01107 return initializer_scheme_;
01108 }
01109
01110
01111
01112
01113
01114 Intrepid::ELEMENT::Type
01115 ConnectivityArray::GetType() const
01116 {
01117 return type_;
01118 }
01119
01120
01121
01122
01123 PointMap
01124 ConnectivityArray::GetNodeList() const
01125 {
01126 return nodes_;
01127 }
01128
01129
01130
01131
01132 AdjacencyMap
01133 ConnectivityArray::GetConnectivity() const
01134 {
01135 return connectivity_;
01136 }
01137
01138
01139
01140
01141 Albany::AbstractDiscretization &
01142 ConnectivityArray::GetDiscretization()
01143 {
01144 return (*discretization_ptr_.get());
01145 }
01146
01147
01148
01149
01150
01151 Index
01152 ConnectivityArray::GetNodesPerElement() const
01153 {
01154 Index
01155 nodes_per_element;
01156
01157 switch (GetType()) {
01158
01159 default:
01160 std::cerr << "ERROR: Unknown element type in GetNodesPerElement()";
01161 std::cerr << '\n';
01162 exit(1);
01163 break;
01164
01165 case Intrepid::ELEMENT::SEGMENTAL:
01166 nodes_per_element = 2;
01167 break;
01168
01169 case Intrepid::ELEMENT::TRIANGULAR:
01170 nodes_per_element = 3;
01171 break;
01172
01173 case Intrepid::ELEMENT::QUADRILATERAL:
01174 nodes_per_element = 4;
01175 break;
01176
01177 case Intrepid::ELEMENT::TETRAHEDRAL:
01178 nodes_per_element = 4;
01179 break;
01180
01181 case Intrepid::ELEMENT::HEXAHEDRAL:
01182 nodes_per_element = 8;
01183 break;
01184
01185 }
01186
01187 return nodes_per_element;
01188 }
01189
01190
01191
01192
01193
01194 ScalarMap
01195 ConnectivityArray::GetVolumes() const
01196 {
01197 ScalarMap volumes;
01198 for (AdjacencyMap::const_iterator
01199 elements_iter = connectivity_.begin();
01200 elements_iter != connectivity_.end();
01201 ++elements_iter) {
01202
01203 int const &
01204 element = (*elements_iter).first;
01205
01206 IDList const &
01207 node_list = (*elements_iter).second;
01208
01209 std::vector< Vector<double> >
01210 points;
01211
01212 for (IDList::size_type
01213 i = 0;
01214 i < node_list.size();
01215 ++i) {
01216
01217 PointMap::const_iterator
01218 nodes_iter = nodes_.find(node_list[i]);
01219
01220 assert(nodes_iter != nodes_.end());
01221 points.push_back((*nodes_iter).second);
01222
01223 }
01224
01225 double volume = 0.0;
01226
01227 switch (type_) {
01228
01229 case Intrepid::ELEMENT::SEGMENTAL:
01230 volume = Intrepid::length(points[0], points[1]);
01231 break;
01232
01233 case Intrepid::ELEMENT::TRIANGULAR:
01234 volume = Intrepid::area(points[0], points[1], points[2]);
01235 break;
01236
01237 case Intrepid::ELEMENT::QUADRILATERAL:
01238 volume = Intrepid::area(points[0], points[1], points[2], points[3]);
01239 break;
01240
01241 case Intrepid::ELEMENT::TETRAHEDRAL:
01242 volume = Intrepid::volume(points[0], points[1], points[2], points[3]);
01243 break;
01244
01245 case Intrepid::ELEMENT::HEXAHEDRAL:
01246 volume = Intrepid::volume(points[0], points[1], points[2], points[3],
01247 points[4], points[5], points[6], points[7]);
01248 break;
01249
01250 default:
01251 std::cerr << "Unknown element type in calculating volume." << '\n';
01252 exit(1);
01253 break;
01254
01255 }
01256
01257 volumes.insert(std::make_pair(element, volume));
01258
01259 }
01260
01261 return volumes;
01262 }
01263
01264
01265
01266
01267 double
01268 ConnectivityArray::GetVolume() const
01269 {
01270 double volume = 0.0;
01271
01272 const ScalarMap
01273 volumes = GetVolumes();
01274
01275 for (ScalarMap::const_iterator
01276 volumes_iter = volumes.begin();
01277 volumes_iter != volumes.end();
01278 ++volumes_iter) {
01279
01280 volume += (*volumes_iter).second;
01281
01282 }
01283
01284 return volume;
01285 }
01286
01287
01288
01289
01290 std::map<int, int>
01291 ConnectivityArray::GetPartitions() const
01292 {
01293 return partitions_;
01294 }
01295
01296
01297
01298
01299 ScalarMap
01300 ConnectivityArray::GetPartitionVolumes() const
01301 {
01302 std::map<int, int>
01303 partitions = GetPartitions();
01304
01305 ScalarMap
01306 volumes = GetVolumes();
01307
01308 ScalarMap
01309 partition_volumes;
01310
01311 for (std::map<int, int>::const_iterator part_iter = partitions.begin();
01312 part_iter != partitions.end();
01313 ++part_iter) {
01314
01315 int element = (*part_iter).first;
01316 int partition = (*part_iter).second;
01317
01318 ScalarMap::const_iterator
01319 volumes_iterator = volumes.find(element);
01320
01321 if (volumes_iterator == volumes.end()) {
01322 std::cerr << "Cannot find volume for element " << element << '\n';
01323 exit(1);
01324 }
01325
01326 double volume = (*volumes_iterator).second;
01327
01328 ScalarMap::const_iterator
01329 partition_volumes_iter = partition_volumes.find(partition);
01330
01331 if (partition_volumes_iter == partition_volumes.end()) {
01332 partition_volumes[partition] = volume;
01333 } else {
01334 partition_volumes[partition] += volume;
01335 }
01336
01337 }
01338
01339 return partition_volumes;
01340 }
01341
01342
01343
01344
01345 std::vector< Vector<double> >
01346 ConnectivityArray::GetPartitionCentroids() const
01347 {
01348 std::map<int, int>
01349 partitions = GetPartitions();
01350
01351 ScalarMap
01352 element_volumes = GetVolumes();
01353
01354 ScalarMap
01355 partition_volumes = GetPartitionVolumes();
01356
01357 Index const
01358 number_partitions = partition_volumes.size();
01359
01360 std::vector< Vector<double> >
01361 partition_centroids(number_partitions);
01362
01363 for (Index i = 0; i < number_partitions; ++i) {
01364 partition_centroids[i].set_dimension(GetDimension());
01365 partition_centroids[i].clear();
01366 }
01367
01368
01369 Index const
01370 nodes_per_element = GetNodesPerElement();
01371
01372 for (std::map<int, int>::const_iterator partitions_iterator =
01373 partitions.begin();
01374 partitions_iterator != partitions.end();
01375 ++partitions_iterator) {
01376
01377 int
01378 element = (*partitions_iterator).first;
01379
01380 int
01381 partition = (*partitions_iterator).second;
01382
01383 AdjacencyMap::const_iterator
01384 elements_iterator = connectivity_.find(element);
01385
01386 if (elements_iterator == connectivity_.end()) {
01387 std::cerr << "Cannot find element in partition centroids." << element;
01388 std::cerr << '\n';
01389 exit(1);
01390 }
01391
01392 IDList const &
01393 node_list = (*elements_iterator).second;
01394
01395 std::vector< Vector<double> >
01396 element_nodes;
01397
01398 for (IDList::size_type i = 0; i < nodes_per_element; ++i) {
01399
01400 PointMap::const_iterator
01401 nodes_iterator = nodes_.find(node_list[i]);
01402
01403 assert(nodes_iterator != nodes_.end());
01404
01405 element_nodes.push_back((*nodes_iterator).second);
01406
01407 }
01408
01409 Vector<double> const
01410 element_centroid = centroid(element_nodes);
01411
01412 ScalarMap::const_iterator
01413 volumes_iterator = element_volumes.find(element);
01414
01415 if (volumes_iterator == element_volumes.end()) {
01416 std::cerr << "Cannot find volume for element " << element;
01417 std::cerr << '\n';
01418 exit(1);
01419 }
01420
01421 double
01422 element_volume = (*volumes_iterator).second;
01423
01424 partition_centroids[partition] += element_volume * element_centroid;
01425
01426 }
01427
01428 for (Index i = 0; i < number_partitions; ++i) {
01429 partition_centroids[i] = partition_centroids[i] / partition_volumes[i];
01430 }
01431
01432 return partition_centroids;
01433 }
01434
01435
01436
01437
01438 PointMap
01439 ConnectivityArray::GetCentroids() const
01440 {
01441 PointMap
01442 centroids;
01443
01444 for (AdjacencyMap::const_iterator
01445 elements_iter = connectivity_.begin();
01446 elements_iter != connectivity_.end();
01447 ++elements_iter) {
01448
01449
01450 int const &
01451 element = (*elements_iter).first;
01452
01453 IDList const &
01454 node_list = (*elements_iter).second;
01455
01456 std::vector< Vector<double> >
01457 points;
01458
01459
01460 for (IDList::size_type
01461 i = 0;
01462 i < node_list.size();
01463 ++i) {
01464
01465 int const
01466 node = node_list[i];
01467
01468 PointMap::const_iterator
01469 nodes_iter = nodes_.find(node);
01470
01471 assert(nodes_iter != nodes_.end());
01472
01473 Vector<double> const
01474 point = (*nodes_iter).second;
01475
01476 points.push_back(point);
01477
01478 }
01479
01480 Vector<double> const
01481 centroid = Intrepid::centroid(points);
01482
01483 centroids.insert(std::make_pair(element, centroid));
01484
01485 }
01486
01487 return centroids;
01488
01489 }
01490
01494 std::pair<Vector<double>, Vector<double> >
01495 ConnectivityArray::BoundingBox() const
01496 {
01497 PointMap::const_iterator
01498 it = nodes_.begin();
01499
01500 Vector<double>
01501 min = (*it).second;
01502
01503 Vector<double>
01504 max = min;
01505
01506 Index const
01507 N = min.get_dimension();
01508
01509 ++it;
01510
01511 for (; it != nodes_.end(); ++it) {
01512
01513 Vector<double> const &
01514 node = (*it).second;
01515
01516 for (Index i = 0; i < N; ++i) {
01517 min(i) = std::min(min(i), node(i));
01518 max(i) = std::max(max(i), node(i));
01519 }
01520
01521 }
01522
01523 return std::make_pair(min, max);
01524 }
01525
01526 namespace {
01527
01528 boost::tuple<Index, double, double>
01529 parametric_limits(Intrepid::ELEMENT::Type const element_type)
01530 {
01531 Index
01532 parametric_dimension = 3;
01533
01534 double
01535 parametric_size = 1.0;
01536
01537 double
01538 lower_limit = 0.0;
01539
01540 switch (element_type) {
01541
01542 default:
01543 std::cerr << "ERROR: Unknown element type in paramtetric_limits";
01544 std::cerr << '\n';
01545 exit(1);
01546 break;
01547
01548 case Intrepid::ELEMENT::TRIANGULAR:
01549 lower_limit = 0.0;
01550 parametric_size = 1.0;
01551 parametric_dimension = 3;
01552 break;
01553
01554 case Intrepid::ELEMENT::QUADRILATERAL:
01555 lower_limit = -1.0;
01556 parametric_size = 2.0;
01557 parametric_dimension = 2;
01558 break;
01559
01560 case Intrepid::ELEMENT::TETRAHEDRAL:
01561 lower_limit = 0.0;
01562 parametric_size = 1.0;
01563 parametric_dimension = 4;
01564 break;
01565
01566 case Intrepid::ELEMENT::HEXAHEDRAL:
01567 lower_limit = -1.0;
01568 parametric_size = 2.0;
01569 parametric_dimension = 3;
01570 break;
01571
01572 }
01573
01574 return boost::make_tuple(
01575 parametric_dimension,
01576 parametric_size,
01577 lower_limit);
01578 }
01579
01580 }
01581
01582
01583
01584
01585
01586
01587 std::vector< Vector<double> >
01588 ConnectivityArray::CreateGrid()
01589 {
01590 std::cout << '\n';
01591 std::cout << "Creating background mesh ..." << '\n';
01592
01593
01594
01595
01596 Vector<double>
01597 lower_corner;
01598
01599 Vector<double>
01600 upper_corner;
01601
01602 boost::tie(lower_corner, upper_corner) = BoundingBox();
01603
01604 Vector<double> const
01605 bounding_box_span = upper_corner - lower_corner;
01606
01607 Index const
01608 dimension = lower_corner.get_dimension();
01609
01610 double
01611 maximum_dimension = 0.0;
01612
01613 for (Index i = 0; i < dimension; ++i) {
01614 maximum_dimension = std::max(maximum_dimension, bounding_box_span(i));
01615 }
01616
01617 double const
01618 delta = GetCellSize();
01619
01620
01621
01622
01623 Vector<Index>
01624 cells_per_dimension(dimension);
01625
01626 cell_size_.set_dimension(dimension);
01627
01628 for (Index i = 0; i < dimension; ++i) {
01629
01630 Index const
01631 number_cells = std::ceil((bounding_box_span(i)) / delta);
01632
01633 cells_per_dimension(i) = number_cells;
01634 cell_size_(i) = bounding_box_span(i) / number_cells;
01635
01636 }
01637
01638
01639
01640
01641
01642
01643 cells_.resize(cells_per_dimension(0));
01644 for (Index i = 0; i < cells_per_dimension(0); ++i) {
01645 cells_[i].resize(cells_per_dimension(1));
01646 for (Index j = 0; j < cells_per_dimension(1); ++j) {
01647 cells_[i][j].resize(cells_per_dimension(2));
01648 for (Index k = 0; k < cells_per_dimension(2); ++k) {
01649 cells_[i][j][k] = false;
01650 }
01651 }
01652 }
01653
01654
01655 Index const
01656 nodes_per_element = GetNodesPerElement();
01657
01658 Index const
01659 number_of_elements = connectivity_.size();
01660
01661 for (AdjacencyMap::const_iterator
01662 elements_iter = connectivity_.begin();
01663 elements_iter != connectivity_.end();
01664 ++elements_iter) {
01665
01666 int const
01667 element = (*elements_iter).first;
01668
01669 if ((element + 1) % 10000 == 0) {
01670 std::cout << "Processing element: " << element + 1;
01671 std::cout << "/" << number_of_elements << '\n';
01672 }
01673
01674 IDList const &
01675 node_list = (*elements_iter).second;
01676
01677 std::vector< Vector<double> >
01678 element_nodes;
01679
01680 for (IDList::size_type i = 0;
01681 i < nodes_per_element;
01682 ++i) {
01683
01684 PointMap::const_iterator
01685 nodes_iter = nodes_.find(node_list[i]);
01686
01687 assert(nodes_iter != nodes_.end());
01688
01689 element_nodes.push_back((*nodes_iter).second);
01690
01691 }
01692
01693 Vector<double>
01694 min;
01695
01696 Vector<double>
01697 max;
01698
01699 boost::tie(min, max) =
01700 Intrepid::bounding_box<double>(element_nodes.begin(),
01701 element_nodes.end());
01702
01703 Vector<double> const
01704 element_span = max - min;
01705
01706 Vector<Index>
01707 divisions(dimension);
01708
01709
01710
01711 for (Index i = 0; i < dimension; ++i) {
01712 divisions(i) =
01713 cell_size_(i) > element_span(i) ?
01714 1 :
01715 2.0 * element_span(i) / cell_size_(i) + 0.5;
01716 }
01717
01718
01719
01720
01721 Intrepid::ELEMENT::Type
01722 element_type = GetType();
01723
01724 Index
01725 parametric_dimension = 3;
01726
01727 double
01728 parametric_size = 1.0;
01729
01730 double
01731 lower_limit = 0.0;
01732
01733 boost::tie(parametric_dimension, parametric_size, lower_limit) =
01734 parametric_limits(element_type);
01735
01736 Vector<double>
01737 origin(parametric_dimension);
01738
01739 for (Index i = 0; i < dimension; ++i) {
01740 origin(i) = lower_limit;
01741 }
01742
01743 Vector<double>
01744 xi(parametric_dimension);
01745
01746 for (Index i = 0; i <= divisions(0); ++i) {
01747 xi(0) = origin(0) + double(i) / divisions(0) * parametric_size;
01748 for (Index j = 0; j <= divisions(1); ++j) {
01749 xi(1) = origin(1) + double(j) / divisions(1) * parametric_size;
01750 for (Index k = 0; k <= divisions(2); ++k) {
01751 xi(2) = origin(2) + double(k) / divisions(2) * parametric_size;
01752 Vector<double>
01753 p = interpolate_element(element_type, xi, element_nodes);
01754 for (Index l = 0; l < dimension; ++l) {
01755 p(l) = std::max(p(l), lower_corner(l));
01756 p(l) = std::min(p(l), upper_corner(l));
01757 }
01758
01759 Vector<int>
01760 index = PointToIndex(p);
01761
01762 for (Index l = 0; l < dimension; ++l) {
01763 assert(index(l) >= 0);
01764 assert(index(l) <= int(cells_per_dimension(l)));
01765
01766 if (index(l) == int(cells_per_dimension(l))) {
01767 --index(l);
01768 }
01769 }
01770
01771 cells_[index(0)][index(1)][index(2)] = true;
01772 }
01773 }
01774 }
01775 }
01776
01777 std::cout << connectivity_.size() << " elements processed." << '\n';
01778
01779
01780 std::vector< Vector<double> >
01781 domain_points;
01782
01783 std::ofstream ofs("cells.csv");
01784 ofs << "X, Y, Z, I" << '\n';
01785 Vector<double> p(dimension);
01786
01787 for (Index i = 0; i < cells_per_dimension(0); ++i) {
01788 p(0) = (i + 0.5) * bounding_box_span(0) / cells_per_dimension(0) +
01789 lower_corner(0);
01790 for (Index j = 0; j < cells_per_dimension(1); ++j) {
01791 p(1) = (j + 0.5) * bounding_box_span(1) / cells_per_dimension(1) +
01792 lower_corner(1);
01793 for (Index k = 0; k < cells_per_dimension(2); ++k) {
01794 p(2) = (k + 0.5) * bounding_box_span(2) / cells_per_dimension(2) +
01795 lower_corner(2);
01796
01797 if (cells_[i][j][k] == true) {
01798 domain_points.push_back(p);
01799 }
01800
01801 ofs << p << "," << cells_[i][j][k] << '\n';
01802 }
01803 }
01804 }
01805
01806 Index const
01807 number_generated_points =
01808 cells_per_dimension(0) *
01809 cells_per_dimension(1) *
01810 cells_per_dimension(2);
01811
01812 Index const
01813 number_points_in_domain = domain_points.size();
01814
01815 double const
01816 ratio = double(number_points_in_domain) / double(number_generated_points);
01817
01818 std::cout << "Number of cells inside domain: ";
01819 std::cout << number_points_in_domain;
01820 std::cout << '\n';
01821 std::cout << "Number of generated cells : ";
01822 std::cout << number_generated_points;
01823 std::cout << '\n';
01824 std::cout << "Ratio : ";
01825 std::cout << ratio;
01826 std::cout << '\n';
01827
01828 return domain_points;
01829 }
01830
01831
01832
01833
01834 Vector<int>
01835 ConnectivityArray::PointToIndex(Vector<double> const & point) const
01836 {
01837 int const
01838 i = (point(0) - lower_corner_(0)) / cell_size_(0);
01839
01840 int const
01841 j = (point(1) - lower_corner_(1)) / cell_size_(1);
01842
01843 int const
01844 k = (point(2) - lower_corner_(2)) / cell_size_(2);
01845
01846 return Vector<int>(i, j, k);
01847 }
01848
01849
01850
01851
01852
01853 bool
01854 ConnectivityArray::IsInsideMesh(Vector<double> const & point) const
01855 {
01856 int
01857 i = (point(0) - lower_corner_(0)) / cell_size_(0);
01858
01859 int
01860 j = (point(1) - lower_corner_(1)) / cell_size_(1);
01861
01862 int
01863 k = (point(2) - lower_corner_(2)) / cell_size_(2);
01864
01865
01866 int const
01867 x_size = cells_.size();
01868
01869 int const
01870 y_size = cells_[0].size();
01871
01872 int const
01873 z_size = cells_[0][0].size();
01874
01875
01876 if (i < 0 || i > x_size) {
01877 return false;
01878 }
01879
01880 if (j < 0 || j > y_size) {
01881 return false;
01882 }
01883
01884 if (k < 0 || k > z_size) {
01885 return false;
01886 }
01887
01888
01889 if (i == x_size) --i;
01890 if (j == y_size) --j;
01891 if (k == z_size) --k;
01892
01893 return cells_[i][j][k];
01894 }
01895
01896
01897
01898
01899
01900
01901
01902 bool
01903 ConnectivityArray::IsInsideMeshByElement(Vector<double> const & point) const
01904 {
01905
01906
01907 if (in_box(point, lower_corner_, upper_corner_) == false) {
01908 return false;
01909 }
01910
01911
01912 for (AdjacencyMap::const_iterator
01913 elements_iter = connectivity_.begin();
01914 elements_iter != connectivity_.end();
01915 ++elements_iter) {
01916
01917 IDList const &
01918 node_list = (*elements_iter).second;
01919
01920 std::vector< Vector<double> >
01921 node;
01922
01923 for (IDList::size_type
01924 i = 0;
01925 i < node_list.size();
01926 ++i) {
01927
01928 PointMap::const_iterator
01929 nodes_iter = nodes_.find(node_list[i]);
01930
01931 assert(nodes_iter != nodes_.end());
01932 node.push_back((*nodes_iter).second);
01933
01934 }
01935
01936 switch (type_) {
01937
01938 case Intrepid::ELEMENT::TETRAHEDRAL:
01939 if (in_tetrahedron(point, node[0], node[1], node[2], node[3]) == true) {
01940 return true;
01941 }
01942 break;
01943
01944 case Intrepid::ELEMENT::HEXAHEDRAL:
01945 if (in_hexahedron(point, node[0], node[1], node[2], node[3],
01946 node[4], node[5], node[6], node[7])) {
01947 return true;
01948 }
01949 break;
01950
01951 default:
01952 std::cerr << "Unknown element type in K-means partition." << '\n';
01953 exit(1);
01954 break;
01955
01956 }
01957
01958 }
01959
01960 return false;
01961 }
01962
01963
01964
01965
01966
01967
01968
01969 Index
01970 ConnectivityArray::GetNumberPartitions(double const length_scale) const
01971 {
01972 double const
01973 ball_volume = length_scale * length_scale * length_scale;
01974
01975 Index const
01976 number_partitions =
01977 static_cast<Index>(round(GetVolume() / ball_volume));
01978
01979 return number_partitions;
01980 }
01981
01982
01983
01984
01985 namespace {
01986
01987
01988
01989
01990
01991 std::vector<int>
01992 shuffled_sequence(int number_elements)
01993 {
01994 std::vector<int>
01995 shuffled;
01996
01997 std::vector<int>
01998 unshuffled;
01999
02000 for (int i = 0; i < number_elements; ++i) {
02001 unshuffled.push_back(i);
02002 }
02003
02004
02005 const int
02006 prime = std::numeric_limits<int>::max();
02007
02008 for (int i = 0; i < number_elements; ++i) {
02009 const int
02010 remainder = number_elements - i;
02011
02012 const int
02013 index = prime % remainder;
02014
02015 const int
02016 selection = unshuffled[index];
02017
02018 shuffled.push_back(selection);
02019
02020 std::vector<int>::iterator
02021 delete_position = unshuffled.begin();
02022
02023 std::advance(delete_position, index);
02024
02025 unshuffled.erase(delete_position);
02026 }
02027
02028 return shuffled;
02029 }
02030
02031
02032
02033
02034
02035
02036
02037
02038 std::map<int, int>
02039 RenumberPartitions(std::map<int, int> const & old_partitions) {
02040
02041 std::set<int>
02042 partitions_set;
02043
02044 for (std::map<int, int>::const_iterator it = old_partitions.begin();
02045 it != old_partitions.end();
02046 ++it) {
02047
02048 int const
02049 partition = (*it).second;
02050
02051 partitions_set.insert(partition);
02052 }
02053
02054 std::set<int>::size_type
02055 number_partitions = partitions_set.size();
02056
02057 std::vector<int>
02058 partition_shuffle = shuffled_sequence(number_partitions);
02059
02060 std::map<int, int>
02061 partition_map;
02062
02063 int
02064 partition_index = 0;
02065
02066 for (std::set<int>::const_iterator it = partitions_set.begin();
02067 it != partitions_set.end();
02068 ++it) {
02069
02070 int const
02071 partition = (*it);
02072
02073 partition_map[partition] = partition_index;
02074
02075 ++partition_index;
02076
02077 }
02078
02079 std::map<int, int>
02080 new_partitions;
02081
02082 for (std::map<int, int>::const_iterator it = old_partitions.begin();
02083 it != old_partitions.end();
02084 ++it) {
02085
02086 int const
02087 element = (*it).first;
02088
02089 int const
02090 old_partition = (*it).second;
02091
02092 int const
02093 partition_index = partition_map[old_partition];
02094
02095 int const
02096 new_partition = partition_shuffle[partition_index];
02097
02098 new_partitions[element] = new_partition;
02099
02100 }
02101
02102 return new_partitions;
02103 }
02104
02105 }
02106
02107 void
02108 ConnectivityArray::CheckNullVolume() const
02109 {
02110 ScalarMap const
02111 partition_volumes = GetPartitionVolumes();
02112
02113 std::vector<Index>
02114 zero_volume;
02115
02116 for (ScalarMap::const_iterator it = partition_volumes.begin();
02117 it != partition_volumes.end();
02118 ++it) {
02119
02120 Index const
02121 partition = (*it).first;
02122
02123 double const
02124 volume = (*it).second;
02125
02126 if (volume == 0.0) {
02127 zero_volume.push_back(partition);
02128 }
02129
02130 }
02131
02132 Index const
02133 number_null_partitions = zero_volume.size();
02134
02135 if (number_null_partitions > 0) {
02136 std::cerr << "ERROR: The following partitions have zero volume.";
02137 std::cerr << '\n';
02138 std::cerr << "Length scale may be too small:";
02139 std::cerr << '\n';
02140
02141 for (Index i = 0; i < number_null_partitions; ++i) {
02142 std::cerr << " " << zero_volume[i];
02143 }
02144
02145 std::cerr << '\n';
02146
02147 exit(1);
02148 }
02149
02150 return;
02151 }
02152
02153
02154
02155
02156
02157
02158
02159
02160 std::map<int, int>
02161 ConnectivityArray::Partition(
02162 const PARTITION::Scheme partition_scheme,
02163 double const length_scale)
02164 {
02165
02166 std::map<int, int>
02167 partitions;
02168
02169 switch (partition_scheme) {
02170
02171 case PARTITION::RANDOM:
02172 partitions = PartitionRandom(length_scale);
02173 break;
02174
02175 case PARTITION::HYPERGRAPH:
02176 partitions = PartitionHyperGraph(length_scale);
02177 break;
02178
02179 case PARTITION::GEOMETRIC:
02180 partitions = PartitionGeometric(length_scale);
02181 break;
02182
02183 case PARTITION::KMEANS:
02184 partitions = PartitionKMeans(length_scale);
02185 break;
02186
02187 case PARTITION::SEQUENTIAL:
02188 partitions = PartitionSequential(length_scale);
02189 break;
02190
02191 case PARTITION::KDTREE:
02192 partitions = PartitionKDTree(length_scale);
02193 break;
02194
02195 default:
02196 std::cerr << "Unknown partitioning scheme." << '\n';
02197 exit(1);
02198 break;
02199
02200 }
02201
02202 CheckNullVolume();
02203
02204
02205 partitions_ = RenumberPartitions(partitions);
02206
02207 return partitions_;
02208
02209 }
02210
02211
02212
02213
02214
02215
02216 std::map<int, int>
02217 ConnectivityArray::PartitionByCenters(
02218 std::vector< Vector<double> > const & centers)
02219 {
02220 Index const
02221 number_partitions = centers.size();
02222
02223
02224 std::map<int, int>
02225 partitions;
02226
02227
02228 std::set<Index>
02229 unassigned_partitions;
02230
02231 for (Index partition = 0; partition < number_partitions; ++partition) {
02232 unassigned_partitions.insert(partition);
02233 }
02234
02235
02236 Index const
02237 nodes_per_element = GetNodesPerElement();
02238
02239 std::ofstream centroids_ofs("centroids.csv");
02240
02241 centroids_ofs << "X,Y,Z" << '\n';
02242 for (AdjacencyMap::const_iterator
02243 elements_iter = connectivity_.begin();
02244 elements_iter != connectivity_.end();
02245 ++elements_iter) {
02246
02247 int const &
02248 element = (*elements_iter).first;
02249
02250 IDList const &
02251 node_list = (*elements_iter).second;
02252
02253 std::vector< Vector<double> >
02254 element_nodes;
02255
02256 for (IDList::size_type i = 0; i < nodes_per_element; ++i) {
02257
02258 PointMap::const_iterator
02259 nodes_iter = nodes_.find(node_list[i]);
02260
02261 assert(nodes_iter != nodes_.end());
02262
02263 element_nodes.push_back((*nodes_iter).second);
02264
02265 }
02266
02267 Vector<double> const
02268 element_centroid = centroid(element_nodes);
02269
02270 centroids_ofs << element_centroid << '\n';
02271
02272 Index const
02273 partition = closest_point(element_centroid, centers);
02274
02275 partitions[element] = partition;
02276
02277 std::set<Index>::const_iterator
02278 it = unassigned_partitions.find(partition);
02279
02280 if (it != unassigned_partitions.end()) {
02281 unassigned_partitions.erase(it);
02282 }
02283
02284 }
02285
02286 if (unassigned_partitions.size() > 0) {
02287 std::cout << "WARNING: The following partitions were not" << '\n';
02288 std::cout << "assigned any elements (mesh too coarse?):" << '\n';
02289
02290 for (std::set<Index>::const_iterator it = unassigned_partitions.begin();
02291 it != unassigned_partitions.end();
02292 ++it) {
02293 std::cout << (*it) << '\n';
02294 }
02295
02296 }
02297
02298 std::ofstream generators_ofs("centers.csv");
02299 generators_ofs << "X,Y,Z" << '\n';
02300 for (Index i = 0; i < centers.size(); ++i) {
02301 generators_ofs << centers[i] << '\n';
02302 }
02303
02304 return partitions;
02305
02306 }
02307
02308
02309
02310
02311
02312
02313
02314 std::map<int, int>
02315 ConnectivityArray::PartitionHyperGraph(double const length_scale)
02316 {
02317
02318 int const
02319 number_partitions = GetNumberPartitions(length_scale);
02320
02321 std::stringstream
02322 ioss;
02323
02324 ioss << number_partitions;
02325
02326 std::string
02327 zoltan_number_parts;
02328
02329 ioss >> zoltan_number_parts;
02330
02331 Zoltan
02332 zoltan(MPI_COMM_SELF);
02333
02334 zoltan.Set_Param("LB_METHOD", "HYPERGRAPH");
02335 zoltan.Set_Param("LB_APPROACH", "PARTITION");
02336 zoltan.Set_Param("DEBUG_LEVEL", "0");
02337 zoltan.Set_Param("OBJ_WEIGHT_DIM", "1");
02338 zoltan.Set_Param("NUM_GLOBAL_PARTS", zoltan_number_parts.c_str());
02339 zoltan.Set_Param("REMAP", "0");
02340 zoltan.Set_Param("HYPERGRAPH_PACKAGE", "PHG");
02341 zoltan.Set_Param("PHG_MULTILEVEL", "1");
02342 zoltan.Set_Param("PHG_EDGE_WEIGHT_OPERATION", "ERROR");
02343 zoltan.Set_Param("IMBALANCE_TOL", "1.01");
02344 zoltan.Set_Param("PHG_CUT_OBJECTIVE", "HYPEREDGES");
02345
02346
02347
02348
02349 DualGraph
02350 dual_graph(*this);
02351
02352 ZoltanHyperGraph
02353 zoltan_hypergraph(dual_graph);
02354
02355
02356 zoltan.Set_Num_Obj_Fn(
02357 LCM::ZoltanHyperGraph::GetNumberOfObjects,
02358 &zoltan_hypergraph);
02359
02360 zoltan.Set_Obj_List_Fn(
02361 LCM::ZoltanHyperGraph::GetObjectList,
02362 &zoltan_hypergraph);
02363
02364 zoltan.Set_HG_Size_CS_Fn(
02365 LCM::ZoltanHyperGraph::GetHyperGraphSize,
02366 &zoltan_hypergraph);
02367
02368 zoltan.Set_HG_CS_Fn(
02369 LCM::ZoltanHyperGraph::GetHyperGraph,
02370 &zoltan_hypergraph);
02371
02372 int changes;
02373 int num_gid_entries;
02374 int num_lid_entries;
02375 int num_import;
02376 ZOLTAN_ID_PTR import_global_ids;
02377 ZOLTAN_ID_PTR import_local_ids;
02378 int* import_procs;
02379 int* import_to_part;
02380 int num_export;
02381 ZOLTAN_ID_PTR export_global_ids;
02382 ZOLTAN_ID_PTR export_local_ids;
02383 int* export_procs;
02384 int* export_to_part;
02385
02386 int rc =
02387 zoltan.LB_Partition(
02388 changes,
02389 num_gid_entries,
02390 num_lid_entries,
02391 num_import,
02392 import_global_ids,
02393 import_local_ids,
02394 import_procs,
02395 import_to_part,
02396 num_export,
02397 export_global_ids,
02398 export_local_ids,
02399 export_procs,
02400 export_to_part);
02401
02402 if (rc != ZOLTAN_OK) {
02403 std::cerr << "Partitioning failed" << '\n';
02404 exit(1);
02405 }
02406
02407
02408 std::map<int, int> partitions;
02409
02410
02411 const ScalarMap
02412 vertex_weights = zoltan_hypergraph.GetVertexWeights();
02413
02414
02415
02416 for (ScalarMap::const_iterator
02417 weights_iter = vertex_weights.begin();
02418 weights_iter != vertex_weights.end();
02419 ++weights_iter) {
02420 int const vertex = (*weights_iter).first;
02421 partitions[vertex] = 0;
02422 }
02423
02424
02425 for (int i = 0; i < num_import; ++i) {
02426 int const vertex = static_cast<int>(import_local_ids[i]);
02427 partitions[vertex] = import_to_part[i];
02428 }
02429
02430
02431
02432
02433 zoltan.LB_Free_Part(
02434 &import_global_ids,
02435 &import_local_ids,
02436 &import_procs,
02437 &import_to_part );
02438
02439 zoltan.LB_Free_Part(
02440 &export_global_ids,
02441 &export_local_ids,
02442 &export_procs,
02443 &export_to_part );
02444
02445 return partitions;
02446
02447 }
02448
02449
02451
02452
02453
02454
02455 std::map<int, int>
02456 ConnectivityArray::PartitionGeometric(double const length_scale)
02457 {
02458
02459 int const
02460 number_partitions = GetNumberPartitions(length_scale);
02461
02462 std::stringstream
02463 ioss;
02464
02465 ioss << number_partitions;
02466
02467 std::string
02468 zoltan_number_parts;
02469
02470 ioss >> zoltan_number_parts;
02471
02472 Zoltan
02473 zoltan(MPI_COMM_SELF);
02474
02475 zoltan.Set_Param("LB_METHOD", "RCB");
02476 zoltan.Set_Param("RCB_RECOMPUTE_BOX", "1");
02477 zoltan.Set_Param("LB_APPROACH", "PARTITION");
02478 zoltan.Set_Param("DEBUG_LEVEL", "0");
02479 zoltan.Set_Param("OBJ_WEIGHT_DIM", "1");
02480 zoltan.Set_Param("NUM_GLOBAL_PARTS", zoltan_number_parts.c_str());
02481 zoltan.Set_Param("REMAP", "0");
02482 zoltan.Set_Param("IMBALANCE_TOL", "1.10");
02483 zoltan.Set_Param("CHECK_GEOM", "1");
02484 zoltan.Set_Param("AVERAGE_CUTS", "1");
02485 zoltan.Set_Param("REDUCE_DIMENSIONS", "1");
02486 zoltan.Set_Param("DEGENERATE_RATIO", "10");
02487
02488
02489
02490
02491
02492
02493 zoltan.Set_Num_Obj_Fn(LCM::ConnectivityArray::GetNumberOfObjects, this);
02494 zoltan.Set_Obj_List_Fn(LCM::ConnectivityArray::GetObjectList, this);
02495 zoltan.Set_Num_Geom_Fn(LCM::ConnectivityArray::GetNumberGeometry, this);
02496 zoltan.Set_Geom_Multi_Fn(LCM::ConnectivityArray::GetGeometry, this);
02497
02498 int changes;
02499 int num_gid_entries;
02500 int num_lid_entries;
02501 int num_import;
02502 ZOLTAN_ID_PTR import_global_ids;
02503 ZOLTAN_ID_PTR import_local_ids;
02504 int* import_procs;
02505 int* import_to_part;
02506 int num_export;
02507 ZOLTAN_ID_PTR export_global_ids;
02508 ZOLTAN_ID_PTR export_local_ids;
02509 int* export_procs;
02510 int* export_to_part;
02511
02512 int rc =
02513 zoltan.LB_Partition(
02514 changes,
02515 num_gid_entries,
02516 num_lid_entries,
02517 num_import,
02518 import_global_ids,
02519 import_local_ids,
02520 import_procs,
02521 import_to_part,
02522 num_export,
02523 export_global_ids,
02524 export_local_ids,
02525 export_procs,
02526 export_to_part);
02527
02528 if (rc != ZOLTAN_OK) {
02529 std::cerr << "Partitioning failed" << '\n';
02530 exit(1);
02531 }
02532
02533
02534 std::map<int, int> partitions;
02535
02536 const ScalarMap
02537 element_volumes = GetVolumes();
02538
02539
02540 for (ScalarMap::const_iterator
02541 volumes_iter = element_volumes.begin();
02542 volumes_iter != element_volumes.end();
02543 ++volumes_iter) {
02544 int const element = (*volumes_iter).first;
02545 partitions[element] = 0;
02546 }
02547
02548
02549
02550 for (int i = 0; i < num_import; ++i) {
02551 int const element = static_cast<int>(import_local_ids[i]);
02552 partitions[element] = import_to_part[i];
02553 }
02554
02555 return partitions;
02556
02557 }
02558
02559
02561
02562
02563
02564
02565 std::map<int, int>
02566 ConnectivityArray::PartitionKMeans(double const length_scale)
02567 {
02568
02569
02570
02571 std::cout << '\n';
02572 std::cout << "Partition with initializer ..." << '\n';
02573
02574
02575 PARTITION::Scheme const
02576 initializer_scheme = GetInitializerScheme();
02577
02578 Partition(initializer_scheme, length_scale);
02579
02580
02581
02582 std::vector< Vector<double> >
02583 centers = GetPartitionCentroids();
02584
02585 Index const
02586 number_partitions = centers.size();
02587
02588 Vector<double>
02589 lower_corner;
02590
02591 Vector<double>
02592 upper_corner;
02593
02594 boost::tie(lower_corner, upper_corner) = BoundingBox();
02595
02596 lower_corner_ = lower_corner;
02597 upper_corner_ = upper_corner;
02598
02599 std::vector< Vector<double> >
02600 domain_points = CreateGrid();
02601
02602
02603
02604
02605 std::cout << "Main K-means Iteration." << '\n';
02606
02607 Index const
02608 max_iterations = GetMaximumIterations();
02609
02610 Index
02611 number_iterations = 0;
02612
02613 double const
02614 diagonal_distance = norm(upper_corner - lower_corner);
02615
02616 double const
02617 tolerance = GetTolerance() * diagonal_distance;
02618
02619 double
02620 step_norm = diagonal_distance;
02621
02622 std::vector<double>
02623 steps(number_partitions);
02624
02625 for (Index i = 0; i < number_partitions; ++i) {
02626 steps[i] = diagonal_distance;
02627 }
02628
02629 Index const
02630 number_points = domain_points.size();
02631
02632 while (step_norm >= tolerance && number_iterations < max_iterations) {
02633
02634
02635 std::vector<double>
02636 point_to_generator(number_points);
02637
02638 for (Index i = 0; i < domain_points.size(); ++i) {
02639 point_to_generator[i] = closest_point(domain_points[i], centers);
02640 }
02641
02642
02643 std::vector<std::vector<Vector<double> > >
02644 clusters;
02645
02646 clusters.resize(number_partitions);
02647
02648 for (Index p = 0; p < point_to_generator.size(); ++p) {
02649
02650 Index const
02651 c = point_to_generator[p];
02652
02653 clusters[c].push_back(domain_points[p]);
02654
02655 }
02656
02657
02658
02659 for (Index i = 0; i < clusters.size(); ++i) {
02660
02661
02662 if (clusters[i].size() == 0) {
02663 steps[i] = 0.0;
02664 std::cout << "Iteration: " << number_iterations;
02665 std::cout << ", center " << i << " has zero points." << '\n';
02666 continue;
02667 }
02668
02669 Vector<double> const
02670 cluster_centroid = centroid(clusters[i]);
02671
02672
02673 Vector<double> const
02674 old_generator = centers[i];
02675
02676 centers[i] = cluster_centroid;
02677
02678 steps[i] = norm(centers[i] - old_generator);
02679 }
02680
02681 step_norm = norm(Vector<double>(number_partitions, &steps[0]));
02682
02683 std::cout << "Iteration: " << number_iterations;
02684 std::cout << ". Step: " << step_norm << ". Tol: " << tolerance;
02685 std::cout << '\n';
02686
02687 ++number_iterations;
02688
02689 }
02690
02691
02692 std::map<int, int>
02693 partitions = PartitionByCenters(centers);
02694
02695 return partitions;
02696 }
02697
02698
02700
02701
02702
02703
02704 std::map<int, int>
02705 ConnectivityArray::PartitionKDTree(double const length_scale)
02706 {
02707
02708
02709
02710 std::cout << '\n';
02711 std::cout << "Partition with initializer ..." << '\n';
02712
02713
02714 PARTITION::Scheme const
02715 initializer_scheme = GetInitializerScheme();
02716
02717 Partition(initializer_scheme, length_scale);
02718
02719
02720
02721 std::vector< Vector<double> >
02722 center_positions = GetPartitionCentroids();
02723
02724 Index const
02725 number_partitions = center_positions.size();
02726
02727
02728 std::cout << "Main K-means Iteration." << '\n';
02729
02730 std::vector<ClusterCenter>
02731 centers(number_partitions);
02732
02733 for (Index i = 0; i < number_partitions; ++i) {
02734 centers[i].position = center_positions[i];
02735 centers[i].weighted_centroid = 0.0 * center_positions[i];
02736 }
02737
02738 Vector<double>
02739 lower_corner;
02740
02741 Vector<double>
02742 upper_corner;
02743
02744 boost::tie(lower_corner, upper_corner) = BoundingBox();
02745
02746 lower_corner_ = lower_corner;
02747 upper_corner_ = upper_corner;
02748
02749 std::vector< Vector<double> >
02750 domain_points = CreateGrid();
02751
02752
02753
02754
02755 KDTree<KDTreeNode>
02756 kdtree(domain_points, number_partitions);
02757
02758
02759
02760 FilterVisitor<boost::shared_ptr<KDTreeNode>, ClusterCenter>
02761 filter_visitor(domain_points, centers);
02762
02763
02764
02765
02766 Index const
02767 max_iterations = GetMaximumIterations();
02768
02769 Index
02770 number_iterations = 0;
02771
02772 double const
02773 diagonal_distance = norm(upper_corner - lower_corner);
02774
02775 double const
02776 tolerance = GetTolerance() * GetCellSize();
02777
02778 double
02779 step_norm = diagonal_distance;
02780
02781 std::vector<double>
02782 steps(number_partitions);
02783
02784 for (Index i = 0; i < number_partitions; ++i) {
02785 steps[i] = diagonal_distance;
02786 }
02787
02788 while (step_norm >= tolerance && number_iterations < max_iterations) {
02789
02790
02791 for (Index i = 0; i < number_partitions; ++i) {
02792 ClusterCenter &
02793 center = centers[i];
02794
02795 center.weighted_centroid.clear();
02796 center.count = 0;
02797 }
02798
02799 TraverseTree(kdtree, filter_visitor);
02800
02801
02802 for (Index i = 0; i < centers.size(); ++i) {
02803
02804 ClusterCenter &
02805 center = centers[i];
02806
02807
02808 if (center.count == 0) {
02809 steps[i] = 0.0;
02810 std::cout << "Iteration: " << number_iterations;
02811 std::cout << ", center " << i << " has zero points." << '\n';
02812 continue;
02813 }
02814
02815 Vector<double> const
02816 new_position = center.weighted_centroid / center.count;
02817
02818 steps[i] = norm(new_position - center.position);
02819
02820 center.position = new_position;
02821
02822 }
02823
02824 step_norm = norm(Vector<double>(number_partitions, &steps[0]));
02825
02826 std::cout << "Iteration: " << number_iterations;
02827 std::cout << ". Step: " << step_norm << ". Tol: " << tolerance;
02828 std::cout << '\n';
02829
02830 ++number_iterations;
02831
02832 }
02833
02834 for (Index i = 0; i < number_partitions; i++) {
02835 center_positions[i] = centers[i].position;
02836 }
02837
02838
02839 std::map<int, int>
02840 partitions = PartitionByCenters(center_positions);
02841
02842 return partitions;
02843
02844 }
02845
02846
02847
02848
02849
02850
02851
02852 std::map<int, int>
02853 ConnectivityArray::PartitionSequential(double const length_scale)
02854 {
02855 int const
02856 number_partitions = GetNumberPartitions(length_scale);
02857
02858 Vector<double>
02859 lower_corner;
02860
02861 Vector<double>
02862 upper_corner;
02863
02864 boost::tie(lower_corner, upper_corner) = BoundingBox();
02865
02866 lower_corner_ = lower_corner;
02867 upper_corner_ = upper_corner;
02868
02869
02870
02871
02872
02873
02874 const PARTITION::Scheme
02875 initializer_scheme = GetInitializerScheme();
02876
02877 Partition(initializer_scheme, length_scale);
02878
02879
02880
02881 std::vector< Vector<double> >
02882 centers = GetPartitionCentroids();
02883
02884 std::vector<Index>
02885 weights(number_partitions);
02886
02887 for (int i = 0; i < number_partitions; ++i) {
02888 weights[i] = 1;
02889 }
02890
02891
02892 Index const
02893 number_random_points = GetMaximumIterations() * number_partitions;
02894
02895 Index const
02896 max_iterations = number_random_points;
02897
02898 Index
02899 number_iterations = 0;
02900
02901 double const
02902 diagonal_distance = norm(upper_corner - lower_corner);
02903
02904 double const
02905 tolerance = GetTolerance() * diagonal_distance;
02906
02907 std::vector<double>
02908 steps(number_partitions);
02909
02910 for (int i = 0; i < number_partitions; ++i) {
02911 steps[i] = diagonal_distance;
02912 }
02913
02914 double
02915 step_norm = diagonal_distance;
02916
02917 std::cout << "K-means Sequential." << '\n';
02918
02919 while (step_norm >= tolerance && number_iterations < max_iterations) {
02920
02921
02922 bool
02923 is_point_in_domain = false;
02924
02925 Vector<double>
02926 random_point(lower_corner.get_dimension());
02927
02928 while (is_point_in_domain == false) {
02929 random_point = random_in_box(lower_corner, upper_corner);
02930 is_point_in_domain = IsInsideMesh(random_point);
02931 }
02932
02933
02934 Index const
02935 i = closest_point(random_point, centers);
02936
02937
02938 Vector<double> const
02939 old_generator = centers[i];
02940
02941 centers[i] =
02942 (weights[i] * centers[i] + random_point) / (weights[i] + 1);
02943
02944 weights[i] += 1;
02945
02946 steps[i] = norm(centers[i] - old_generator);
02947 step_norm = norm(Vector<double>(number_partitions, &steps[0]));
02948
02949 if (number_iterations % 10000 == 0) {
02950 std::cout << "Random point: " << number_iterations;
02951 std::cout << ". Step: " << step_norm << ". ";
02952 std::cout << "Tol: " << tolerance << '\n';
02953 }
02954
02955 ++number_iterations;
02956
02957 }
02958
02959 std::cout << "Random point: " << number_iterations;
02960 std::cout << ". Step: " << step_norm << ". ";
02961 std::cout << "Tol: " << tolerance << '\n';
02962
02963
02964 std::map<int, int>
02965 partitions = PartitionByCenters(centers);
02966
02967 return partitions;
02968 }
02969
02970
02971
02972
02973
02974
02975
02976
02977 std::map<int, int>
02978 ConnectivityArray::PartitionRandom(double const length_scale)
02979 {
02980 int const
02981 number_partitions = GetNumberPartitions(length_scale);
02982
02983 Vector<double>
02984 lower_corner;
02985
02986 Vector<double>
02987 upper_corner;
02988
02989 boost::tie(lower_corner, upper_corner) = BoundingBox();
02990
02991 lower_corner_ = lower_corner;
02992 upper_corner_ = upper_corner;
02993
02994
02995
02996
02997 int
02998 number_generators = 0;
02999
03000 std::vector< Vector<double> >
03001 centers;
03002
03003 while (number_generators < number_partitions) {
03004
03005 Vector<double>
03006 p = random_in_box(lower_corner, upper_corner);
03007
03008 if (IsInsideMesh(p) == true) {
03009 centers.push_back(p);
03010 ++number_generators;
03011 }
03012
03013 }
03014
03015
03016 std::map<int, int>
03017 partitions = PartitionByCenters(centers);
03018
03019 return partitions;
03020 }
03021
03022
03023
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034 int
03035 ConnectivityArray::GetNumberGeometry(
03036 void* data,
03037 int* ierr)
03038 {
03039
03040 ConnectivityArray &
03041 connectivity_array = *(static_cast<ConnectivityArray*>(data));
03042
03043 *ierr = ZOLTAN_OK;
03044
03045 int dimension = connectivity_array.GetDimension();
03046
03047 return dimension;
03048 }
03049
03050
03051
03052
03053 int
03054 ConnectivityArray::GetNumberOfObjects(void* data, int* ierr)
03055 {
03056
03057 ConnectivityArray &
03058 connectivity_array = *(static_cast<ConnectivityArray*>(data));
03059
03060 *ierr = ZOLTAN_OK;
03061
03062 int num_objects = connectivity_array.GetConnectivity().size();
03063
03064 return num_objects;
03065 }
03066
03067
03068
03069
03070 void
03071 ConnectivityArray::GetObjectList(
03072 void* data,
03073 int sizeGID,
03074 int sizeLID,
03075 ZOLTAN_ID_PTR globalID,
03076 ZOLTAN_ID_PTR localID,
03077 int wgt_dim,
03078 float* obj_wgts,
03079 int* ierr)
03080 {
03081
03082 ConnectivityArray &
03083 connectivity_array = *(static_cast<ConnectivityArray*>(data));
03084
03085 *ierr = ZOLTAN_OK;
03086
03087 ScalarMap
03088 element_volumes = connectivity_array.GetVolumes();
03089
03090 ZOLTAN_ID_PTR
03091 global_id_ptr = globalID;
03092
03093 ZOLTAN_ID_PTR
03094 local_id_ptr = localID;
03095
03096 float*
03097 weight_ptr = obj_wgts;
03098
03099 for (ScalarMap::const_iterator
03100 volumes_iter = element_volumes.begin();
03101 volumes_iter != element_volumes.end();
03102 ++volumes_iter) {
03103
03104 int element = (*volumes_iter).first;
03105 double volume = (*volumes_iter).second;
03106
03107
03108 (*global_id_ptr) = element;
03109 (*local_id_ptr) = element;
03110 (*weight_ptr) = volume;
03111 global_id_ptr++;
03112 local_id_ptr++;
03113 weight_ptr++;
03114
03115 }
03116
03117 return;
03118 }
03119
03120
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130
03131
03132
03133
03134
03135
03136
03137
03138
03139
03140
03141
03142
03143
03144
03145
03146
03147
03148
03149
03150
03151
03152
03153
03154
03155
03156
03157
03158 void
03159 ConnectivityArray::GetGeometry(
03160 void* data,
03161 int sizeGID,
03162 int sizeLID,
03163 int num_obj,
03164 ZOLTAN_ID_PTR globalID,
03165 ZOLTAN_ID_PTR localID,
03166 int num_dim,
03167 double* geom_vec,
03168 int* ierr)
03169 {
03170
03171 ConnectivityArray &
03172 connectivity_array = *(static_cast<ConnectivityArray*>(data));
03173
03174 *ierr = ZOLTAN_OK;
03175
03176 PointMap
03177 centroids = connectivity_array.GetCentroids();
03178
03179
03180 int
03181 index_geom_vec = 0;
03182
03183 for (PointMap::const_iterator
03184 centroids_iter = centroids.begin();
03185 centroids_iter != centroids.end();
03186 ++centroids_iter) {
03187
03188 Vector<double> const
03189 centroid = (*centroids_iter).second;
03190
03191 for (Index i = 0; i < 3; ++i) {
03192
03193 geom_vec[index_geom_vec] = centroid(i);
03194 ++index_geom_vec;
03195
03196 }
03197
03198 }
03199
03200 return;
03201 }
03202
03203
03204
03205
03206 std::ostream &
03207 operator<<(
03208 std::ostream & output_stream,
03209 ConnectivityArray const & connectivity_array)
03210 {
03211 output_stream << std::setw(12) << connectivity_array.GetNumberNodes();
03212 output_stream << std::setw(12) << connectivity_array.GetNumberElements();
03213 output_stream << std::setw(12) << connectivity_array.GetType();
03214 output_stream << '\n';
03215
03216
03217 const PointMap
03218 nodes = connectivity_array.GetNodeList();
03219
03220 int const
03221 dimension = connectivity_array.GetDimension();
03222
03223 for (PointMap::const_iterator
03224 nodes_iter = nodes.begin();
03225 nodes_iter != nodes.end();
03226 ++nodes_iter) {
03227
03228 int const
03229 node = (*nodes_iter).first;
03230
03231 output_stream << std::setw(12) << node;
03232
03233 Vector<double> const &
03234 point = (*nodes_iter).second;
03235
03236 for (int j = 0; j < dimension; ++j) {
03237 output_stream << std::scientific;
03238 output_stream << std::setw(16) << std::setprecision(8);
03239 output_stream << point(j);
03240 }
03241
03242 output_stream << '\n';
03243
03244 }
03245
03246
03247 const ScalarMap
03248 volumes = connectivity_array.GetVolumes();
03249
03250
03251 const AdjacencyMap
03252 connectivity = connectivity_array.GetConnectivity();
03253
03254 for (AdjacencyMap::const_iterator
03255 connectivity_iter = connectivity.begin();
03256 connectivity_iter != connectivity.end();
03257 ++connectivity_iter) {
03258
03259 int const element = (*connectivity_iter).first;
03260
03261 output_stream << std::setw(12) << element;
03262
03263 IDList const &
03264 node_list = (*connectivity_iter).second;
03265
03266 for (IDList::size_type j = 0; j < node_list.size(); ++j) {
03267 output_stream << std::setw(12) << node_list[j];
03268 }
03269
03270
03271 ScalarMap::const_iterator
03272 volumes_iter = volumes.find(element);
03273
03274 assert(volumes_iter != volumes.end());
03275
03276 double const
03277 volume = (*volumes_iter).second;
03278
03279 output_stream << std::scientific << std::setw(16) << std::setprecision(8);
03280 output_stream << volume;
03281
03282 output_stream << '\n';
03283 }
03284
03285 return output_stream;
03286 }
03287
03288
03289
03290
03291 DualGraph::DualGraph() : number_edges_(0)
03292 {
03293 return;
03294 }
03295
03296
03297
03298
03299
03300 DualGraph::DualGraph(ConnectivityArray const & connectivity_array)
03301 {
03302
03303 const std::vector< std::vector<int> >
03304 face_connectivity = GetFaceConnectivity(connectivity_array.GetType());
03305
03306 const AdjacencyMap
03307 connectivity = connectivity_array.GetConnectivity();
03308
03309 std::map<std::set<int>, int>
03310 face_nodes_faceID_map;
03311
03312 int
03313 face_count = 0;
03314
03315 graph_.clear();
03316
03317 AdjacencyMap
03318 faceID_element_map;
03319
03320
03321 for (AdjacencyMap::const_iterator
03322 connectivity_iter = connectivity.begin();
03323 connectivity_iter != connectivity.end();
03324 ++connectivity_iter) {
03325
03326 int const
03327 element = (*connectivity_iter).first;
03328
03329 const std::vector<int>
03330 element_nodes = (*connectivity_iter).second;
03331
03332
03333
03334 graph_[element].clear();
03335
03336
03337 for (std::vector< std::vector<int> >::size_type
03338 i = 0;
03339 i < face_connectivity.size();
03340 ++i) {
03341
03342 std::set<int>
03343 face_nodes;
03344
03345 for (std::vector<int>::size_type
03346 j = 0;
03347 j < face_connectivity[i].size();
03348 ++j) {
03349 face_nodes.insert(element_nodes[face_connectivity[i][j]]);
03350 }
03351
03352
03353 std::map<std::set<int>, int>::const_iterator
03354 face_map_iter = face_nodes_faceID_map.find(face_nodes);
03355
03356 const bool
03357 face_is_new = face_map_iter == face_nodes_faceID_map.end();
03358
03359
03360 int
03361 faceID = -1;
03362
03363 if (face_is_new == true) {
03364 faceID = face_count;
03365 face_nodes_faceID_map.insert(std::make_pair(face_nodes, faceID));
03366 ++face_count;
03367 } else {
03368 faceID = (*face_map_iter).second;
03369 }
03370
03371
03372 faceID_element_map[faceID].push_back(element);
03373
03374 }
03375
03376 }
03377
03378
03379 IDList
03380 internal_faces;
03381
03382 for (AdjacencyMap::const_iterator
03383 face_element_iter = faceID_element_map.begin();
03384 face_element_iter != faceID_element_map.end();
03385 ++face_element_iter) {
03386
03387 int const
03388 faceID = (*face_element_iter).first;
03389
03390 int const
03391 number_elements_per_face = ((*face_element_iter).second).size();
03392
03393 switch (number_elements_per_face) {
03394
03395 case 1:
03396
03397 break;
03398
03399 case 2:
03400 internal_faces.push_back(faceID);
03401 break;
03402
03403 default:
03404 std::cerr << "Bad number of faces adjacent to element." << '\n';
03405 exit(1);
03406 break;
03407
03408 }
03409
03410 }
03411
03412
03413 for (IDList::size_type
03414 i = 0;
03415 i < internal_faces.size();
03416 ++i) {
03417
03418 int const
03419 faceID = internal_faces[i];
03420
03421 const IDList
03422 elements_face = faceID_element_map[faceID];
03423
03424 assert(elements_face.size() == 2);
03425
03426 for (IDList::size_type
03427 j = 0;
03428 j < elements_face.size();
03429 ++j) {
03430
03431 int const
03432 element = elements_face[j];
03433
03434 graph_[element].push_back(faceID);
03435
03436 }
03437
03438 }
03439
03440 number_edges_ = internal_faces.size();
03441 vertex_weights_ = connectivity_array.GetVolumes();
03442
03443 return;
03444 }
03445
03446 int
03447 DualGraph::GetNumberVertices() const
03448 {
03449 return graph_.size();
03450 }
03451
03452 int
03453 DualGraph::GetNumberEdges() const
03454 {
03455 return number_edges_;
03456 }
03457
03458 void
03459 DualGraph::SetGraph(AdjacencyMap & graph)
03460 {
03461 graph_ = graph;
03462 return;
03463 }
03464
03465 AdjacencyMap
03466 DualGraph::GetGraph() const
03467 {
03468 return graph_;
03469 }
03470
03471
03472
03473
03474 AdjacencyMap
03475 DualGraph::GetEdgeList() const
03476 {
03477 AdjacencyMap edge_list;
03478
03479 for (AdjacencyMap::const_iterator graph_iter = graph_.begin();
03480 graph_iter != graph_.end();
03481 ++graph_iter) {
03482 int const vertex = (*graph_iter).first;
03483 const IDList edges = (*graph_iter).second;
03484
03485 for (IDList::const_iterator edges_iter = edges.begin();
03486 edges_iter != edges.end();
03487 ++edges_iter) {
03488
03489 int const edge = (*edges_iter);
03490
03491 IDList & vertices = edge_list[edge];
03492
03493 vertices.push_back(vertex);
03494
03495 }
03496
03497 }
03498
03499 return edge_list;
03500 }
03501
03502 void
03503 DualGraph::SetVertexWeights(ScalarMap & vertex_weights)
03504 {
03505 vertex_weights_ = vertex_weights;
03506 return;
03507 }
03508
03509 ScalarMap
03510 DualGraph::GetVertexWeights() const
03511 {
03512 return vertex_weights_;
03513 }
03514
03515
03516
03517
03518 int
03519 DualGraph::GetConnectedComponents(std::vector<int> & components) const
03520 {
03521
03522 typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS>
03523 UndirectedGraph;
03524
03525 typedef boost::graph_traits<UndirectedGraph>::vertex_descriptor Vertex;
03526 typedef boost::graph_traits<UndirectedGraph>::edge_descriptor Edge;
03527
03528 UndirectedGraph graph;
03529
03530
03531 std::map<int, Vertex> dual_2_boost;
03532 AdjacencyMap dual_graph = GetGraph();
03533
03534 for (AdjacencyMap::const_iterator graph_iter = dual_graph.begin();
03535 graph_iter != dual_graph.end();
03536 ++graph_iter) {
03537
03538 Vertex boost_vertex = boost::add_vertex(graph);
03539 int dual_vertex = (*graph_iter).first;
03540
03541 dual_2_boost.insert(std::make_pair(dual_vertex, boost_vertex));
03542
03543 }
03544
03545
03546 AdjacencyMap
03547 edge_list = GetEdgeList();
03548
03549 for (AdjacencyMap::const_iterator edges_iter = edge_list.begin();
03550 edges_iter != edge_list.end();
03551 ++edges_iter) {
03552
03553 const IDList vertices = (*edges_iter).second;
03554
03555 int source_vertex = vertices[0];
03556 int target_vertex = vertices[1];
03557
03558 Vertex source_boost_vertex = dual_2_boost[source_vertex];
03559 Vertex target_boost_vertex = dual_2_boost[target_vertex];
03560
03561 boost::add_edge(source_boost_vertex, target_boost_vertex, graph);
03562
03563 }
03564
03565 int const number_vertices = GetNumberVertices();
03566 components.resize(number_vertices);
03567
03568 int number_components =
03569 boost::connected_components(graph, &components[0]);
03570
03571 return number_components;
03572 }
03573
03574
03575
03576
03577 void
03578 DualGraph::Print() const
03579 {
03580
03581 ScalarMap
03582 vertex_weights = GetVertexWeights();
03583
03584 AdjacencyMap
03585 graph = GetGraph();
03586
03587 int const
03588 number_vertices = GetNumberVertices();
03589
03590 int const
03591 number_edges = GetNumberEdges();
03592
03593 std::cout << '\n';
03594 std::cout << "Vertex - Edge Format:" << '\n';
03595 std::cout << '\n';
03596 std::cout << "============================================================";
03597 std::cout << '\n';
03598 std::cout << "Number of Vertices : " << number_vertices << '\n';
03599 std::cout << "Number of Edges : " << number_edges << '\n';
03600 std::cout << "------------------------------------------------------------";
03601 std::cout << '\n';
03602 std::cout << "Vertex Weight Edges" << '\n';
03603 std::cout << "------------------------------------------------------------";
03604 std::cout << '\n';
03605
03606 for (ScalarMap::const_iterator vw_iter = vertex_weights.begin();
03607 vw_iter != vertex_weights.end();
03608 ++vw_iter) {
03609
03610 int const vertex = (*vw_iter).first;
03611 double const weight = (*vw_iter).second;
03612
03613 std::cout << std::setw(8) << vertex;
03614 std::cout << std::scientific << std::setw(16) << std::setprecision(8);
03615 std::cout << weight;
03616
03617 AdjacencyMap::const_iterator
03618 graph_iter = graph.find(vertex);
03619
03620 if (graph_iter == graph.end()) {
03621 std::cerr << "Cannot find vertex " << vertex << '\n';
03622 exit(1);
03623 }
03624
03625 IDList
03626 edges = graph[vertex];
03627
03628 for (IDList::const_iterator edges_iter = edges.begin();
03629 edges_iter != edges.end();
03630 ++edges_iter) {
03631 int const edge = *edges_iter;
03632 std::cout << std::setw(8) << edge;
03633 }
03634
03635 std::cout << '\n';
03636
03637 }
03638
03639 std::cout << "============================================================";
03640 std::cout << '\n';
03641
03642 std::cout << '\n';
03643 std::cout << "Edge - Vertex Format:" << '\n';
03644 std::cout << '\n';
03645
03646 AdjacencyMap
03647 edge_list = GetEdgeList();
03648
03649 std::cout << "------------------------------------------------------------";
03650 std::cout << '\n';
03651 std::cout << "Edge Vertices" << '\n';
03652 std::cout << "------------------------------------------------------------";
03653 std::cout << '\n';
03654
03655 for (AdjacencyMap::const_iterator edges_iter = edge_list.begin();
03656 edges_iter != edge_list.end();
03657 ++edges_iter) {
03658
03659 int const edge = (*edges_iter).first;
03660 std::cout << std::setw(8) << edge;
03661 const IDList vertices = (*edges_iter).second;
03662
03663 for (IDList::const_iterator vertices_iter = vertices.begin();
03664 vertices_iter != vertices.end();
03665 ++vertices_iter) {
03666 int const vertex = (*vertices_iter);
03667 std::cout << std::setw(8) << vertex;
03668 }
03669
03670 std::cout << '\n';
03671
03672 }
03673
03674 std::cout << "============================================================";
03675 std::cout << '\n';
03676
03677 return;
03678 }
03679
03680
03681
03682
03683 std::vector< std::vector<int> >
03684 DualGraph::GetFaceConnectivity(Intrepid::ELEMENT::Type const type) const
03685 {
03686
03687 std::vector< std::vector<int> >
03688 face_connectivity;
03689
03690
03691
03692 int
03693 number_faces = 0;
03694
03695 int
03696 nodes_per_face = 0;
03697
03698 switch (type) {
03699
03700 case Intrepid::ELEMENT::SEGMENTAL:
03701 number_faces = 2;
03702 nodes_per_face = 1;
03703 break;
03704
03705 case Intrepid::ELEMENT::TRIANGULAR:
03706 number_faces = 3;
03707 nodes_per_face = 2;
03708 break;
03709
03710 case Intrepid::ELEMENT::QUADRILATERAL:
03711 number_faces = 4;
03712 nodes_per_face = 2;
03713 break;
03714
03715 case Intrepid::ELEMENT::TETRAHEDRAL:
03716 number_faces = 4;
03717 nodes_per_face = 3;
03718 break;
03719
03720 case Intrepid::ELEMENT::HEXAHEDRAL:
03721 number_faces = 6;
03722 nodes_per_face = 4;
03723 break;
03724
03725 default:
03726 std::cerr << "Unknown element type in face connectivity." << '\n';
03727 exit(1);
03728 break;
03729
03730 }
03731
03732 face_connectivity.resize(number_faces);
03733 for (int i = 0; i < number_faces; ++i) {
03734 face_connectivity[i].resize(nodes_per_face);
03735 }
03736
03737
03738 std::vector< std::vector<int> > &
03739 f = face_connectivity;
03740
03741 switch (type) {
03742
03743 case Intrepid::ELEMENT::SEGMENTAL:
03744 f[0][0] = 0;
03745 f[1][0] = 1;
03746 break;
03747
03748 case Intrepid::ELEMENT::TRIANGULAR:
03749 f[0][0] = 0; f[0][1] = 1;
03750 f[1][0] = 1; f[1][1] = 2;
03751 f[2][0] = 2; f[2][1] = 0;
03752 break;
03753
03754 case Intrepid::ELEMENT::QUADRILATERAL:
03755 f[0][0] = 0; f[0][1] = 1;
03756 f[1][0] = 1; f[1][1] = 2;
03757 f[2][0] = 2; f[2][1] = 3;
03758 f[3][0] = 3; f[3][1] = 0;
03759 break;
03760
03761 case Intrepid::ELEMENT::TETRAHEDRAL:
03762 f[0][0] = 0; f[0][1] = 1; f[0][2] = 2;
03763 f[1][0] = 0; f[1][1] = 3; f[1][2] = 1;
03764 f[2][0] = 1; f[2][1] = 3; f[2][2] = 2;
03765 f[3][0] = 2; f[3][1] = 3; f[3][2] = 0;
03766 break;
03767
03768 case Intrepid::ELEMENT::HEXAHEDRAL:
03769 f[0][0] = 0; f[0][1] = 1; f[0][2] = 2; f[0][3] = 3;
03770 f[1][0] = 0; f[1][1] = 4; f[1][2] = 5; f[1][3] = 1;
03771 f[2][0] = 1; f[2][1] = 5; f[2][2] = 6; f[2][3] = 2;
03772 f[3][0] = 2; f[3][1] = 6; f[3][2] = 7; f[3][3] = 3;
03773 f[4][0] = 3; f[4][1] = 7; f[4][2] = 4; f[4][3] = 0;
03774 f[5][0] = 4; f[5][1] = 7; f[5][2] = 6; f[5][3] = 5;
03775 break;
03776
03777 default:
03778 std::cerr << "Unknown element type in face connectivity." << '\n';
03779 exit(1);
03780 break;
03781
03782 }
03783
03784 return face_connectivity;
03785 }
03786
03787
03788
03789
03790 ZoltanHyperGraph::ZoltanHyperGraph() :
03791 number_vertices_(0),
03792 number_hyperedges_(0)
03793 {
03794 return;
03795 }
03796
03797
03798
03799
03800 ZoltanHyperGraph::ZoltanHyperGraph(DualGraph const & dual_graph)
03801 {
03802 graph_ = dual_graph.GetGraph();
03803 vertex_weights_ = dual_graph.GetVertexWeights();
03804 number_vertices_ = dual_graph.GetNumberVertices();
03805 number_hyperedges_ = dual_graph.GetNumberEdges();
03806 return;
03807 }
03808
03809 int
03810 ZoltanHyperGraph::GetNumberVertices() const
03811 {
03812 return graph_.size();
03813 }
03814
03815 void
03816 ZoltanHyperGraph::SetNumberHyperedges(int number_hyperedges)
03817 {
03818 number_hyperedges_ = number_hyperedges;
03819 return;
03820 }
03821
03822 int
03823 ZoltanHyperGraph::GetNumberHyperedges() const
03824 {
03825 return number_hyperedges_;
03826 }
03827
03828 void
03829 ZoltanHyperGraph::SetGraph(AdjacencyMap & graph)
03830 {
03831 graph_ = graph;
03832 return;
03833 }
03834
03835 AdjacencyMap
03836 ZoltanHyperGraph::GetGraph() const
03837 {
03838 return graph_;
03839 }
03840
03841 void
03842 ZoltanHyperGraph::SetVertexWeights(ScalarMap & vertex_weights)
03843 {
03844 vertex_weights_ = vertex_weights;
03845 return;
03846 }
03847
03848 ScalarMap
03849 ZoltanHyperGraph::GetVertexWeights() const
03850 {
03851 return vertex_weights_;
03852 }
03853
03854
03855
03856
03857 std::vector<ZOLTAN_ID_TYPE>
03858 ZoltanHyperGraph::GetEdgeIDs() const
03859 {
03860
03861 std::vector<ZOLTAN_ID_TYPE>
03862 edges;
03863
03864 for (AdjacencyMap::const_iterator
03865 graph_iter = graph_.begin();
03866 graph_iter != graph_.end();
03867 ++graph_iter) {
03868
03869 IDList
03870 hyperedges = (*graph_iter).second;
03871
03872
03873 for (IDList::const_iterator
03874 hyperedges_iter = hyperedges.begin();
03875 hyperedges_iter != hyperedges.end();
03876 ++hyperedges_iter) {
03877
03878 int const hyperedge = (*hyperedges_iter);
03879 edges.push_back(hyperedge);
03880
03881 }
03882 }
03883
03884 return edges;
03885 }
03886
03887
03888
03889
03890 std::vector<int>
03891 ZoltanHyperGraph::GetEdgePointers() const
03892 {
03893
03894 std::vector<int>
03895 pointers;
03896
03897 int
03898 pointer = 0;
03899
03900 for (AdjacencyMap::const_iterator
03901 graph_iter = graph_.begin();
03902 graph_iter != graph_.end();
03903 ++graph_iter) {
03904
03905 pointers.push_back(pointer);
03906
03907 IDList
03908 hyperedges = (*graph_iter).second;
03909
03910
03911 for (IDList::const_iterator
03912 hyperedges_iter = hyperedges.begin();
03913 hyperedges_iter != hyperedges.end();
03914 ++hyperedges_iter) {
03915
03916 ++pointer;
03917
03918 }
03919
03920 }
03921
03922 return pointers;
03923 }
03924
03925
03926
03927
03928 std::vector<ZOLTAN_ID_TYPE>
03929 ZoltanHyperGraph::GetVertexIDs() const
03930 {
03931
03932 std::vector<ZOLTAN_ID_TYPE>
03933 vertices;
03934
03935 for (AdjacencyMap::const_iterator
03936 graph_iter = graph_.begin();
03937 graph_iter != graph_.end();
03938 ++graph_iter) {
03939
03940 int vertex = (*graph_iter).first;
03941 vertices.push_back(vertex);
03942
03943 }
03944
03945 return vertices;
03946 }
03947
03948
03949
03950
03951 int
03952 ZoltanHyperGraph::GetNumberOfObjects(void* data, int* ierr)
03953 {
03954
03955 ZoltanHyperGraph &
03956 zoltan_hypergraph = *(static_cast<ZoltanHyperGraph*>(data));
03957
03958 *ierr = ZOLTAN_OK;
03959
03960 int
03961 num_objects = zoltan_hypergraph.GetGraph().size();
03962
03963 return num_objects;
03964 }
03965
03966
03967
03968
03969 void
03970 ZoltanHyperGraph::GetObjectList(
03971 void* data,
03972 int sizeGID,
03973 int sizeLID,
03974 ZOLTAN_ID_PTR globalID,
03975 ZOLTAN_ID_PTR localID,
03976 int wgt_dim,
03977 float* obj_wgts,
03978 int* ierr)
03979 {
03980
03981 ZoltanHyperGraph &
03982 zoltan_hypergraph = *(static_cast<ZoltanHyperGraph*>(data));
03983
03984 *ierr = ZOLTAN_OK;
03985
03986 ScalarMap
03987 vertex_weights = zoltan_hypergraph.GetVertexWeights();
03988
03989 ZOLTAN_ID_PTR
03990 global_id_ptr = globalID;
03991
03992 ZOLTAN_ID_PTR
03993 local_id_ptr = localID;
03994
03995 float*
03996 weight_ptr = obj_wgts;
03997
03998 for (ScalarMap::const_iterator
03999 weights_iter = vertex_weights.begin();
04000 weights_iter != vertex_weights.end();
04001 ++weights_iter) {
04002
04003 int vertex = (*weights_iter).first;
04004 double vertex_weight = (*weights_iter).second;
04005
04006
04007 (*global_id_ptr) = vertex;
04008 (*local_id_ptr) = vertex;
04009 (*weight_ptr) = vertex_weight;
04010 global_id_ptr++;
04011 local_id_ptr++;
04012 weight_ptr++;
04013
04014 }
04015
04016 return;
04017 }
04018
04019
04020
04021
04022 void
04023 ZoltanHyperGraph::GetHyperGraphSize(
04024 void* data,
04025 int* num_lists,
04026 int* num_pins,
04027 int* format,
04028 int* ierr)
04029 {
04030
04031 ZoltanHyperGraph &
04032 zoltan_hypergraph = *(static_cast<ZoltanHyperGraph*>(data));
04033
04034 *ierr = ZOLTAN_OK;
04035
04036
04037 *num_lists = zoltan_hypergraph.GetVertexIDs().size();
04038
04039
04040 *num_pins = zoltan_hypergraph.GetEdgeIDs().size();
04041
04042 *format = ZOLTAN_COMPRESSED_VERTEX;
04043
04044 return;
04045 }
04046
04047
04048
04049
04050 void
04051 ZoltanHyperGraph::GetHyperGraph(
04052 void* data,
04053 int num_gid_entries,
04054 int num_vtx_edge,
04055 int num_pins,
04056 int format,
04057 ZOLTAN_ID_PTR vtxedge_GID,
04058 int* vtxedge_ptr,
04059 ZOLTAN_ID_PTR pin_GID,
04060 int* ierr)
04061 {
04062
04063 ZoltanHyperGraph &
04064 zoltan_hypergraph = *(static_cast<ZoltanHyperGraph*>(data));
04065
04066 *ierr = ZOLTAN_OK;
04067
04068
04069 assert(num_vtx_edge ==
04070 static_cast<int>(zoltan_hypergraph.GetVertexIDs().size()));
04071
04072 assert(num_pins ==
04073 static_cast<int>(zoltan_hypergraph.GetEdgeIDs().size()));
04074
04075 assert(format == ZOLTAN_COMPRESSED_VERTEX);
04076
04077
04078 std::vector<ZOLTAN_ID_TYPE>
04079 vertex_IDs = zoltan_hypergraph.GetVertexIDs();
04080
04081 std::vector<ZOLTAN_ID_TYPE>
04082 edge_IDs = zoltan_hypergraph.GetEdgeIDs();
04083
04084 std::vector<int>
04085 edge_pointers = zoltan_hypergraph.GetEdgePointers();
04086
04087 for (std::vector<ZOLTAN_ID_TYPE>::size_type
04088 i = 0;
04089 i < vertex_IDs.size();
04090 ++i) {
04091
04092 vtxedge_GID[i] = vertex_IDs[i];
04093
04094 }
04095
04096 for (std::vector<ZOLTAN_ID_TYPE>::size_type
04097 i = 0;
04098 i < edge_IDs.size();
04099 ++i) {
04100
04101 pin_GID[i] = edge_IDs[i];
04102
04103 }
04104
04105 for (std::vector<int>::size_type
04106 i = 0;
04107 i < edge_pointers.size();
04108 ++i) {
04109
04110 vtxedge_ptr[i] = edge_pointers[i];
04111
04112 }
04113
04114 return;
04115 }
04116
04117
04118
04119
04120 std::istream &
04121 operator>>(std::istream & input_stream, ZoltanHyperGraph & zoltan_hypergraph)
04122 {
04123
04124
04125
04126 const std::vector<char>::size_type
04127 MaxChar = 256;
04128
04129 char line[MaxChar];
04130 input_stream.getline(line, MaxChar);
04131
04132 std::stringstream header(line);
04133 std::string token;
04134
04135
04136 header >> token;
04137 int number_vertices = atoi(token.c_str());
04138
04139
04140 header >> token;
04141 int number_hyperedges = atoi(token.c_str());
04142
04143 AdjacencyMap
04144 graph;
04145
04146 ScalarMap
04147 vertex_weights;
04148
04149
04150 for (int i = 0; i < number_vertices; ++i) {
04151
04152 input_stream.getline(line, MaxChar);
04153 std::stringstream input_line(line);
04154
04155
04156 input_line >> token;
04157 int vertex = atoi(token.c_str());
04158
04159
04160 input_line >> token;
04161 double vw = atof(token.c_str());
04162 vertex_weights[vertex] = vw;
04163
04164
04165 IDList hyperedges;
04166 while (input_line >> token) {
04167 int hyperedge = atoi(token.c_str());
04168 hyperedges.push_back(hyperedge);
04169 }
04170
04171 graph[vertex] = hyperedges;
04172
04173 }
04174
04175 zoltan_hypergraph.SetGraph(graph);
04176 zoltan_hypergraph.SetVertexWeights(vertex_weights);
04177 zoltan_hypergraph.SetNumberHyperedges(number_hyperedges);
04178
04179 return input_stream;
04180 }
04181
04182
04183
04184
04185 std::ostream &
04186 operator<<(
04187 std::ostream & output_stream,
04188 ZoltanHyperGraph const & zoltan_hypergraph)
04189 {
04190
04191 output_stream << std::setw(12) << zoltan_hypergraph.GetNumberVertices();
04192 output_stream << std::setw(12) << zoltan_hypergraph.GetNumberHyperedges();
04193 output_stream << '\n';
04194
04195 AdjacencyMap const &
04196 graph = zoltan_hypergraph.GetGraph();
04197
04198 ScalarMap
04199 vertex_weights = zoltan_hypergraph.GetVertexWeights();
04200
04201 for (AdjacencyMap::const_iterator
04202 graph_iter = graph.begin();
04203 graph_iter != graph.end();
04204 ++graph_iter) {
04205
04206
04207 int const
04208 vertex = (*graph_iter).first;
04209
04210 double const
04211 vertex_weight = vertex_weights[vertex];
04212
04213 output_stream << std::setw(12) << vertex;
04214 output_stream << std::scientific;
04215 output_stream << std::setw(16) << std::setprecision(8);
04216 output_stream << vertex_weight;
04217
04218 const IDList
04219 hyperedges = (*graph_iter).second;
04220
04221 for (IDList::const_iterator
04222 hyperedges_iter = hyperedges.begin();
04223 hyperedges_iter != hyperedges.end();
04224 ++hyperedges_iter) {
04225
04226 int const
04227 hyperedge = (*hyperedges_iter);
04228
04229 output_stream << std::setw(12) << hyperedge;
04230
04231 }
04232
04233 output_stream << '\n';
04234
04235 }
04236
04237 return output_stream;
04238 }
04239
04240 }
04241
04242 #endif // #if defined (ALBANY_LCM) && defined(ALBANY_ZOLTAN)