1 | /*!\file: NodesPartitioning.cpp
|
---|
2 | * \brief: partition elements and nodes and vertices
|
---|
3 | */
|
---|
4 |
|
---|
5 | #ifdef HAVE_CONFIG_H
|
---|
6 | #include <config.h>
|
---|
7 | #else
|
---|
8 | #error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
|
---|
9 | #endif
|
---|
10 |
|
---|
11 | #include <string.h>
|
---|
12 | #include "../../classes/objects/objects.h"
|
---|
13 | #include "../../shared/shared.h"
|
---|
14 | #include "../../EnumDefinitions/EnumDefinitions.h"
|
---|
15 | #include "../../io/io.h"
|
---|
16 | #include "../../include/include.h"
|
---|
17 | #include "../MeshPartitionx/MeshPartitionx.h"
|
---|
18 | #include "../ModelProcessorx/ModelProcessorx.h"
|
---|
19 |
|
---|
20 | void DiscontinuousGalerkinNodesPartitioning(bool** pmy_nodes,bool* my_elements, int* my_vertices, IoModel* iomodel);
|
---|
21 | void ContinuousGalerkinNodesPartitioning(bool** pmy_nodes,bool* my_elements, int* my_vertices, IoModel* iomodel);
|
---|
22 |
|
---|
23 | void NodesPartitioning(bool** pmy_nodes,bool* my_elements, int* my_vertices, IoModel* iomodel, bool continuous){
|
---|
24 |
|
---|
25 | /*First thing, this is a new partition for a new analysis_type, therefore, to avoid a leak, erase the nodes partition that might come through pmy_nodes: */
|
---|
26 | xDelete<bool>(*pmy_nodes);
|
---|
27 |
|
---|
28 | /*Now, depending on whether we are running galerkin discontinous or continuous elements, carry out a different partition of the nodes: */
|
---|
29 | if(continuous==true)
|
---|
30 | ContinuousGalerkinNodesPartitioning(pmy_nodes,my_elements, my_vertices, iomodel);
|
---|
31 | else
|
---|
32 | DiscontinuousGalerkinNodesPartitioning(pmy_nodes,my_elements, my_vertices, iomodel);
|
---|
33 | }
|
---|
34 |
|
---|
35 | void ContinuousGalerkinNodesPartitioning(bool** pmy_nodes,bool* my_elements, int* my_vertices, IoModel* iomodel){
|
---|
36 |
|
---|
37 | /*as many nodes as there are vertices */
|
---|
38 | int numberofvertices;
|
---|
39 |
|
---|
40 | /*output: */
|
---|
41 | bool* my_nodes=NULL;
|
---|
42 |
|
---|
43 | /*Fetch parameters: */
|
---|
44 | iomodel->Constant(&numberofvertices,MeshNumberofverticesEnum);
|
---|
45 |
|
---|
46 | my_nodes=xNew<bool>(numberofvertices);
|
---|
47 | for(int i=0;i<numberofvertices;i++) my_nodes[i]=(bool)my_vertices[i];
|
---|
48 |
|
---|
49 | /*Assign output pointers:*/
|
---|
50 | *pmy_nodes=my_nodes;
|
---|
51 | }
|
---|
52 |
|
---|
53 |
|
---|
54 | void DiscontinuousGalerkinNodesPartitioning(bool** pmy_nodes,bool* my_elements, int* my_vertices, IoModel* iomodel){
|
---|
55 |
|
---|
56 | int numberofelements;
|
---|
57 |
|
---|
58 | /*Fetch parameters: */
|
---|
59 | iomodel->Constant(&numberofelements,MeshNumberofelementsEnum);
|
---|
60 |
|
---|
61 | /*each element has it own nodes (as many as vertices) + additional nodes from neighbouring elements for each edge. This yields to a very different partition for
|
---|
62 | * the nodes and the vertices. The vertices are similar to continuous galerkin, but the nodes partitioning involves edges, which mess up sorting of
|
---|
63 | * ids. */
|
---|
64 |
|
---|
65 | int i,j;
|
---|
66 | int dim;
|
---|
67 |
|
---|
68 | /*output: */
|
---|
69 | bool* my_nodes=NULL;
|
---|
70 |
|
---|
71 | int i1,i2;
|
---|
72 | int cols;
|
---|
73 | int e1,e2;
|
---|
74 | int pos;
|
---|
75 | int numberofedges;
|
---|
76 | int *edges = NULL;
|
---|
77 | int *elements = NULL;
|
---|
78 |
|
---|
79 | /*Fetch parameters: */
|
---|
80 | iomodel->Constant(&dim,MeshDimensionEnum);
|
---|
81 |
|
---|
82 | /*Build discontinuous node partitioning
|
---|
83 | * - there are three nodes per element (discontinous)
|
---|
84 | * - for each element present of each partition, its three nodes will be in this partition
|
---|
85 | * - the edges require the dofs of the 2 nodes of each elements sharing the edge.
|
---|
86 | * if the 2 elements sharing the edge are on 2 different cpus, we must duplicate
|
---|
87 | * the two nodes that are not on the cpus so that the edge can access the dofs of
|
---|
88 | * all its 4 nodes
|
---|
89 | */
|
---|
90 |
|
---|
91 | /*Allocate*/
|
---|
92 | my_nodes=xNewZeroInit<bool>(3*numberofelements);
|
---|
93 |
|
---|
94 | /*First: add all the nodes of all the elements belonging to this cpu*/
|
---|
95 | if (dim==2){
|
---|
96 | for (i=0;i<numberofelements;i++){
|
---|
97 | if (my_elements[i]){
|
---|
98 | my_nodes[3*i+0]=true;
|
---|
99 | my_nodes[3*i+1]=true;
|
---|
100 | my_nodes[3*i+2]=true;
|
---|
101 | }
|
---|
102 | }
|
---|
103 | }
|
---|
104 | else{
|
---|
105 | _error2_("not implemented yet");
|
---|
106 | }
|
---|
107 |
|
---|
108 | /*Second: add all missing nodes*/
|
---|
109 |
|
---|
110 | /*Get edges and elements*/
|
---|
111 | iomodel->FetchData(&edges,&numberofedges,&cols,MeshEdgesEnum);
|
---|
112 | iomodel->FetchData(&elements,NULL,NULL,MeshElementsEnum);
|
---|
113 | if (cols!=4) _error2_("field edges should have 4 columns");
|
---|
114 |
|
---|
115 | /*!All elements have been partitioned above, only create elements for this CPU: */
|
---|
116 | for (i=0;i<numberofedges;i++){
|
---|
117 |
|
---|
118 | /*Get left and right elements*/
|
---|
119 | e1=edges[4*i+2]-1; //edges are [node1 node2 elem1 elem2]
|
---|
120 | e2=edges[4*i+3]-1; //edges are [node1 node2 elem1 elem2]
|
---|
121 |
|
---|
122 | /* 1) If the element e1 is in the current partition
|
---|
123 | * 2) and if the edge of the element is shared by another element (internal edge)
|
---|
124 | * 3) and if this element is not in the same partition:
|
---|
125 | * we must clone the nodes on this partition so that the loads (Numericalflux)
|
---|
126 | * will have access to their properties (dofs,...)*/
|
---|
127 | if(my_elements[e1] && e2!=-2 && !my_elements[e2]){
|
---|
128 |
|
---|
129 | /*1: Get vertices ids*/
|
---|
130 | i1=edges[4*i+0];
|
---|
131 | i2=edges[4*i+1];
|
---|
132 |
|
---|
133 | /*2: Get the column where these ids are located in the index*/
|
---|
134 | pos=UNDEF;
|
---|
135 | for(j=0;j<3;j++){
|
---|
136 | if (elements[3*e2+j]==i1) pos=j;
|
---|
137 | }
|
---|
138 |
|
---|
139 | /*3: We have the id of the elements and the position of the vertices in the index
|
---|
140 | * we can now create the corresponding nodes:*/
|
---|
141 | if (pos==0){
|
---|
142 | my_nodes[e2*3+0]=true;
|
---|
143 | my_nodes[e2*3+2]=true;
|
---|
144 | }
|
---|
145 | else if(pos==1){
|
---|
146 | my_nodes[e2*3+1]=true;
|
---|
147 | my_nodes[e2*3+0]=true;
|
---|
148 | }
|
---|
149 | else if (pos==2){
|
---|
150 | my_nodes[e2*3+2]=true;
|
---|
151 | my_nodes[e2*3+1]=true;
|
---|
152 | }
|
---|
153 | else{
|
---|
154 | _error2_("Problem in edges creation");
|
---|
155 | }
|
---|
156 | }
|
---|
157 | }
|
---|
158 |
|
---|
159 | /*Free data: */
|
---|
160 | xDelete<int>(elements);
|
---|
161 | xDelete<int>(edges);
|
---|
162 |
|
---|
163 | /*Assign output pointers:*/
|
---|
164 | *pmy_nodes=my_nodes;
|
---|
165 | }
|
---|