1616
1717#include < algorithm>
1818#include < format>
19- #include < iostream>
2019
2120FOUR_C_NAMESPACE_OPEN
2221
@@ -75,6 +74,7 @@ void Core::DOFSets::DofSet::print(std::ostream& os) const
7574 {
7675 int numdf = (*numdfcolnodes_)[i];
7776 int idx = (*idxcolnodes_)[i];
77+
7878 os << i << " : " ;
7979 for (int j = 0 ; j < numdf; ++j) os << (idx + j) << " " ;
8080 os << " \n " ;
@@ -203,22 +203,23 @@ int Core::DOFSets::DofSet::assign_degrees_of_freedom(
203203 // ////////////////////////////////////////////////////////////////
204204 int maxnodenumdf = 0 ;
205205 int maxelementnumdf = 0 ;
206+ int numrownodes = dis.num_my_row_nodes ();
207+ int numrowelements = dis.num_my_row_elements ();
206208 std::map<int , std::vector<int >> nodedofset;
207- std::map<int , std::vector<int >> nodeduplicatedofset;
208209 std::map<int , std::vector<int >> elementdofset;
209210 std::map<int , std::vector<int >> facedofset;
211+ std::vector<int > localrowdofs;
210212
211213 {
212214 // get DoF coupling conditions
213215 std::vector<Core::Conditions::Condition*> couplingconditions (0 );
214216 dis.get_condition (" PointCoupling" , couplingconditions);
215- if (( int ) couplingconditions.size () > 0 ) pccdofhandling_ = true ;
217+ if (! couplingconditions.empty () ) pccdofhandling_ = true ;
216218
217219 // do the nodes first
218220 Core::LinAlg::Vector<int > num_dof_rownodes (*dis.node_row_map ());
219221 Core::LinAlg::Vector<int > idxrownodes (*dis.node_row_map ());
220222
221- int numrownodes = dis.num_my_row_nodes ();
222223 for (int i = 0 ; i < numrownodes; ++i)
223224 {
224225 Core::Nodes::Node* actnode = dis.l_row_node (i);
@@ -228,31 +229,21 @@ int Core::DOFSets::DofSet::assign_degrees_of_freedom(
228229 int minnodegid = get_minimal_node_gid_if_relevant (dis);
229230 maxnodenumdf = num_dof_rownodes.max_value ();
230231 get_reserved_max_num_dofper_node (maxnodenumdf); // XFEM::XFEMDofSet set to const number!
232+ localrowdofs.reserve (numrownodes * maxnodenumdf);
231233
232234 std::vector<std::vector<int >> onoffcond; // vector of onoff status for each condition
233235 std::vector<int > numdofcond; // vector of NUMDOF for each condition
234236 std::vector<std::vector<int >> nodeids; // vector of node IDs for each condition
235- std::vector<int > mgids; // vector of master node IDs for each condition
237+ std::vector<int > masterIds; // vector of master node IDs for each condition
236238
237- for (int k = 0 ; k < ( int ) couplingconditions. size (); ++k )
239+ for (const auto * condition : couplingconditions)
238240 {
239- onoffcond.push_back (couplingconditions[k]->parameters ().get <std::vector<int >>(" ONOFF" ));
240- numdofcond.push_back (couplingconditions[k]->parameters ().get <int >(" NUMDOF" ));
241- nodeids.push_back (*couplingconditions[k]->get_nodes ());
242- mgids.push_back (nodeids[k][0 ]);
243- std::cout << " Coupling condition " << k << " contains " << nodeids[k].size ()
244- << " nodes, master: " << mgids[k] << " \n " ;
245-
246- // check if all nodes in this condition are on same processor
247- // (otherwise throw a FOUR_C_THROW for now - not yet implemented)
248- bool allononeproc = true ;
249- for (auto nd : nodeids[k])
250- {
251- if (!dis.node_row_map ()->MyGID (nd)) allononeproc = false ;
252- }
253- if (!allononeproc)
254- FOUR_C_THROW (
255- " ERROR: Nodes in point coupling condition must all be on same processor (for now)" );
241+ onoffcond.push_back (condition->parameters ().get <std::vector<int >>(" ONOFF" ));
242+ numdofcond.push_back (condition->parameters ().get <int >(" NUMDOF" ));
243+ const auto conditioned_node_ids = condition->get_nodes ();
244+ nodeids.push_back (*conditioned_node_ids);
245+ // The first node ID of each condition serves as the master node:
246+ masterIds.push_back (*conditioned_node_ids->begin ());
256247 }
257248
258249 for (int i = 0 ; i < numrownodes; ++i)
@@ -267,119 +258,110 @@ int Core::DOFSets::DofSet::assign_degrees_of_freedom(
267258 std::vector<int > applied_condition (maxnodenumdf, -1 );
268259 if (dspos_ == 0 )
269260 {
270- for (int icond = 0 ; icond < ( int ) couplingconditions.size (); ++icond )
261+ for (size_t condition_id = 0 ; condition_id < couplingconditions.size (); ++condition_id )
271262 {
272- // check total number of dofs and determine which dofs are to be coupled
273- if (numdofcond[icond] != num_dof_rownodes[i])
274- FOUR_C_THROW (
275- " ERROR: Number of DoFs in coupling condition (%i) does not match node (%i)" ,
276- numdofcond[icond], num_dof_rownodes[i]);
277-
278- // check if the node i is contained in the coupling condition
279- auto found = std::find (nodeids[icond].begin (), nodeids[icond].end (), gid);
280- if (found != nodeids[icond].end ())
263+ // check if the node gid is contained in the coupling condition
264+ if (couplingconditions[condition_id]->contains_node (gid))
281265 {
282- for (int k_on = 0 ; k_on < ( int ) onoffcond[icond ].size (); ++k_on)
266+ for (size_t k_on = 0 ; k_on < onoffcond[condition_id ].size (); ++k_on)
283267 {
284- if (onoffcond[icond ][k_on] == 0 ) continue ;
268+ if (onoffcond[condition_id ][k_on] == 0 ) continue ;
285269 FOUR_C_ASSERT (applied_condition[k_on] == -1 ,
286270 " ERROR: Two coupling conditions on the same degree of freedom" );
287- applied_condition[k_on] = icond ;
271+ applied_condition[k_on] = condition_id ;
288272 }
289273 }
290274 }
291275 }
292- // check for node coupling condition and slave/master status
293- bool specialtreatment (false );
276+ // check if all nodes in this condition are on the same processor
277+ // (otherwise throw a FOUR_C_THROW for now - not yet implemented)
278+ bool allononeproc = true ;
294279
295- // for (int idim = 0; idim < (int)applied_condition.size(); ++idim);
296- if (*std::ranges::max_element (applied_condition.begin (), applied_condition.end ()) >= 0 )
280+ for (int k_on = 0 ; k_on < maxnodenumdf; ++k_on)
297281 {
298- // do nothing if the node is the master in all of the applied conditions
299- // do something for second, third, ... (slave) node
300- // also if the node is a master in one condition, but a slave in another
301- bool allmaster = true ;
302- for (auto condition_id : applied_condition)
282+ if (applied_condition[k_on] == -1 ) continue ;
283+ const int condition_id = applied_condition[k_on];
284+ const std::vector<int >* ndvec = couplingconditions[condition_id]->get_nodes ();
285+ for (const auto nd : *ndvec)
303286 {
304- if (condition_id == -1 ) continue ;
305- if (mgids[condition_id] != gid) allmaster = false ;
287+ if (!dis.node_row_map ()->MyGID (nd))
288+ {
289+ allononeproc = false ;
290+ std::cout << " Node " << nd << " (LID " << dis.node_row_map ()->LID (nd)
291+ << " ) in condition " << condition_id << " (" << k_on
292+ << " ) is not in the current row map!\n " ;
293+ }
306294 }
307- if (!allmaster)
295+ }
296+ if (!allononeproc)
297+ FOUR_C_THROW (
298+ " ERROR: Nodes in point coupling condition must all be on same processor (for now)." );
299+
300+ // check for node coupling condition and slave/master status
301+
302+ // do nothing if the node is the master in all of the applied conditions
303+ // do something for second, third, ... (slave) node
304+ // also if the node is a master in one condition, but a slave in another
305+ bool is_slave = false ;
306+ for (auto condition_id : applied_condition)
307+ {
308+ if (condition_id == -1 ) continue ;
309+ // check total number of dofs and determine which dofs are to be coupled
310+ if (numdofcond[condition_id] != num_dof_rownodes[i])
311+ FOUR_C_THROW (" ERROR: Number of DoFs in coupling condition {} does not match node {}" ,
312+ numdofcond[condition_id], num_dof_rownodes[i]);
313+ if (masterIds[condition_id] != gid) is_slave = true ;
314+ }
315+
316+ if (is_slave)
317+ { // in case it is a slave node (in some dof): the dof is cancelled, replaced by the master
318+ // dof
319+ int numdf = num_dof_rownodes[i];
320+ int dof = count + (gid - minnodegid) * maxnodenumdf;
321+ idxrownodes[i] = dof;
322+ std::vector<int >& dofs = nodedofset[gid];
323+ dofs.reserve (numdf);
324+ for (int j = 0 ; j < numdf; ++j)
308325 {
309- // critical case
310- specialtreatment = true ;
311-
312- // special treatment
313- int numdf = num_dof_rownodes[i];
314- int dof = count + (gid - minnodegid) * maxnodenumdf;
315- idxrownodes[i] = dof;
316- std::vector<int >& dofs = nodedofset[gid];
317- std::vector<int >& duplicatedofs = nodeduplicatedofset[gid];
318- dofs.reserve (numdf);
319- duplicatedofs.reserve (numdf);
320- for (int j = 0 ; j < numdf; ++j)
326+ // push back master node DoF ID if the id is coupled
327+ // it might be that the node is the master in one direction and a slave in another
328+ if (applied_condition[j] >= 0 && masterIds[applied_condition[j]] != gid)
321329 {
322- // push back master node DoF ID if the id is coupled
323- // it might be that the node is the master in one direction and a slave in another
324- if (applied_condition[j] >= 0 && mgids[applied_condition[j]] != gid)
325- {
326- std::vector<int >& mdofs = nodedofset[mgids[applied_condition[j]]];
327- dofs.push_back (mdofs[j]);
328- duplicatedofs.push_back (1 );
329- }
330- // push back new DoF ID if not coupled
331- else
332- {
333- dofs.push_back (dof + j);
334- duplicatedofs.push_back (0 );
335- }
330+ std::vector<int >& mdofs = nodedofset[masterIds[applied_condition[j]]];
331+ dofs.push_back (mdofs[j]);
332+ }
333+ // push back new DoF ID if not coupled
334+ else
335+ {
336+ dofs.push_back (dof + j);
337+ localrowdofs.push_back (dof + j);
336338 }
337339 }
338340 }
339-
341+ else
340342 // standard treatment for non-coupling nodes and master coupling nodes
341- if (!specialtreatment)
342343 {
343344 // now treat only the nodes, which are master and thus did not get the special treatment
344345 int numdf = num_dof_rownodes[i];
345346 int dof = count + (gid - minnodegid) * maxnodenumdf;
346347 idxrownodes[i] = dof;
347348 std::vector<int >& dofs = nodedofset[gid];
348- std::vector<int >& duplicatedofs = nodeduplicatedofset[gid];
349349 dofs.reserve (numdf);
350- duplicatedofs.reserve (numdf);
351350 for (int j = 0 ; j < numdf; ++j)
352351 {
353352 dofs.push_back (dof + j);
354- duplicatedofs .push_back (0 );
353+ localrowdofs .push_back (dof + j );
355354 }
356355 }
357356 // **********************************************************************
358357 // **********************************************************************
359358 // **********************************************************************
360359 // **********************************************************************
361- // std::cout << "Node ID " << gid << " - 0:" << nodedofset[gid][0] << "/"
362- // << nodeduplicatedofset[gid][0] << ", 2:" << nodedofset[gid][2] << "/"
363- // << nodeduplicatedofset[gid][2]<< "\n";
364- }
365- for (int i = 0 ; i < numrownodes; ++i)
366- {
367- const int gid = dis.l_row_node (i)->id ();
368- std::string s = std::format (" Node {}: " , gid + 1 );
369- bool printflag = false ;
370- for (int j = 0 ; j < 3 ; ++j)
371- {
372- const int dupnode = nodeduplicatedofset[gid][j];
373- s += std::format (" {}/{}, " , nodedofset[gid][j], dupnode);
374- if (dupnode == 1 ) printflag = true ;
375- }
376- if (printflag) std::cout << s << std::endl;
377360 }
378361
379-
380- Epetra_Import nodeimporter (numdfcolnodes_->get_map (), num_dof_rownodes.get_map ());
362+ Epetra_Import nodeimporter (numdfcolnodes_->get_block_map (), num_dof_rownodes.get_block_map ());
381363 int err = numdfcolnodes_->import (num_dof_rownodes, nodeimporter, Insert);
382- if (err) FOUR_C_THROW (" Import using importer returned err=%d " , err);
364+ if (err) FOUR_C_THROW (" Import using importer returned err={} " , err);
383365 err = idxcolnodes_->import (idxrownodes, nodeimporter, Insert);
384366 if (err) FOUR_C_THROW (" Import using importer returned err={}" , err);
385367
@@ -451,7 +433,6 @@ int Core::DOFSets::DofSet::assign_degrees_of_freedom(
451433 Core::LinAlg::Vector<int > numdfrowelements (*dis.element_row_map ());
452434 Core::LinAlg::Vector<int > idxrowelements (*dis.element_row_map ());
453435
454- int numrowelements = dis.num_my_row_elements ();
455436 for (int i = 0 ; i < numrowelements; ++i)
456437 {
457438 Core::Elements::Element* actele = dis.l_row_element (i);
@@ -462,6 +443,7 @@ int Core::DOFSets::DofSet::assign_degrees_of_freedom(
462443
463444 int minelementgid = dis.element_row_map ()->MinAllGID ();
464445 maxelementnumdf = numdfrowelements.max_value ();
446+ localrowdofs.reserve (numrownodes * maxnodenumdf + numrowelements * maxelementnumdf);
465447
466448 for (int i = 0 ; i < numrowelements; ++i)
467449 {
@@ -479,72 +461,46 @@ int Core::DOFSets::DofSet::assign_degrees_of_freedom(
479461 }
480462
481463 Epetra_Import elementimporter (
482- numdfcolelements_->get_map (), numdfrowelements.get_map ());
464+ numdfcolelements_->get_block_map (), numdfrowelements.get_block_map ());
483465 err = numdfcolelements_->import (numdfrowelements, elementimporter, Insert);
484466 if (err) FOUR_C_THROW (" Import using importer returned err={}" , err);
485467 err = idxcolelements_->import (idxrowelements, elementimporter, Insert);
486468 if (err) FOUR_C_THROW (" Import using importer returned err={}" , err);
487469 }
488470
489471 // Now finally we have everything in place to build the maps.
490- int numrownodes = dis.num_my_row_nodes ();
491- int numrowelements = dis.num_my_row_elements ();
492-
493- std::vector<int > localrowdofs;
494- std::vector<int > localcoldofs;
495- localrowdofs.reserve (numrownodes * maxnodenumdf + numrowelements * maxelementnumdf);
496- localcoldofs.reserve (numrownodes * maxnodenumdf + numrowelements * maxelementnumdf);
497-
498- std::vector<int > allnodelocalcoldofs;
499- allnodelocalcoldofs.reserve (numrownodes * maxnodenumdf);
500-
501- for (std::map<int , std::vector<int >>::iterator i = nodedofset.begin (); i != nodedofset.end (); ++i)
502- {
503- std::vector<int >& dofs = i->second ;
504- std::vector<int >& duplicatedofs = nodeduplicatedofset[i->first ];
505- std::vector<int > cleandofs;
506- for (unsigned j = 0 ; j < dofs.size (); ++j)
507- {
508- if (duplicatedofs[j] == 0 ) cleandofs.push_back (dofs[j]);
509- }
510- std::copy (cleandofs.begin (), cleandofs.end (), std::back_inserter (localrowdofs));
511- // printf("Proc %d nodal gid %d ndofs %d\n",proc,i->first,(int)dofs.size());
512- // for (unsigned j=0; j<dofs.size(); ++j) printf(" %d ",dofs[j]);
513- // printf("\n");
514- }
515472 for (std::map<int , std::vector<int >>::iterator i = facedofset.begin (); i != facedofset.end (); ++i)
516473 {
517474 std::vector<int >& dofs = i->second ;
518475 std::copy (dofs.begin (), dofs.end (), std::back_inserter (localrowdofs));
519- // printf("Proc %d ele gid %d ndofs %d\n",dis.Comm().MyPID(),i->first,(int)dofs.size());
520- // for (unsigned j=0; j<dofs.size(); ++j) printf(" %d ",dofs[j]);
521- // printf("\n");
522476 }
523477 for (std::map<int , std::vector<int >>::iterator i = elementdofset.begin ();
524478 i != elementdofset.end (); ++i)
525479 {
526480 std::vector<int >& dofs = i->second ;
527481 std::copy (dofs.begin (), dofs.end (), std::back_inserter (localrowdofs));
528- // printf("Proc %d ele gid %d ndofs %d\n",dis.Comm().MyPID(),i->first,(int)dofs.size());
529- // for (unsigned j=0; j<dofs.size(); ++j) printf(" %d ",dofs[j]);
530- // printf("\n");
531482 }
532483
533484 Core::Communication::Exporter nodeexporter (
534485 *dis.node_row_map (), *dis.node_col_map (), dis.get_comm ());
535486 nodeexporter.do_export (nodedofset);
536487
537- Core::Communication::Exporter elementexporter (
538- *dis.element_row_map (), *dis.element_col_map (), dis.get_comm ());
539- elementexporter.do_export (elementdofset);
540-
541488 if (facedis != nullptr && facedis->face_row_map () != nullptr )
542489 {
543490 Core::Communication::Exporter faceexporter (
544491 *facedis->face_row_map (), *facedis->face_col_map (), dis.get_comm ());
545492 faceexporter.do_export (facedofset);
546493 }
547494
495+ Core::Communication::Exporter elementexporter (
496+ *dis.element_row_map (), *dis.element_col_map (), dis.get_comm ());
497+ elementexporter.do_export (elementdofset);
498+
499+ std::vector<int > localcoldofs;
500+ localcoldofs.reserve (numrownodes * maxnodenumdf + numrowelements * maxelementnumdf);
501+ std::vector<int > allnodelocalcoldofs;
502+ allnodelocalcoldofs.reserve (numrownodes * maxnodenumdf);
503+
548504 for (std::map<int , std::vector<int >>::iterator i = nodedofset.begin (); i != nodedofset.end (); ++i)
549505 {
550506 std::vector<int >& dofs = i->second ;
0 commit comments