OOFEM 3.0
Loading...
Searching...
No Matches
connectivitytable.C
Go to the documentation of this file.
1/*
2 *
3 * ##### ##### ###### ###### ### ###
4 * ## ## ## ## ## ## ## ### ##
5 * ## ## ## ## #### #### ## # ##
6 * ## ## ## ## ## ## ## ##
7 * ## ## ## ## ## ## ## ##
8 * ##### ##### ## ###### ## ##
9 *
10 *
11 * OOFEM : Object Oriented Finite Element Code
12 *
13 * Copyright (C) 1993 - 2025 Borek Patzak
14 *
15 *
16 *
17 * Czech Technical University, Faculty of Civil Engineering,
18 * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19 *
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License as published by the Free Software Foundation; either
23 * version 2.1 of the License, or (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Lesser General Public License for more details.
29 *
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; if not, write to the Free Software
32 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33 */
34
35#include "connectivitytable.h"
36#include "domain.h"
37#include "element.h"
38#include "dofmanager.h"
39#include "feinterpol.h"
40#include "intarray.h"
41#include <set>
42
43
44namespace oofem {
45
47{
48#ifdef _OPENMP
49 omp_init_lock(&initLock);
50#endif
51}
52
53void
54ConnectivityTable :: reset()
55{
57 elementColoringFlag = false;
58}
59
60void
61ConnectivityTable :: instanciateConnectivityTable()
62//
63// assembles table of nodal connectivities
64//
65{
66 int ndofMan = domain->giveNumberOfDofManagers();
67 int nelems = domain->giveNumberOfElements();
68 IntArray dofManConnectivity(ndofMan);
69
71 return; // already initialized
72 }
73#ifdef _OPENMP
74 omp_set_lock(&initLock); // if not initialized yet; one thread can proceed with init; others have to wait until init completed
75 if ( this->nodalConnectivityFlag ) {
76 omp_unset_lock(&initLock);
77 return;
78 }
79#endif
80// OOFEM_LOG_INFO("ConnectivityTable: initializing\n");
81
82 for ( auto &elem : domain->giveElements() ) {
83 int nnodes = elem->giveNumberOfDofManagers();
84 for ( int j = 1; j <= nnodes; j++ ) {
85 int jnode = elem->giveDofManager(j)->giveNumber();
86 dofManConnectivity.at(jnode)++;
87 }
88 }
89
90 // allocate Nodal connectivity table for domain
91 nodalConnectivity.resize(ndofMan);
92 for ( int i = 0; i < ndofMan; i++ ) {
93 nodalConnectivity[i].resize( dofManConnectivity[i] );
94 }
95
96 // build Nodal connectivity table for domain
97 dofManConnectivity.zero();
98
99 for ( int i = 1; i <= nelems; i++ ) {
100 Element *ielem = domain->giveElement(i);
101 int nnodes = ielem->giveNumberOfDofManagers();
102 for ( int j = 1; j <= nnodes; j++ ) {
103 int jnode = ielem->giveDofManager(j)->giveNumber();
104 nodalConnectivity[jnode-1].at( ++dofManConnectivity.at(jnode) ) = i;
105 }
106 }
107
109
110 #ifdef _OPENMP
111 omp_unset_lock(&initLock);
112#endif
113
114}
115
116const IntArray *
117ConnectivityTable :: giveDofManConnectivityArray(int dofman)
118{
119 if ( nodalConnectivityFlag == 0 ) {
121 }
122
123 return &this->nodalConnectivity[dofman-1];
124}
125
126
127void
128ConnectivityTable :: giveElementNeighbourList(IntArray &answer, const IntArray &elemList)
129{
130 if ( nodalConnectivityFlag == 0 ) {
132 }
133
134 answer.resize(0);
135
136 for ( auto &el_num : elemList ) {
137 Element *ielem = domain->giveElement( el_num );
138 int nnode = ielem->giveNumberOfDofManagers();
139 for ( int j = 1; j <= nnode; j++ ) {
140 int jnode = ielem->giveDofManager(j)->giveNumber();
141 for ( auto &val : this->nodalConnectivity[jnode-1] ) {
142 answer.insertSortedOnce( val );
143 }
144 }
145 }
146}
147
148
149void
150ConnectivityTable :: giveNodeNeighbourList(IntArray &answer, IntArray &nodeList)
151{
152 int nnodes = nodeList.giveSize();
153 if ( nodalConnectivityFlag == 0 ) {
155 }
156
157 answer.resize(0);
158
159 for ( int i = 1; i <= nnodes; i++ ) {
160 int inode = nodeList.at(i);
161 for ( auto &val : this->nodalConnectivity[inode-1] ) {
162 answer.insertSortedOnce( val );
163 }
164 }
165}
166
167void
169{
170 // loop over individual node's connectivity arrays and find intersection (common elements)
171 answer.resize(0);
172 if (nodes.giveSize()) {
173 for (int i=1; i<= nodes.giveSize(); i++) {
174 const IntArray *candidates = this->giveDofManConnectivityArray(nodes.at(i));
175 if (i == 1) {
176 answer = *candidates; // first node gives preliminary set of elements
177 } else { // other nodes refine the set
178 for (int j=1; j<=answer.giveSize(); j++) { // loop over candidates
179 if (candidates->contains(answer.at(j)) == false) {
180 answer.erase(j);
181 j--;
182 }
183 }
184 }
185 }
186 }
187}
188
189void
191 // greedy coloring algorithm
192 // loop over elements
194 return;
195 } else {
196 int nelems = domain->giveNumberOfElements();
197 elementColoring.resize(nelems);
198 elementColoring.zero();
199 for (auto &elem : domain->elementList) {
200 IntArray neighbors;
201 giveElementNeighbourList(neighbors, IntArray({elem->giveNumber()}));
202 IntArray neighborsColors;
203 for (auto val : neighbors) {
204 neighborsColors.insertSortedOnce(elementColoring.at(val));
205 }
206 // find first unused color code in neighborsColor array
207 for (int c=1; true; c++) {
208 if (!neighborsColors.containsSorted(c)) {
209 elementColoring.at(elem->giveNumber()) = c;
210 break;
211 }
212 }
213 }
214 elementColoringFlag = true;
215 }
216}
217
218int
225
226
227void
229 // sets of processed boundary entities per element
230 std::vector<std::set<int>> processedBoundaryEdges;
231 std::vector<std::set<int>> processedBoundarySurfaces;
232
233 // local vars
234 IntArray bnodes, bnodesSorted, neighbors;
235
236 processedBoundaryEdges.resize(domain->giveNumberOfElements());
237 processedBoundarySurfaces.resize(domain->giveNumberOfElements());
238
239 // start with a loop over all elements
240 for (auto &elem : domain->elementList) {
241 // loop over all edges of the element
242 // int nsd = elem->giveSpatialDimension();
243 // process edges
244 int nedges = elem->giveNumberOfEdges();
245 for (int i = 1; i <= nedges; i++) {
246 if (processedBoundaryEdges[elem->giveNumber()-1].find(i) != processedBoundaryEdges[elem->giveNumber()-1].end()) {
247 continue; // edge already processed by neighbor element
248 }
249 // get element edge
250 bnodes = elem->giveBoundaryEdgeNodes(i);
251 for ( int j = 1; j <= bnodes.giveSize(); j++ ) {
252 bnodes.at(j) = elem->giveDofManager(bnodes.at(j))->giveNumber();
253 }
254 bnodesSorted = bnodes;
255 bnodesSorted.sort();
256
257 // create a boundary entity
258 std::unique_ptr<SharedBoundaryEntity> sbe = std::make_unique<SharedBoundaryEntity>();
259 sbe->nodes = bnodes;
260 SharedBoundaryEntity::elementRec er={elem->giveNumber(), i};
261 sbe->elements.push_back(er);
262 sbe->geomType = elem->giveEdgeGeometryType(i);
263 sbe->spatialDimension = 1;
264 std::size_t sbeIndex = sharedBoundaryEntities.size()+1;
265 // store the boundary entity ID on the element
266 elem->setSharedEdgeID(i, sbeIndex);
267
268 // now search element neighbors to find one sharing the same boundary nodes
269 this->giveElementsWithNodes(neighbors, bnodes);
270 // loop over elements sharing the boundary entity
271 for (auto neighborelem : neighbors) {
272 if (neighborelem == elem->giveNumber()) {
273 continue;
274 }
275 int neighborboundary = 0;
276 IntArray neighborBoundaryNodes;
277 for ( int j = 1; j <= domain->giveElement(neighborelem)->giveNumberOfEdges(); j++ ) {
278 bool equal = true;
279 neighborBoundaryNodes = domain->giveElement(neighborelem)->giveBoundaryEdgeNodes(j);// edge or surface?
280 for ( int k = 1; k <= neighborBoundaryNodes.giveSize(); k++ ) {
281 neighborBoundaryNodes.at(k) = domain->giveElement(neighborelem)->giveDofManager(neighborBoundaryNodes.at(k))->giveNumber();
282 }
283
284 // compare bnodes (sorted) with neighborBoundaryNodes
285 for ( int k = 1; k <= neighborBoundaryNodes.giveSize(); k++ ) {
286 if ( !bnodesSorted.findSorted(neighborBoundaryNodes.at(k))) {
287 equal = false;
288 break;
289 }
290 }
291 if ( equal) {
292 neighborboundary = j;
293 break;
294 }
295 }
296 if (neighborboundary) {
297 // store the boundary entity id on the neighbor element
298 domain->giveElement(neighborelem)->setSharedEdgeID(neighborboundary, sbeIndex);
299 SharedBoundaryEntity::elementRec er={neighborelem, neighborboundary};
300 sbe->elements.push_back(er);
301 processedBoundaryEdges[neighborelem-1].insert(neighborboundary);
302 } else {
303 OOFEM_ERROR("Boundary entity not found in neighbor element");
304 }
305 } // end loop over neighbors
306 sharedBoundaryEntities.emplace_back(std::move(sbe));
307 } // end loop over element edges
308 } // end loop over elements
309
310 // @TODO now process surfaces
311
312 //@DEBUG print BEs
313#if 0
314 for (auto& be: this->sharedBoundaryEntities) {
315 printf("BE nodes ");
316 for (auto n: be->nodes) {
317 printf("%4d ", n);
318 }
319 printf("elements/sides ");
320 for (auto& p: be->elements) {
321 printf("%4d(%2d) ", p.elementID, p.boundaryID);
322 }
323 printf("\n");
324 }
325#endif
326}
327
330 SharedBoundaryEntity *be = reinterpret_cast< SharedBoundaryEntity * >( sharedBoundaryEntities[id-1].get() );
331 return be;
332}
333
334
335} // end namespace oofem
SharedBoundaryEntity * giveBoundaryEntity(int id)
bool elementColoringFlag
flag indicating assembled element coloring
const IntArray * giveDofManConnectivityArray(int dofman)
Domain * domain
Pointer to domain to which receiver belongs to.
void giveElementNeighbourList(IntArray &answer, const IntArray &elemList)
void giveElementsWithNodes(IntArray &answer, const IntArray &nodes)
std::vector< IntArray > nodalConnectivity
Nodal connectivity table for domain.
int nodalConnectivityFlag
Flag indicating assembled connectivity table for domain.
IntArray elementColoring
Element colors.
std::vector< std::unique_ptr< SharedBoundaryEntity > > sharedBoundaryEntities
void buildSharedBoundaryEntities(Domain *d)
virtual int giveNumberOfDofManagers() const
Definition element.h:695
DofManager * giveDofManager(int i) const
Definition element.C:553
int giveNumber() const
Definition femcmpnn.h:104
bool insertSortedOnce(int value, int allocChunk=0)
Definition intarray.C:309
void resize(int n)
Definition intarray.C:73
int findSorted(int value) const
Definition intarray.C:293
bool contains(int value) const
Definition intarray.h:292
void erase(int pos)
Definition intarray.C:112
void zero()
Sets all component to zero.
Definition intarray.C:52
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
#define OOFEM_ERROR(...)
Definition error.h:79

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011