Directory: | ./ |
---|---|
File: | DegreeOfFreedom/dofBoundary.cpp |
Date: | 2024-04-14 07:32:34 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 193 | 487 | 39.6% |
Branches: | 206 | 1400 | 14.7% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | // ______ ______ _ _ _____ ______ | ||
2 | // | ____| ____| | (_)/ ____| | ____| | ||
3 | // | |__ | |__ | | _| (___ ___| |__ | ||
4 | // | __| | __| | | | |\___ \ / __| __| | ||
5 | // | | | |____| |____| |____) | (__| |____ | ||
6 | // |_| |______|______|_|_____/ \___|______| | ||
7 | // Finite Elements for Life Sciences and Engineering | ||
8 | // | ||
9 | // License: LGL2.1 License | ||
10 | // FELiScE default license: LICENSE in root folder | ||
11 | // | ||
12 | // Main authors: J. Foulon & J-F. Gerbeau | ||
13 | // | ||
14 | |||
15 | // System includes | ||
16 | #include <unordered_map> | ||
17 | |||
18 | // External includes | ||
19 | |||
20 | // Project includes | ||
21 | #include "DegreeOfFreedom/dofBoundary.hpp" | ||
22 | #include "Solver/linearProblem.hpp" | ||
23 | #include "PETScInterface/petscMatrix.hpp" | ||
24 | |||
25 | namespace felisce | ||
26 | { | ||
27 | /*! \brief Class constructor. | ||
28 | It sets all flags to false | ||
29 | */ | ||
30 | 538 | DofBoundary::DofBoundary(): | |
31 | 538 | m_boundaryPatternAlreadyBuilt(false), | |
32 | 538 | m_dofBoundaryHasBeenInitialized(false), | |
33 | 538 | m_volumeInterfaceMappingBuilt(false) | |
34 | 538 | {} | |
35 | |||
36 | /*! \brief Initializer of the entire class | ||
37 | |||
38 | It has to be called in linear problem. | ||
39 | |||
40 | \param[in] lpb_ptr a pointer to the linear problem class. | ||
41 | |||
42 | The flag #m_dofBoundaryHasBeenInitialized is std::set to false. | ||
43 | */ | ||
44 | 8 | void DofBoundary::initialize(LinearProblem* lpb_ptr) { | |
45 | 8 | m_dofPtr = &lpb_ptr->dof(); | |
46 | 8 | m_ao = lpb_ptr->ao(); | |
47 | 8 | m_dofPartPtr = &lpb_ptr->dofPartition(); | |
48 | 8 | m_dofBoundaryHasBeenInitialized=true; | |
49 | 8 | } | |
50 | |||
51 | /*! \brief It creates the pattern for a sparse matrix defined on the boundary. | ||
52 | |||
53 | The pattern is taken directly from the volume pattern. | ||
54 | It implies: | ||
55 | - #m_dofBoundaryHasBeenInitialized = true | ||
56 | - #m_volumeInterfaceMappingBuilt = true. | ||
57 | In case it had already been called before it does not do anyting. | ||
58 | It raises the flag #m_boundaryPatternAlreadyBuilt to true. | ||
59 | |||
60 | #m_boundaryPattern is created. | ||
61 | */ | ||
62 | ✗ | void DofBoundary::buildBoundaryPattern() { | |
63 | ✗ | if ( m_boundaryPatternAlreadyBuilt ) | |
64 | ✗ | return; | |
65 | ✗ | if ( !m_dofBoundaryHasBeenInitialized ) | |
66 | ✗ | FEL_ERROR("dof boundary not yet initialized"); | |
67 | ✗ | if ( !m_volumeInterfaceMappingBuilt) | |
68 | ✗ | FEL_ERROR("volume interface mapping not yet build"); | |
69 | // if the pattern is already built than exit | ||
70 | ✗ | m_boundaryPatternAlreadyBuilt = true; | |
71 | |||
72 | // create a mapping to get local numbering of a dof given in global application numbering | ||
73 | // TODO check if the mapping is present in linearProblem | ||
74 | ✗ | felInt idLocal = 0; | |
75 | ✗ | std::unordered_map<felInt,felInt> glob2loc; | |
76 | ✗ | for (felInt i = 0; i < m_dofPtr->numDof(); i++) { | |
77 | ✗ | if ( (*m_dofPartPtr)[i] == MpiInfo::rankProc()) { | |
78 | ✗ | glob2loc[i] = idLocal; | |
79 | ✗ | idLocal++; | |
80 | } | ||
81 | } | ||
82 | |||
83 | // this structure will contain, for each node on the Boundary, the std::vector of the neighbours which belong to the boundary. | ||
84 | // it is local to the proc. | ||
85 | ✗ | std::vector< std::vector< felInt > > nodesNeighborhood( m_numLocalDofInterface ); | |
86 | // the number of nnz in the local pattern | ||
87 | ✗ | std::size_t nnz = 0; | |
88 | // building of nodesNeighborhood: | ||
89 | // for each surface node in this proc.. | ||
90 | ✗ | for ( int iNode = 0; iNode < m_numLocalDofInterface; iNode++ ) { | |
91 | // get all the neighbours! | ||
92 | // they can be both on surface and in the volume | ||
93 | // and in this proc or in another | ||
94 | ✗ | std::vector<felInt> currentVecOfNeighbour; | |
95 | ✗ | felInt iGlobAppli = m_loc2PetscVolume[iNode]; | |
96 | ✗ | AOPetscToApplication(m_ao,1,&iGlobAppli); | |
97 | ✗ | m_dofPtr->getNeighbourhood( glob2loc[iGlobAppli], currentVecOfNeighbour ); //currentVec is in global application numbering | |
98 | // we save only the neighbours that are on the surface | ||
99 | // we take also the neighbours on different proc | ||
100 | ✗ | for ( std::size_t iNeigh(0); iNeigh < currentVecOfNeighbour.size(); ++iNeigh ) { | |
101 | ✗ | felInt iPetsc = currentVecOfNeighbour[iNeigh]; | |
102 | ✗ | AOApplicationToPetsc(m_ao,1,&iPetsc); | |
103 | ✗ | if ( std::find( m_glob2PetscVolume.begin(), m_glob2PetscVolume.end(), iPetsc) != m_glob2PetscVolume.end() ) { | |
104 | ✗ | nodesNeighborhood[ iNode ].push_back(currentVecOfNeighbour[iNeigh]); | |
105 | } | ||
106 | } | ||
107 | // we update nnz | ||
108 | ✗ | nnz = nnz + nodesNeighborhood[ iNode ].size(); | |
109 | } | ||
110 | // resize of the pattern! | ||
111 | // nb of rows: m_numLocalDofInterface | ||
112 | // total number of non zeros | ||
113 | ✗ | m_boundaryPattern.resize(m_numLocalDofInterface,nnz); | |
114 | // we fill it! | ||
115 | ✗ | for ( int iNode = 0; iNode < m_numLocalDofInterface; iNode++) { | |
116 | ✗ | m_boundaryPattern.rowPointer(iNode+1) = m_boundaryPattern.rowPointer(iNode) + nodesNeighborhood[iNode].size(); | |
117 | ✗ | felInt pos = 0; | |
118 | ✗ | for(auto iCon = nodesNeighborhood[iNode].begin(); iCon != nodesNeighborhood[iNode].end(); iCon++) { | |
119 | // here we apply the std::unordered_map petscVolume2Glob to move the index *iCon from the global application volume ordering to | ||
120 | // the global application interface ordering | ||
121 | ✗ | felInt iPetscVol = *iCon; | |
122 | ✗ | AOApplicationToPetsc( m_ao, 1, &iPetscVol ); | |
123 | ✗ | m_boundaryPattern.columnIndex( m_boundaryPattern.rowPointer(iNode) + pos ) = m_petscVolume2Glob[ iPetscVol ]; | |
124 | ✗ | pos++; | |
125 | } | ||
126 | } | ||
127 | } | ||
128 | |||
129 | /*! \brief It allocates a sparse petsc matrix using the boundary pattern. | ||
130 | |||
131 | \param[in,out] theMatrix an empty matrix that will be allocated. | ||
132 | |||
133 | It is usefull, for instance, to allocate a mass matrix on the boarder. | ||
134 | It is necessary to pass a completely empty matrix. | ||
135 | |||
136 | If the boundary pattern was not built it builds it. | ||
137 | */ | ||
138 | ✗ | void DofBoundary::allocateMatrixOnBoundary( PetscMatrix& theMatrix ) { | |
139 | ✗ | if ( !m_boundaryPatternAlreadyBuilt ) | |
140 | ✗ | this->buildBoundaryPattern(); | |
141 | // only processors who actually own some nodes on the boundary | ||
142 | ✗ | if ( m_numLocalDofInterface > 0 ) { | |
143 | // we get the nb of procs that share the boundary nodes | ||
144 | felInt size; | ||
145 | ✗ | MPI_Comm_size( m_boundaryComm, &size ); | |
146 | |||
147 | // the matrix is now allocate in the same way as it is done for the system matrix | ||
148 | // parallel case | ||
149 | ✗ | if ( size > 1 ) { | |
150 | |||
151 | ✗ | std::vector<felInt> jCSR = m_boundaryPattern.columnIndices(); | |
152 | ✗ | AOApplicationToPetsc(m_aoInterface, m_boundaryPattern.numNonzeros(), jCSR.data()); | |
153 | |||
154 | ✗ | theMatrix.createAIJ(m_boundaryComm, m_numLocalDofInterface, m_numLocalDofInterface, | |
155 | m_numGlobalDofInterface, m_numGlobalDofInterface, 0, | ||
156 | FELISCE_PETSC_NULLPTR, 0, FELISCE_PETSC_NULLPTR); | ||
157 | ✗ | theMatrix.mpiAIJSetPreallocationCSR(m_boundaryPattern.rowPointer().data(), jCSR.data(), nullptr); | |
158 | ✗ | theMatrix.setOption(MAT_KEEP_NONZERO_PATTERN, PETSC_TRUE); | |
159 | ✗ | theMatrix.setFromOptions(); | |
160 | ✗ | } // serial case | |
161 | else { | ||
162 | |||
163 | ✗ | std::size_t numRows = m_boundaryPattern.numRows(); | |
164 | ✗ | std::vector<felInt> nnz( numRows ); | |
165 | ✗ | for ( std::size_t idof = 0; idof < numRows; idof++ ) { | |
166 | ✗ | nnz[idof] = m_boundaryPattern.numNonzerosInRow(idof); | |
167 | } | ||
168 | |||
169 | ✗ | theMatrix.createSeqAIJ(m_boundaryComm, numRows, numRows, 0, nnz.data()); | |
170 | ✗ | theMatrix.setOption(MAT_KEEP_NONZERO_PATTERN, PETSC_TRUE); | |
171 | ✗ | theMatrix.setFromOptions(); | |
172 | } | ||
173 | } | ||
174 | } | ||
175 | |||
176 | /***********************************************************************************/ | ||
177 | /***********************************************************************************/ | ||
178 | |||
179 | 308 | PetscVector DofBoundary::allocateBoundaryVector(vectorType type) | |
180 | { | ||
181 | // To use this function you have to firt initialize correctly dofBoundary | ||
182 | // look for instance into linearProblemNSRS.cpp | ||
183 | 308 | PetscVector v; | |
184 |
1/2✓ Branch 1 taken 308 times.
✗ Branch 2 not taken.
|
308 | if ( hasDofsOnBoundary() ) { |
185 | int numProcOnBoundary; | ||
186 |
1/2✓ Branch 2 taken 308 times.
✗ Branch 3 not taken.
|
308 | MPI_Comm_size( comm(), &numProcOnBoundary); |
187 |
2/4✓ Branch 0 taken 308 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 308 times.
|
308 | if ( numProcOnBoundary == 1 || type == sequential ) { |
188 | ✗ | v.createSeq( comm(), numGlobalDofInterface() ); | |
189 | } else { | ||
190 |
1/2✓ Branch 4 taken 308 times.
✗ Branch 5 not taken.
|
308 | v.createMPI( comm(), numLocalDofInterface(), numGlobalDofInterface() ); |
191 | } | ||
192 |
1/2✓ Branch 1 taken 308 times.
✗ Branch 2 not taken.
|
308 | v.setFromOptions(); |
193 | } | ||
194 | 308 | return v; | |
195 | } | ||
196 | |||
197 | /***********************************************************************************/ | ||
198 | /***********************************************************************************/ | ||
199 | |||
200 | 160 | void DofBoundary::restrictOnBoundary(PetscVector& volumeVector, PetscVector& parallelBoundaryVector) | |
201 | { | ||
202 |
1/2✓ Branch 1 taken 160 times.
✗ Branch 2 not taken.
|
160 | if ( hasDofsOnBoundary() ) { |
203 |
1/2✓ Branch 3 taken 160 times.
✗ Branch 4 not taken.
|
160 | std::vector<double> tmpValuesBD( numLocalDofInterface(), 0.0); |
204 |
1/2✓ Branch 4 taken 160 times.
✗ Branch 5 not taken.
|
160 | volumeVector.getValues(numLocalDofInterface(), loc2PetscVolPtr(), tmpValuesBD.data()); |
205 |
1/2✓ Branch 4 taken 160 times.
✗ Branch 5 not taken.
|
160 | parallelBoundaryVector.setValues(numLocalDofInterface(), loc2PetscBDPtr(), tmpValuesBD.data(), INSERT_VALUES); |
206 |
1/2✓ Branch 1 taken 160 times.
✗ Branch 2 not taken.
|
160 | parallelBoundaryVector.assembly(); |
207 | 160 | } | |
208 | 160 | } | |
209 | |||
210 | /***********************************************************************************/ | ||
211 | /***********************************************************************************/ | ||
212 | |||
213 | 152 | void DofBoundary::extendOnVolume(PetscVector& parallelVolumeVector, PetscVector& boundaryVector) | |
214 | { | ||
215 |
1/2✓ Branch 1 taken 152 times.
✗ Branch 2 not taken.
|
152 | if ( hasDofsOnBoundary() ) { |
216 |
1/2✓ Branch 3 taken 152 times.
✗ Branch 4 not taken.
|
152 | std::vector<double> tmpValuesBD( numLocalDofInterface(), 0.0); |
217 |
1/2✓ Branch 4 taken 152 times.
✗ Branch 5 not taken.
|
152 | boundaryVector.getValues( numLocalDofInterface(), loc2PetscBDPtr(), tmpValuesBD.data()); // Values are read from the boundary std::vector. |
218 |
1/2✓ Branch 4 taken 152 times.
✗ Branch 5 not taken.
|
152 | parallelVolumeVector.setValues( numLocalDofInterface(), loc2PetscVolPtr(), tmpValuesBD.data(), INSERT_VALUES); // Values are written in a PARALLEL volume std::vector. |
219 | 152 | } | |
220 | 152 | parallelVolumeVector.assembly(); | |
221 | 152 | } | |
222 | |||
223 | /***********************************************************************************/ | ||
224 | /***********************************************************************************/ | ||
225 | |||
226 | 16 | void DofBoundary::buildListOfBoundaryPetscDofs(LinearProblem* lpb_ptr, std::vector<int> labelOfInterface, int iUnknown, int iComponent) | |
227 | { | ||
228 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | if ( ! m_dofBoundaryHasBeenInitialized ) |
229 | ✗ | FEL_ERROR("dof boundary not yet initialized"); | |
230 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | std::size_t iUC(m_dofPtr->getNumGlobComp(iUnknown,iComponent)); |
231 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | if ( iUC >= m_dofsHaveBeenComputed.size() ) { |
232 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | m_dofsHaveBeenComputed.resize( iUC+1, false); |
233 | ✗ | } else if ( m_dofsHaveBeenComputed[iUC] ) { | |
234 | ✗ | std::stringstream msg; | |
235 | ✗ | msg<<"list of boundary petsc dofs already computed for iUnknown: "<<iUnknown<<" iComp: "<<iComponent<<std::endl; | |
236 | ✗ | FEL_ERROR(msg.str().c_str()); | |
237 | } | ||
238 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | m_dofsHaveBeenComputed[iUC] = true; |
239 | |||
240 | 16 | const int idVar = lpb_ptr->listUnknown().idVariable(iUnknown); | |
241 | 16 | const int iMesh = lpb_ptr->listVariable()[idVar].idMesh(); | |
242 |
2/4✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
|
16 | if (FelisceParam::verbose() > 2 ) |
243 | ✗ | std::cout<<"["<<MpiInfo::rankProc()<<"]starting std::unordered_map interface creation in "<<lpb_ptr->name()<<" unknown id: "<<iUnknown<<", component: "<<iComponent<<std::endl; | |
244 | |||
245 | 16 | std::vector<setOfPairOfIntAndPoint> globalVecOfSet; | |
246 | |||
247 | // some useful std::vector | ||
248 | 16 | std::vector<Point*> elemPoint; | |
249 | 16 | std::vector<felInt> elemIdPoint; | |
250 | 16 | std::vector<felInt> vectorIdSupport; | |
251 | |||
252 | //to improve readability | ||
253 | 16 | GeometricMeshRegion::Pointer mesh = lpb_ptr->meshLocal(iMesh); | |
254 | 16 | const std::vector<GeometricMeshRegion::ElementType>& bagElementTypeDomainBoundary = mesh->bagElementTypeDomainBoundary(); | |
255 | |||
256 | //initialization of the counter numElement | ||
257 | felInt numElement[ GeometricMeshRegion::m_numTypesOfElement ]; //std::vector of size 23 number of the different type of elements why we do not use a std::unordered_map | ||
258 |
2/2✓ Branch 0 taken 400 times.
✓ Branch 1 taken 16 times.
|
416 | for (int ityp=0; ityp < GeometricMeshRegion::m_numTypesOfElement; ityp++ ) { |
259 | 400 | numElement[ityp]=0; | |
260 | } | ||
261 | |||
262 | //========loop on the element type of boundary (e.g. triangles..not a real loop) | ||
263 |
2/2✓ Branch 1 taken 16 times.
✓ Branch 2 taken 16 times.
|
32 | for (std::size_t i = 0; i < bagElementTypeDomainBoundary.size(); ++i) { |
264 | 16 | GeometricMeshRegion::ElementType eltType = bagElementTypeDomainBoundary[i]; | |
265 | |||
266 | 16 | int typeOfFiniteElement = lpb_ptr->listVariable()[idVar].finiteElementType(); | |
267 | 16 | const GeoElement *geoEle = GeometricMeshRegion::eltEnumToFelNameGeoEle[eltType].second; | |
268 |
1/2✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | const RefElement *refEle = geoEle->defineFiniteEle(eltType, typeOfFiniteElement, *mesh); |
269 |
2/4✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 8 not taken.
|
16 | CurvilinearFiniteElement* fe = new CurvilinearFiniteElement(*refEle, *geoEle, lpb_ptr->listVariable()[idVar].degreeOfExactness()); |
270 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | FEL_ASSERT(fe); |
271 |
3/6✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 16 times.
|
16 | if( FelisceParam::instance(lpb_ptr->instanceIndex()).flipNormal ) |
272 | ✗ | fe->m_sign = -1; | |
273 | |||
274 | 16 | const int numPointPerElt = GeometricMeshRegion::m_numPointsPerElt[eltType]; | |
275 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | elemPoint.resize(numPointPerElt, nullptr); |
276 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | elemIdPoint.resize(numPointPerElt, 0); |
277 | |||
278 | //=======loop on subregion of the surface, with different labels. | ||
279 |
2/2✓ Branch 6 taken 40 times.
✓ Branch 7 taken 16 times.
|
56 | for(auto itRef = mesh->intRefToBegEndMaps[eltType].begin(); itRef != mesh->intRefToBegEndMaps[eltType].end(); itRef++) { |
280 | 40 | const int currentLabel = itRef->first; | |
281 | 40 | const int numEltPerLabel = itRef->second.second; | |
282 | |||
283 | 40 | bool Found( false ); //flag to select the correct label | |
284 |
5/6✓ Branch 4 taken 40 times.
✓ Branch 5 taken 40 times.
✓ Branch 6 taken 40 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 40 times.
✓ Branch 9 taken 40 times.
|
80 | for(auto it_labelNumber = labelOfInterface.begin(); it_labelNumber != labelOfInterface.end() && !Found; ++it_labelNumber) { |
285 |
2/2✓ Branch 1 taken 16 times.
✓ Branch 2 taken 24 times.
|
40 | if(*it_labelNumber == currentLabel) { |
286 | 16 | Found=true; | |
287 | |||
288 |
1/2✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | setOfPairOfIntAndPoint localSetOfPointsAndIds(&Tools::lgPairComparison); |
289 | |||
290 |
2/2✓ Branch 0 taken 320 times.
✓ Branch 1 taken 16 times.
|
336 | for ( felInt iel = 0; iel < numEltPerLabel; iel++) { |
291 | // return each id of point of the element and coordinate in two arrays: | ||
292 | // elemPoint and elemIdPoint. | ||
293 |
1/2✓ Branch 1 taken 320 times.
✗ Branch 2 not taken.
|
320 | lpb_ptr->setElemPoint(eltType, numElement[eltType], elemPoint, elemIdPoint, vectorIdSupport); |
294 | |||
295 | // loop over all the support elements | ||
296 |
2/2✓ Branch 1 taken 320 times.
✓ Branch 2 taken 320 times.
|
640 | for (std::size_t it = 0; it < vectorIdSupport.size(); it++) { |
297 | // get the id of the support | ||
298 | 320 | felInt ielSupportDof = vectorIdSupport[it]; | |
299 |
2/2✓ Branch 1 taken 640 times.
✓ Branch 2 taken 320 times.
|
960 | for ( std::size_t iSurfDof(0); iSurfDof < (std::size_t) fe->numDof(); iSurfDof++ ) { |
300 | |||
301 | felInt iDofGlobScalar; | ||
302 |
1/2✓ Branch 2 taken 640 times.
✗ Branch 3 not taken.
|
640 | lpb_ptr->dof().loc2glob( ielSupportDof, iSurfDof, idVar, iComponent, iDofGlobScalar); |
303 |
1/2✓ Branch 1 taken 640 times.
✗ Branch 2 not taken.
|
640 | AOApplicationToPetsc(m_ao,1,&iDofGlobScalar); |
304 | Point P; | ||
305 |
1/2✓ Branch 1 taken 640 times.
✗ Branch 2 not taken.
|
640 | lpb_ptr->getSupportCoordinate(eltType, numElement[eltType], iSurfDof, iUnknown, P); |
306 |
2/4✓ Branch 1 taken 640 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 640 times.
✗ Branch 5 not taken.
|
640 | localSetOfPointsAndIds.insert(std::make_pair(iDofGlobScalar,P) ); |
307 | } | ||
308 | } | ||
309 | 320 | numElement[eltType]++; | |
310 | } | ||
311 | |||
312 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 2 taken 8 times.
|
16 | if ( int(m_localVecOfSet.size()) <= currentLabel ) { |
313 |
2/4✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
|
8 | m_localVecOfSet.resize(currentLabel+1, setOfPairOfIntAndPoint(&Tools::lgPairComparison) ); |
314 | } | ||
315 |
1/2✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | m_localVecOfSet[currentLabel] = localSetOfPointsAndIds; |
316 | 16 | } | |
317 | } | ||
318 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 16 times.
|
40 | if (!Found) |
319 | 24 | numElement[eltType] += numEltPerLabel; | |
320 | } | ||
321 | |||
322 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | delete fe; |
323 | }//end of the loop | ||
324 | |||
325 |
1/2✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | const int idUnknComp = lpb_ptr->dof().getNumGlobComp(iUnknown,iComponent); |
326 |
2/2✓ Branch 4 taken 16 times.
✓ Branch 5 taken 16 times.
|
32 | for(auto it_labelNumber = labelOfInterface.begin(); it_labelNumber != labelOfInterface.end(); ++it_labelNumber) { |
327 | |||
328 |
2/4✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
|
16 | if ( FelisceParam::verbose() > 3 ) |
329 | ✗ | std::cout<<"["<<MpiInfo::rankProc()<<"] starting gathering phase"<<std::endl; | |
330 | |||
331 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
|
16 | if ( int( m_localVecOfSet.size() ) <= *it_labelNumber ) |
332 | ✗ | m_localVecOfSet.resize(*it_labelNumber+1, setOfPairOfIntAndPoint(&Tools::lgPairComparison) ); | |
333 | |||
334 |
1/2✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
16 | if ( int( globalVecOfSet.size() ) <= *it_labelNumber ) |
335 |
2/4✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 16 times.
✗ Branch 7 not taken.
|
16 | globalVecOfSet.resize(*it_labelNumber+1, setOfPairOfIntAndPoint(&Tools::lgPairComparison) ); |
336 | |||
337 |
1/2✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
|
16 | Tools::allGatherSetPair(m_localVecOfSet[*it_labelNumber],globalVecOfSet[*it_labelNumber]); |
338 | 16 | const auto& r_global_vec = globalVecOfSet[*it_labelNumber]; | |
339 | |||
340 |
2/4✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
|
16 | if ( FelisceParam::verbose() > 3 ) |
341 | ✗ | std::cout<<"["<<MpiInfo::rankProc()<<"] ending gathering phase"<<std::endl; | |
342 | |||
343 | 16 | int cPoint=0; | |
344 | |||
345 |
2/2✓ Branch 3 taken 1296 times.
✓ Branch 4 taken 16 times.
|
1312 | for(auto it= r_global_vec.begin(); it!= r_global_vec.end(); ++it) { |
346 |
3/6✓ Branch 2 taken 1296 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1296 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1296 times.
✗ Branch 10 not taken.
|
1296 | m_listOfBoundaryPetscDofs[ idUnknComp ][*it_labelNumber][cPoint] = it->first; |
347 | 1296 | cPoint++; | |
348 | } | ||
349 | 16 | cPoint=0; | |
350 |
3/4✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 8 times.
|
16 | if ( m_mapLab2AllPoints[*it_labelNumber].size() == 0 ) { |
351 |
2/2✓ Branch 4 taken 648 times.
✓ Branch 5 taken 8 times.
|
656 | for(auto it= r_global_vec.begin(); it!= r_global_vec.end(); ++it) { |
352 |
1/2✓ Branch 0 taken 648 times.
✗ Branch 1 not taken.
|
648 | if (cPoint==0) { |
353 |
1/2✓ Branch 3 taken 648 times.
✗ Branch 4 not taken.
|
648 | m_mapLab2FirstPoint[*it_labelNumber] = it->second; |
354 | } | ||
355 |
2/4✓ Branch 2 taken 648 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 648 times.
✗ Branch 7 not taken.
|
648 | m_mapLab2AllPoints[*it_labelNumber].push_back(it->second); |
356 | } | ||
357 | 8 | cPoint++; | |
358 | } | ||
359 | |||
360 | } | ||
361 |
2/4✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
|
16 | if ( FelisceParam::verbose() > 3 ) |
362 | ✗ | std::cout<<"["<<MpiInfo::rankProc()<<"] ended"<<std::endl; | |
363 |
2/4✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
|
16 | if ( FelisceParam::verbose() > 3 ) |
364 | ✗ | std::cout<<"["<<MpiInfo::rankProc()<<"] "<<m_listOfBoundaryPetscDofs[idUnknComp].size()<<" labels, for "<<idUnknComp<<" id unknown and component"<<std::endl; | |
365 | 16 | } | |
366 | |||
367 | /***********************************************************************************/ | ||
368 | /***********************************************************************************/ | ||
369 | |||
370 | ✗ | void DofBoundary::writeSurfaceInterpolatorFile(int iUnknown, int numComp, std::string filename, std::string folder) const { | |
371 | // iUnknwon: index of the unknown we want to interpolate. | ||
372 | // numComp: number of components to distinguish between scalars (1) and vectors (2 or 3). | ||
373 | |||
374 | // Goal of the function is to write a list of the points, belonging to the surface, | ||
375 | // that support a degree of freedom (or more) for this unknown. | ||
376 | |||
377 | // ids: for each point we store the id (in globalApplicationOrderingBD) or the ids in the case of a std::vector(that's why a std::set is used.) | ||
378 | ✗ | std::vector<std::vector<int> > ids; | |
379 | // labels: for each point we save the surfaceLabel. | ||
380 | // if he belongs to more than one label we store the first one found. | ||
381 | ✗ | std::vector<felInt> labels; | |
382 | // points: for each point we actually store the Point. | ||
383 | ✗ | std::vector<Point> points; | |
384 | |||
385 | // Checking that everything was allocated | ||
386 | ✗ | for ( felInt iComp(0); iComp<numComp; ++iComp) { | |
387 | ✗ | std::size_t iUC=m_dofPtr->getNumGlobComp(iUnknown, iComp); | |
388 | ✗ | if ( iUC >= m_dofsHaveBeenComputed.size() || !m_dofsHaveBeenComputed[iUC] ) { | |
389 | ✗ | std::stringstream msg; | |
390 | ✗ | msg<<"Error in writing surface interpolator file for iUnknown: "<<iUnknown<<" and iComp: "<<iComp<<std::endl; | |
391 | ✗ | FEL_ERROR(msg.str().c_str()); | |
392 | } | ||
393 | } | ||
394 | |||
395 | // We do a first loop on all the points considering only the first component. | ||
396 | // The idea is that we need to build a sort of index for the points and it is not easy to do it | ||
397 | // since the point class does not work very well as key-value for a std::unordered_map. | ||
398 | |||
399 | ✗ | felInt iUC0 = m_dofPtr->getNumGlobComp(iUnknown, /*iComp*/0); | |
400 | |||
401 | // The idea is that for all the components we will loop over the labels and their points in the same way. | ||
402 | // When looping for the first component we associate an incremental index (cPointUnique) to the points | ||
403 | // that we find. If passing to a different label we find the same point twice we are able to tell it since, | ||
404 | // for the same component the point will be associated to the same degreeOfFreedom. | ||
405 | // The list of already found deegreesOfFreedom is saved in a std::set (alreadyFound). | ||
406 | // For each point we come across either we put the cPointUnique index in the std::vector idForiUC0 | ||
407 | // or we put (-1) if the point was already found in a different label. | ||
408 | ✗ | int cPointUnique(0); | |
409 | ✗ | std::set<int> alreadyFound; | |
410 | ✗ | std::vector<int> idForiUC0; | |
411 | |||
412 | // For each label | ||
413 | ✗ | for ( auto itLabel = m_listOfBoundaryPetscDofs.at(iUC0).begin(); itLabel != m_listOfBoundaryPetscDofs.at(iUC0).end(); ++itLabel) { | |
414 | // Point index label-based | ||
415 | ✗ | int cpoint(0); | |
416 | // for each point | ||
417 | ✗ | for ( auto itDof = itLabel->second.begin(); itDof != itLabel->second.end(); ++itDof) { | |
418 | ✗ | FEL_ASSERT(cpoint==itDof->first); | |
419 | // We insert the dof id in the list | ||
420 | ✗ | auto ret = alreadyFound.insert(m_petscVolume2Glob.at(itDof->second)); | |
421 | // We check if we already found this dof. | ||
422 | ✗ | if ( !ret.second ) { | |
423 | // In this case we do nothing | ||
424 | // and we add a minus one to idForiUC0 | ||
425 | ✗ | idForiUC0.push_back(-1); | |
426 | } else { | ||
427 | // In case of a new point | ||
428 | // we add the point index | ||
429 | ✗ | idForiUC0.push_back(cPointUnique); | |
430 | ✗ | cPointUnique++; | |
431 | // we save the point | ||
432 | ✗ | points.push_back(m_mapLab2AllPoints.find(itLabel->first)->second[cpoint]); | |
433 | // ...the label | ||
434 | ✗ | labels.push_back(itLabel->first); | |
435 | // ...and the dof id | ||
436 | ✗ | std::vector<int> tmp; | |
437 | ✗ | tmp.push_back(m_petscVolume2Glob.at(itDof->second)); | |
438 | ✗ | ids.push_back(tmp); | |
439 | } | ||
440 | //increase the index label-based | ||
441 | ✗ | cpoint++; | |
442 | } | ||
443 | } | ||
444 | |||
445 | // Now we are ready for a second round: | ||
446 | // if there are more components to interpolate | ||
447 | // we loop again in the same way as we just did for the first component | ||
448 | |||
449 | ✗ | for ( felInt iComp(1); iComp<numComp; ++iComp) { | |
450 | // This counter will be used to acces idForiUC0 and either extract -1 | ||
451 | // or extract the cPointUnique index. | ||
452 | ✗ | int count(0); | |
453 | ✗ | std::size_t iUC=m_dofPtr->getNumGlobComp(iUnknown, iComp); | |
454 | // for each label | ||
455 | ✗ | for ( auto itLabel = m_listOfBoundaryPetscDofs.at(iUC).begin(); itLabel != m_listOfBoundaryPetscDofs.at(iUC).end(); ++itLabel) { | |
456 | // counter label-based | ||
457 | ✗ | int cpoint=0; | |
458 | // loop over the points of this label | ||
459 | ✗ | for ( auto itDof = itLabel->second.begin(); itDof != itLabel->second.end(); ++itDof) { | |
460 | // verify if we have to skip this point | ||
461 | ✗ | if ( idForiUC0[count] >= 0 ) { | |
462 | // insert the dof id of the current component | ||
463 | ✗ | ids[idForiUC0[count]].push_back(m_petscVolume2Glob.at(itDof->second)); | |
464 | ✗ | FEL_ASSERT(Tools::equalTol(points[idForiUC0[count]].x(),m_mapLab2AllPoints.find(itLabel->first)->second[cpoint].x(),1e-16)); | |
465 | ✗ | FEL_ASSERT(Tools::equalTol(points[idForiUC0[count]].y(),m_mapLab2AllPoints.find(itLabel->first)->second[cpoint].y(),1e-16)); | |
466 | ✗ | FEL_ASSERT(Tools::equalTol(points[idForiUC0[count]].z(),m_mapLab2AllPoints.find(itLabel->first)->second[cpoint].z(),1e-16)); | |
467 | } | ||
468 | ✗ | count++; | |
469 | ✗ | cpoint++; | |
470 | } | ||
471 | } | ||
472 | } | ||
473 | // Opening the file | ||
474 | ✗ | std::stringstream filenameFull,cmd; | |
475 | ✗ | cmd<<"mkdir -p "<<folder; | |
476 | ✗ | int ierr = system(cmd.str().c_str()); | |
477 | ✗ | if (ierr>0) FEL_ERROR("error in execution of " + cmd.str() ); | |
478 | ✗ | filenameFull<<folder <<"/"<< filename; | |
479 | ✗ | std::ofstream surfaceInterpolatorFile; | |
480 | ✗ | surfaceInterpolatorFile.open(filenameFull.str().c_str()); | |
481 | ✗ | if ( ! surfaceInterpolatorFile.is_open() ) FEL_ERROR("not able to open the file"); | |
482 | |||
483 | // Writing the file | ||
484 | ✗ | surfaceInterpolatorFile<<points.size()<<std::endl; | |
485 | ✗ | for ( std::size_t curPoint(0); curPoint<points.size(); ++curPoint) { | |
486 | ✗ | surfaceInterpolatorFile<<numComp<<" "<<points[curPoint].x()<<" "<<points[curPoint].y()<<" "<<points[curPoint].z()<<" "; | |
487 | ✗ | surfaceInterpolatorFile<<labels[curPoint]<<" "; | |
488 | ✗ | FEL_ASSERT((std::size_t)numComp==ids[curPoint].size()); | |
489 | ✗ | for(auto it=ids[curPoint].begin(); it!= ids[curPoint].end(); it++) { | |
490 | ✗ | surfaceInterpolatorFile<<*it<<" "; | |
491 | } | ||
492 | ✗ | surfaceInterpolatorFile<<std::endl; | |
493 | } | ||
494 | ✗ | surfaceInterpolatorFile.close(); | |
495 | } | ||
496 | |||
497 | /***********************************************************************************/ | ||
498 | /***********************************************************************************/ | ||
499 | |||
500 | 1 | void DofBoundary::exportInterfacePoints(int iUnknown, int iComp) const { | |
501 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | std::size_t iUC=m_dofPtr->getNumGlobComp(iUnknown, iComp); |
502 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
|
1 | if ( iUC >= m_dofsHaveBeenComputed.size() || !m_dofsHaveBeenComputed[iUC] ) { |
503 | ✗ | std::stringstream msg; | |
504 | ✗ | msg<<"trying to export points for iUnknown: "<<iUnknown<<" and iComp: "<<iComp<<std::endl; | |
505 | ✗ | FEL_ERROR(msg.str().c_str()); | |
506 | } | ||
507 | /*! a matlab file "interface.m" is written into the result folder | ||
508 | to import it is enough to run such file in a matlab shell | ||
509 | it will create a matrix called "interfacePoints" with | ||
510 | three columns and a row for each point | ||
511 | the order of the point is the order of the application | ||
512 | */ | ||
513 | 1 | std::unordered_map<int,Point> id2Point; | |
514 |
4/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 1 times.
|
2 | for(auto itLabel = m_listOfBoundaryPetscDofs.at(iUC).begin(); itLabel != m_listOfBoundaryPetscDofs.at(iUC).end(); ++itLabel) { |
515 | 1 | int cpoint(0); | |
516 |
2/2✓ Branch 5 taken 81 times.
✓ Branch 6 taken 1 times.
|
82 | for(auto itDof = itLabel->second.begin(); itDof != itLabel->second.end(); ++itDof) { |
517 |
2/4✓ Branch 2 taken 81 times.
✗ Branch 3 not taken.
✓ Branch 8 taken 81 times.
✗ Branch 9 not taken.
|
81 | id2Point[itDof->second]=m_mapLab2AllPoints.find(itLabel->first)->second[cpoint]; |
518 |
2/4✓ Branch 1 taken 81 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 81 times.
|
81 | if ( FelisceParam::verbose() > 2 ) |
519 | ✗ | std::cout<<" id: "<<itDof->second<<" point "<<m_mapLab2AllPoints.find(itLabel->first)->second[cpoint]<<std::endl; | |
520 | 81 | cpoint++; | |
521 | } | ||
522 | } | ||
523 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | std::stringstream filename,cmd; |
524 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
1 | cmd<<"mkdir -p "<<FelisceParam::instance().resultDir; |
525 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
1 | int ierr = system(cmd.str().c_str()); |
526 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ierr>0) { |
527 | ✗ | FEL_ERROR("error in execution of " + cmd.str() ); | |
528 | } | ||
529 | |||
530 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
1 | filename<< FelisceParam::instance().resultDir << "interface.m"; |
531 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | std::ofstream interfaceFile; |
532 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
1 | interfaceFile.open(filename.str().c_str()); |
533 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
|
1 | if ( ! interfaceFile.is_open() ) |
534 | ✗ | FEL_ERROR("not able to open the file"); | |
535 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | interfaceFile<<"interfacePoints = [ "; |
536 |
2/2✓ Branch 0 taken 81 times.
✓ Branch 1 taken 1 times.
|
82 | for ( int i(0); i<m_numGlobalDofInterface; ++i) { |
537 |
2/4✓ Branch 2 taken 81 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 81 times.
✗ Branch 5 not taken.
|
81 | if ( id2Point.count(m_glob2PetscVolume[i]) > 0 ) { |
538 |
2/4✓ Branch 1 taken 81 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 81 times.
|
81 | if ( FelisceParam::verbose() > 2 ) |
539 | ✗ | std::cout<<" id2: "<<m_glob2PetscVolume[i]<<" point "<<id2Point[m_glob2PetscVolume[i]]<<std::endl; | |
540 |
1/2✓ Branch 2 taken 81 times.
✗ Branch 3 not taken.
|
81 | Point P=id2Point[m_glob2PetscVolume[i]]; |
541 |
6/12✓ Branch 2 taken 81 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 81 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 81 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 81 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 81 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 81 times.
✗ Branch 20 not taken.
|
81 | interfaceFile<<P.x()<<" , "<<P.y()<<" , "<<P.z()<<" ; "; |
542 | } | ||
543 | } | ||
544 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | interfaceFile<<"];"<<std::endl; |
545 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | interfaceFile.close(); |
546 | 1 | } | |
547 | |||
548 | // for compatibility with previous definition of buildBoundaryVolumeMapping, but also | ||
549 | // to have a better code in the linear problems: | ||
550 | 4 | void DofBoundary::buildBoundaryVolumeMapping( int iUnknown, int iComponent ) { | |
551 |
2/4✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
|
4 | this->buildBoundaryVolumeMapping( iUnknown, std::vector<int>(1,iComponent) ); |
552 | 4 | } | |
553 | |||
554 | // One mapping at the time is allowed | ||
555 | // it means that you choose an unknown and a (std::set of) component and you create a mapping! | ||
556 | // for instance in Navier Stokes you can build mapping between the ?whole? volume problem ( vel x 3 + pre ) and | ||
557 | // one component of the velocity OR the pressure on the interface. | ||
558 | 4 | void DofBoundary::buildBoundaryVolumeMapping( int iUnknown, std::vector<int> components ) { | |
559 | |||
560 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if ( m_volumeInterfaceMappingBuilt ) { |
561 | #ifndef NDEBUG | ||
562 | ✗ | std::stringstream msg; | |
563 | ✗ | msg<<"trying to call builBoundaryVolumeMapping again with iUnknwon: "<<iUnknown<<" and component(s): "; | |
564 | ✗ | for(auto itComponent=components.begin(); itComponent!=components.end(); ++itComponent) { | |
565 | ✗ | msg<<*itComponent<<" "; | |
566 | } | ||
567 | ✗ | msg<<std::endl; | |
568 | ✗ | FEL_WARNING(msg.str().c_str()); | |
569 | #endif | ||
570 | |||
571 | ✗ | return; | |
572 | } | ||
573 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if ( ! m_dofBoundaryHasBeenInitialized ) |
574 | ✗ | FEL_ERROR("dof boundary not yet initialized"); | |
575 | 4 | m_volumeInterfaceMappingBuilt=true; | |
576 | |||
577 | 4 | std::set<int> setGlobVolPetscIds; | |
578 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
|
8 | for (std::size_t idComponent(0); idComponent<components.size(); ++idComponent) { |
579 | 4 | int iComponent = components[idComponent]; | |
580 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | int iUnknComp = m_dofPtr->getNumGlobComp(iUnknown, iComponent); |
581 | |||
582 | // we check some basic assumptions | ||
583 |
2/8✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
4 | FEL_CHECK( m_listOfBoundaryPetscDofs[iUnknComp].size() > 0, "not even one label stored in m_listOfBoundaryPetscDofs" ); |
584 |
2/8✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
4 | FEL_CHECK( m_listOfBoundaryPetscDofs[iUnknComp].begin()->second.size() > 0, "the first label stored in the std::unordered_map is empty" ); |
585 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
|
4 | if ( FelisceParam::verbose() > 2) { |
586 | ✗ | PetscPrintf( MpiInfo::petscComm(), "Starting creation of all the mappings to define petsc objects in the interface\n"); | |
587 | } | ||
588 | |||
589 | // =========================================================== | ||
590 | // the global volume petsc ids are stored in the m_listOfBoundaryPetscDofs | ||
591 | // container depending on their label, therefore some of those | ||
592 | // ids could be repeted if they are at the interface | ||
593 | // between different labels | ||
594 | // we "gather" all the ids in one std::set to destroy | ||
595 | // duplicates and to sort them | ||
596 |
4/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 4 times.
✓ Branch 11 taken 4 times.
|
8 | for(auto itLabel = m_listOfBoundaryPetscDofs[iUnknComp].begin(); itLabel != m_listOfBoundaryPetscDofs[iUnknComp].end(); ++itLabel) { |
597 |
2/2✓ Branch 6 taken 324 times.
✓ Branch 7 taken 4 times.
|
328 | for(auto itDof = itLabel->second.begin(); itDof != itLabel->second.end(); ++itDof) { |
598 |
1/2✓ Branch 2 taken 324 times.
✗ Branch 3 not taken.
|
324 | setGlobVolPetscIds.insert(itDof->second); |
599 | } | ||
600 | } | ||
601 | } | ||
602 | // =========================================================== | ||
603 | // m_glob2PetscVolume = | ||
604 | // =========================================================== | ||
605 | // TODO: this is simply a copy of the std::set into a std::vector, there is for sure a better way of doing it. | ||
606 | // we allocate the std::unordered_map | ||
607 | // applicationInterface2PetscVol (m_glob2PetscVolume), actually it is a std::vector of integers and | ||
608 | // it maps: | ||
609 | // ( 0 , m_numGlobalDofInterface - 1) --> (???) \in global volume petsc ids | ||
610 | // so that from the global interface application id you can get the global volume petsc id | ||
611 |
2/2✓ Branch 4 taken 324 times.
✓ Branch 5 taken 4 times.
|
328 | for(auto itDof = setGlobVolPetscIds.begin(); itDof != setGlobVolPetscIds.end(); ++itDof) { |
612 |
1/2✓ Branch 2 taken 324 times.
✗ Branch 3 not taken.
|
324 | m_glob2PetscVolume.push_back(*itDof); // global petsc volume id = m_glob2PetscVolume[global application interface id] |
613 | } | ||
614 | 4 | setGlobVolPetscIds.clear(); | |
615 | 4 | m_numGlobalDofInterface = m_glob2PetscVolume.size(); | |
616 | |||
617 | |||
618 | // =========================================================== | ||
619 | // m_petscVolume2Glob = | ||
620 | // =========================================================== | ||
621 | 4 | int cpoint=0; | |
622 |
2/2✓ Branch 3 taken 324 times.
✓ Branch 4 taken 4 times.
|
328 | for(auto petscVolId=m_glob2PetscVolume.begin(); petscVolId != m_glob2PetscVolume.end(); ++petscVolId, ++cpoint) { |
623 | 324 | int aus( *petscVolId ); | |
624 |
1/2✓ Branch 1 taken 324 times.
✗ Branch 2 not taken.
|
324 | m_petscVolume2Glob[ aus ] = cpoint; |
625 | } | ||
626 | |||
627 | // ============================================================== | ||
628 | // m_loc2GlobInterface & m_loc2PetscVolume = | ||
629 | // ============================================================== | ||
630 | // Here we create the std::vector, | ||
631 | // local to the proc, that contains the global application | ||
632 | // ids of the dof at the interface, i.e, | ||
633 | // m_loc2GlobInterface: | ||
634 | // ( 0 , m_numLocalDofInterface - 1 ) --> ( 0 , m_numGlobalDofInterface - 1 ) | ||
635 | // we create an auxiliary std::vector initialized with the global | ||
636 | // volume petsc ids and then we use m_ao | ||
637 | // to replace those values with global colume application ids | ||
638 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | std::vector<felInt> applicationIdsVolume(m_glob2PetscVolume); |
639 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | AOPetscToApplication(m_ao,m_numGlobalDofInterface,&applicationIdsVolume[0]); |
640 | // this is done because we want to check if those dofs belong | ||
641 | // to this proc or not and the std::vector m_dofPart | ||
642 | // is defined on the global volume application ids not the petsc ids | ||
643 | // at the same time we define a variable startCounter | ||
644 | // which is equal to the number of dofs in the processors | ||
645 | // with a lower rank than the current | ||
646 | // it is zero for the proc 0 | ||
647 | // and it should be numGlob-numLoc-1 for the last proc | ||
648 | 4 | felInt startCounter(0); | |
649 |
2/2✓ Branch 0 taken 324 times.
✓ Branch 1 taken 4 times.
|
328 | for ( felInt iGlobDof(0); iGlobDof < m_numGlobalDofInterface; ++iGlobDof ) { |
650 | 324 | felInt dofProc( (*m_dofPartPtr)[ applicationIdsVolume[iGlobDof] ]); | |
651 |
3/4✓ Branch 1 taken 324 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 81 times.
✓ Branch 4 taken 243 times.
|
324 | if ( dofProc == MpiInfo::rankProc() ) { |
652 |
1/2✓ Branch 1 taken 81 times.
✗ Branch 2 not taken.
|
81 | m_loc2GlobInterface.push_back(iGlobDof); |
653 | } | ||
654 |
3/4✓ Branch 1 taken 324 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 105 times.
✓ Branch 4 taken 219 times.
|
324 | if ( dofProc < MpiInfo::rankProc() ) { |
655 | 105 | ++startCounter; | |
656 | } | ||
657 | } | ||
658 | 4 | applicationIdsVolume.clear(); | |
659 | 4 | m_numLocalDofInterface = m_loc2GlobInterface.size(); | |
660 |
2/2✓ Branch 4 taken 81 times.
✓ Branch 5 taken 4 times.
|
85 | for(auto iLocDof = m_loc2GlobInterface.begin(); iLocDof != m_loc2GlobInterface.end(); ++iLocDof ) { |
661 |
1/2✓ Branch 3 taken 81 times.
✗ Branch 4 not taken.
|
81 | m_loc2PetscVolume.push_back(m_glob2PetscVolume[*iLocDof]); |
662 | } | ||
663 | |||
664 |
4/8✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
|
4 | MPI_Comm_split(MpiInfo::petscComm(), ( m_numLocalDofInterface > 0 ) ? 1 : 0, MpiInfo::rankProc(), &m_boundaryComm); |
665 | int rankB,sizeB; | ||
666 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | MPI_Comm_rank(m_boundaryComm, &rankB); |
667 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | MPI_Comm_size(m_boundaryComm, &sizeB); |
668 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
|
4 | if (FelisceParam::verbose()>2) |
669 | ✗ | std::cout<<"["<<MpiInfo::rankProc()<<"] "<<"rank on the boarder "<< rankB << " size of this group " << sizeB << std::endl; | |
670 | |||
671 | // ============================================================== | ||
672 | // m_aoInterface = | ||
673 | // ============================================================== | ||
674 | // we create the std::vector petscIds | ||
675 | // which contains ( startCounter, startCounter + 1, ..., startCounter + numLocDof -1 ) | ||
676 | 4 | std::vector<felInt> petscIds; | |
677 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | petscIds.reserve(m_numLocalDofInterface); |
678 | |||
679 |
2/2✓ Branch 0 taken 81 times.
✓ Branch 1 taken 4 times.
|
85 | for ( felInt iLocDof(0); iLocDof<m_numLocalDofInterface; ++iLocDof ) { |
680 |
1/2✓ Branch 1 taken 81 times.
✗ Branch 2 not taken.
|
81 | petscIds.push_back(startCounter + iLocDof); |
681 | } | ||
682 | // we build m_aoInterface | ||
683 | // this will allow you to move from the global petsc ordering defined in petscIds and | ||
684 | // the global application ordering. | ||
685 | // consider that in serial this is the identity mapping | ||
686 | // but in parallel nodes are contiguous in petsc ordering | ||
687 |
1/2✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
4 | AOCreateBasic(m_boundaryComm, m_numLocalDofInterface, &m_loc2GlobInterface[0], &petscIds[0], &m_aoInterface); |
688 | 4 | petscIds.clear(); | |
689 | |||
690 | |||
691 | // ============================================================== | ||
692 | // m_loc2PetscInterface = | ||
693 | // ============================================================== | ||
694 | // from local index, directly to the petsc index of the interface | ||
695 |
2/2✓ Branch 0 taken 81 times.
✓ Branch 1 taken 4 times.
|
85 | for ( felInt iDofInterface(0); iDofInterface < m_numLocalDofInterface; ++iDofInterface) { |
696 |
1/2✓ Branch 2 taken 81 times.
✗ Branch 3 not taken.
|
81 | m_loc2PetscInterface.push_back(m_loc2GlobInterface[iDofInterface]); |
697 | } | ||
698 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | AOApplicationToPetsc(m_aoInterface,m_numLocalDofInterface,&m_loc2PetscInterface[0]); |
699 | |||
700 | // bool m_exportInterface=true; | ||
701 | // if ( m_exportInterface ) { | ||
702 |
3/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 3 times.
|
4 | if ( MpiInfo::rankProc() == 0 ) { |
703 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | this->exportInterfacePoints( iUnknown, components[0] );//we export the points only for the first component. |
704 | } | ||
705 | // } | ||
706 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
|
4 | if ( FelisceParam::verbose() > 2 ) { |
707 | ✗ | displayBoundaryVolumeMapping(); | |
708 | } | ||
709 | 4 | } | |
710 | |||
711 | /*! \brief post-process function used in the examples | ||
712 | It writes a readable file to be plot in python. | ||
713 | */ | ||
714 | ✗ | void DofBoundary::BoundaryVolumeMappingForExample() const { | |
715 | ✗ | if ( ! m_volumeInterfaceMappingBuilt ) | |
716 | ✗ | FEL_ERROR("volume interface mapping not yet build"); | |
717 | |||
718 | //! The master processor start to write: | ||
719 | ✗ | if ( MpiInfo::rankProc() == 0 ) { | |
720 | //! a file BVMapping.dat is opened | ||
721 | ✗ | std::stringstream cmd; | |
722 | ✗ | cmd<<"mkdir -p "<<FelisceParam::instance().resultDir; | |
723 | ✗ | int ierr = system( cmd.str().c_str() ); | |
724 | ✗ | if (ierr>0) { | |
725 | ✗ | FEL_ERROR("error in execution of " + cmd.str() ); | |
726 | } | ||
727 | ✗ | std::stringstream filename; | |
728 | ✗ | filename << FelisceParam::instance().resultDir << "BVMapping.dat"; | |
729 | |||
730 | ✗ | std::ofstream outFile; | |
731 | ✗ | outFile.open(filename.str().c_str()); | |
732 | //! we write the header of the first part | ||
733 | ✗ | outFile<<"# Total Number of Processors"<<std::endl; | |
734 | ✗ | outFile<<MpiInfo::numProc()<<std::endl; | |
735 | ✗ | outFile<<"# Number of boundary dofs"<<std::endl; | |
736 | ✗ | outFile<<m_numGlobalDofInterface<<std::endl; | |
737 | |||
738 | // for each id we get the corresponding point //TODO create a function for that. | ||
739 | ✗ | const std::size_t iUC=m_dofPtr->getNumGlobComp(1, 0);//TODO | |
740 | ✗ | std::unordered_map<int,Point> id2Point; | |
741 | ✗ | for(auto itLabel = m_listOfBoundaryPetscDofs.at(iUC).begin(); itLabel != m_listOfBoundaryPetscDofs.at(iUC).end(); ++itLabel) { | |
742 | ✗ | int cpoint(0); | |
743 | ✗ | for(auto itDof = itLabel->second.begin(); itDof != itLabel->second.end(); ++itDof) { | |
744 | ✗ | id2Point[itDof->second]=m_mapLab2AllPoints.find(itLabel->first)->second[cpoint]; | |
745 | ✗ | cpoint++; | |
746 | } | ||
747 | } | ||
748 | |||
749 | // a second line for humans | ||
750 | //! We write a table like this: | ||
751 | //! PointsCoordinate, boundaryApplicationOrdering (BAO), boundaryPetscOrdering (BPO), volumePetscOrdering (VPO), volumeApplicationOrdering (VAO) | ||
752 | ✗ | outFile<<"# PointsCoordinate, boundaryApplicationOrdering (BAO), boundaryPetscOrdering (BPO), volumePetscOrdering (VPO), volumeApplicationOrdering (VAO)"<<std::endl; | |
753 | ✗ | for ( int cPoint(0); cPoint < m_numGlobalDofInterface; ++cPoint ) { | |
754 | ✗ | Point P=id2Point[m_glob2PetscVolume[cPoint]]; | |
755 | ✗ | felInt BPO=cPoint; AOApplicationToPetsc( m_aoInterface, 1, &BPO ); | |
756 | ✗ | felInt VAO=m_glob2PetscVolume[cPoint]; AOPetscToApplication( m_ao, 1, &VAO); | |
757 | outFile | ||
758 | ✗ | << P.x() <<" , " | |
759 | ✗ | << P.y() <<" , " | |
760 | ✗ | << P.z() <<" , " | |
761 | ✗ | << cPoint <<" , " | |
762 | ✗ | << BPO <<" , " | |
763 | ✗ | << m_glob2PetscVolume[cPoint] <<" , " | |
764 | ✗ | << VAO << std::endl; | |
765 | } | ||
766 | ✗ | outFile.close(); | |
767 | } | ||
768 | } | ||
769 | |||
770 | /***********************************************************************************/ | ||
771 | /***********************************************************************************/ | ||
772 | |||
773 | ✗ | void DofBoundary::displayBoundaryVolumeMapping() const { | |
774 | ✗ | if ( ! m_volumeInterfaceMappingBuilt ) | |
775 | ✗ | FEL_ERROR("volume interface mapping not yet build"); | |
776 | ✗ | const int N(25); // used only for printing information in debug | |
777 | typedef std::stringstream aStream; | ||
778 | ✗ | aStream master; | |
779 | ✗ | master << "m_glob2PetscVolume maps the global indeces in the application ordering (0,...," << m_numGlobalDofInterface-1 <<")" << std::endl; | |
780 | ✗ | master << " to the corresponding indeces of the volume in the petsc ordering (" << m_glob2PetscVolume[0]<<",...,"<<m_glob2PetscVolume[m_numGlobalDofInterface-1]<<")"<<std::endl; | |
781 | ✗ | PetscPrintf( MpiInfo::petscComm(), "%s",master.str().c_str() ); | |
782 | ✗ | MPI_Barrier(MpiInfo::petscComm()); | |
783 | ✗ | if ( FelisceParam::verbose() > 3) { | |
784 | ✗ | aStream lineOne, lineTwo; | |
785 | ✗ | lineOne<<"The first "<<N<<" mapped dofs being: "<<std::endl; | |
786 | ✗ | for ( int ii(0); ii < N && ii < m_numGlobalDofInterface; ++ii) { | |
787 | ✗ | lineOne << ii << '\t' ; | |
788 | ✗ | lineTwo << m_glob2PetscVolume[ii] << '\t' ; | |
789 | } | ||
790 | ✗ | lineOne << std::endl; | |
791 | ✗ | lineTwo << std::endl; | |
792 | ✗ | PetscPrintf( MpiInfo::petscComm(), "%s",lineOne.str().c_str() ); | |
793 | ✗ | MPI_Barrier(MpiInfo::petscComm()); | |
794 | ✗ | PetscPrintf( MpiInfo::petscComm(), "%s",lineTwo.str().c_str() ); | |
795 | ✗ | MPI_Barrier(MpiInfo::petscComm()); | |
796 | } | ||
797 | ✗ | master.str(""); | |
798 | ✗ | master.clear(); | |
799 | ✗ | master<<"Number of local dof (for each proc) on the interface is ... "<<std::endl; | |
800 | ✗ | PetscPrintf(MpiInfo::petscComm(),"%s", master.str().c_str()); | |
801 | ✗ | MPI_Barrier(MpiInfo::petscComm()); | |
802 | ✗ | std::cout<<"["<<MpiInfo::rankProc()<<"] numLoc ("<<m_numLocalDofInterface<<"/"<<m_numGlobalDofInterface<<") (local/global)"<<std::endl; | |
803 | ✗ | MPI_Barrier(MpiInfo::petscComm()); | |
804 | ✗ | master.str(""); | |
805 | ✗ | master.clear(); | |
806 | ✗ | master<<"m_loc2GlobInterface let you go from local indexing to global ids in the application ordering"<<std::endl; | |
807 | ✗ | master<<"---------info are displayed only for the last proc------------"<<std::endl; | |
808 | ✗ | PetscPrintf( MpiInfo::petscComm(),"%s", master.str().c_str() ); | |
809 | ✗ | MPI_Barrier(MpiInfo::petscComm()); | |
810 | ✗ | if ( MpiInfo::rankProc() == MpiInfo::numProc() - 1) { | |
811 | ✗ | std::cout<<"-----------["<<MpiInfo::rankProc()<<"] mapping from local (0,...,"<<m_numLocalDofInterface-1<<")"<<std::endl; | |
812 | ✗ | std::cout<<"-----------["<<MpiInfo::rankProc()<<"] The first "<< ( (N<m_numLocalDofInterface) ? N : m_numLocalDofInterface ) <<" being: "<<std::endl; | |
813 | ✗ | std::cout<<"-----------["<<MpiInfo::rankProc()<<"] "; | |
814 | ✗ | for ( int ii(0); ii<N && ii<m_numLocalDofInterface; ++ii ) { | |
815 | ✗ | std::cout<<ii<<'\t'; | |
816 | } | ||
817 | ✗ | std::cout<<std::endl; | |
818 | ✗ | std::cout<<"-----------["<<MpiInfo::rankProc()<<"] "; | |
819 | ✗ | for ( int ii(0); ii<N && ii<m_numLocalDofInterface; ++ii ) { | |
820 | ✗ | std::cout<<m_loc2GlobInterface[ii]<<'\t'; | |
821 | } | ||
822 | ✗ | std::cout<<std::endl; | |
823 | } | ||
824 | ✗ | MPI_Barrier(MpiInfo::petscComm()); | |
825 | ✗ | master.str(""); | |
826 | ✗ | master.clear(); | |
827 | ✗ | master<<"m_loc2PetscVolume let you go from local indexing to global ids in the volume petsc ordering"<<std::endl; | |
828 | ✗ | master<<"---------info are displayed only for the last proc------------"<<std::endl; | |
829 | ✗ | PetscPrintf( MpiInfo::petscComm(),"%s", master.str().c_str() ); | |
830 | ✗ | MPI_Barrier(MpiInfo::petscComm()); | |
831 | ✗ | if ( MpiInfo::rankProc() == MpiInfo::numProc() -1 ) { | |
832 | ✗ | std::cout<<"-----------["<<MpiInfo::rankProc()<<"] mapping from local (0,...,"<<m_numLocalDofInterface-1<<")"<<std::endl; | |
833 | ✗ | std::cout<<"-----------["<<MpiInfo::rankProc()<<"] The first "<<( ( N < m_numLocalDofInterface )?N:m_numLocalDofInterface)<<" being: "<<std::endl; | |
834 | ✗ | std::cout<<"-----------["<<MpiInfo::rankProc()<<"] "; | |
835 | ✗ | for ( int ii(0); ii<N && ii<m_numLocalDofInterface; ++ii ) { | |
836 | ✗ | std::cout<<ii<<'\t'; | |
837 | } | ||
838 | ✗ | std::cout<<std::endl; | |
839 | ✗ | std::cout<<"-----------["<<MpiInfo::rankProc()<<"] "; | |
840 | ✗ | for ( int ii(0); ii<N && ii<m_numLocalDofInterface; ++ii ) { | |
841 | ✗ | std::cout<<m_loc2PetscVolume[ii]<<'\t'; | |
842 | } | ||
843 | ✗ | std::cout<<std::endl; | |
844 | } | ||
845 | ✗ | MPI_Barrier(MpiInfo::petscComm()); | |
846 | ✗ | if ( FelisceParam::verbose() > 2 ) { | |
847 | ✗ | master.str(""); | |
848 | ✗ | master.clear(); | |
849 | ✗ | master<<" m_aoInterface "<<std::endl; | |
850 | ✗ | PetscPrintf(MpiInfo::petscComm(), "%s",master.str().c_str()); | |
851 | ✗ | MPI_Barrier(MpiInfo::petscComm()); | |
852 | ✗ | AOView(m_aoInterface,PETSC_VIEWER_STDOUT_WORLD); | |
853 | } | ||
854 | ✗ | master.str(""); | |
855 | ✗ | master.clear(); | |
856 | ✗ | master<<"m_loc2PetscInterface let you go from local indexing to global indexing petsc ordering"<<std::endl; | |
857 | ✗ | PetscPrintf( MpiInfo::petscComm(), "%s",master.str().c_str() ); | |
858 | ✗ | MPI_Barrier(MpiInfo::petscComm()); | |
859 | ✗ | if ( FelisceParam::verbose() > 2 ) { | |
860 | ✗ | master.str(""); | |
861 | ✗ | master.clear(); | |
862 | ✗ | master<<"----------info are displayed only for the last proc"<<std::endl; | |
863 | ✗ | PetscPrintf( MpiInfo::petscComm(), "%s",master.str().c_str() ); | |
864 | ✗ | MPI_Barrier(MpiInfo::petscComm()); | |
865 | ✗ | if ( MpiInfo::rankProc() == MpiInfo::numProc() - 1 ) { | |
866 | ✗ | std::cout<<"-----------["<<MpiInfo::rankProc()<<"] mapping from local (0,...,"<<m_numLocalDofInterface-1<<")"<<std::endl; | |
867 | ✗ | std::cout<<"-----------["<<MpiInfo::rankProc()<<"] The first "<<( ( N < m_numLocalDofInterface )?N:m_numLocalDofInterface )<<" being: "<<std::endl; | |
868 | ✗ | std::cout<<"-----------["<<MpiInfo::rankProc()<<"] "; | |
869 | ✗ | for ( int ii(0); ii<N && ii<m_numLocalDofInterface; ++ii ) { | |
870 | ✗ | std::cout<<ii<<'\t'; | |
871 | } | ||
872 | ✗ | std::cout<<std::endl; | |
873 | ✗ | std::cout<<"-----------["<<MpiInfo::rankProc()<<"] "; | |
874 | ✗ | for ( int ii(0); ii<N && ii<m_numLocalDofInterface; ++ii ) { | |
875 | ✗ | std::cout<<m_loc2PetscInterface[ii]<<'\t'; | |
876 | } | ||
877 | ✗ | std::cout<<std::endl; | |
878 | } | ||
879 | ✗ | MPI_Barrier(MpiInfo::petscComm()); | |
880 | } | ||
881 | } | ||
882 | |||
883 | /***********************************************************************************/ | ||
884 | /***********************************************************************************/ | ||
885 | |||
886 | ✗ | void DofBoundary::unRoll( felInt iUnkComp ) { | |
887 | ✗ | if ( ! m_dofsHaveBeenComputed[iUnkComp] ) | |
888 | ✗ | FEL_ERROR("need to calculate those dofs"); | |
889 | ✗ | if ( m_unRolledList.size() <= std::size_t( iUnkComp ) ) { | |
890 | ✗ | m_unRolledList.resize(iUnkComp+1); | |
891 | } | ||
892 | ✗ | if ( m_unRolledList[iUnkComp].size() > 0 ) | |
893 | ✗ | return; | |
894 | else { | ||
895 | ✗ | for(auto it_label = m_listOfBoundaryPetscDofs[iUnkComp].begin(); it_label != m_listOfBoundaryPetscDofs[iUnkComp].end(); ++it_label ) { | |
896 | ✗ | for(auto it_point = it_label->second.begin(); it_point != it_label->second.end(); ++it_point) { | |
897 | ✗ | m_unRolledList[iUnkComp].insert( it_point->second ); | |
898 | } | ||
899 | } | ||
900 | } | ||
901 | } | ||
902 | |||
903 | /***********************************************************************************/ | ||
904 | /***********************************************************************************/ | ||
905 | |||
906 | ✗ | bool DofBoundary::isOnSurface( felInt iUnkComp, felInt petscDof ) { | |
907 | ✗ | if ( m_unRolledList.size() <= std::size_t( iUnkComp ) ) { | |
908 | ✗ | this->unRoll(iUnkComp); | |
909 | } | ||
910 | ✗ | if ( m_unRolledList[iUnkComp].size() == std::size_t(0) ) { | |
911 | ✗ | this->unRoll(iUnkComp); | |
912 | } | ||
913 | ✗ | auto it = m_unRolledList[iUnkComp].find( petscDof ); | |
914 | ✗ | return it != m_unRolledList[iUnkComp].end(); | |
915 | } | ||
916 | |||
917 | } | ||
918 |