1515#include < Epetra_FECrsGraph.h>
1616
1717#include < algorithm>
18- #include < iostream >
18+ #include < format >
1919
2020FOUR_C_NAMESPACE_OPEN
2121
@@ -74,6 +74,7 @@ void Core::DOFSets::DofSet::print(std::ostream& os) const
7474 {
7575 int numdf = (*numdfcolnodes_)[i];
7676 int idx = (*idxcolnodes_)[i];
77+
7778 os << i << " : " ;
7879 for (int j = 0 ; j < numdf; ++j) os << (idx + j) << " " ;
7980 os << " \n " ;
@@ -202,137 +203,154 @@ int Core::DOFSets::DofSet::assign_degrees_of_freedom(
202203 // ////////////////////////////////////////////////////////////////
203204 int maxnodenumdf = 0 ;
204205 int maxelementnumdf = 0 ;
206+ int numrownodes = dis.num_my_row_nodes ();
207+ int numrowelements = dis.num_my_row_elements ();
205208 std::map<int , std::vector<int >> nodedofset;
206- std::map<int , std::vector<int >> nodeduplicatedofset;
207209 std::map<int , std::vector<int >> elementdofset;
208210 std::map<int , std::vector<int >> facedofset;
211+ std::vector<int > localrowdofs;
209212
210213 {
211214 // get DoF coupling conditions
212215 std::vector<Core::Conditions::Condition*> couplingconditions (0 );
213216 dis.get_condition (" PointCoupling" , couplingconditions);
214- if (( int ) couplingconditions.size () > 0 ) pccdofhandling_ = true ;
217+ if (! couplingconditions.empty () ) pccdofhandling_ = true ;
215218
216219 // do the nodes first
217- Core::LinAlg::Vector<int > numdfrownodes (*dis.node_row_map ());
220+ Core::LinAlg::Vector<int > num_dof_rownodes (*dis.node_row_map ());
218221 Core::LinAlg::Vector<int > idxrownodes (*dis.node_row_map ());
219222
220- int numrownodes = dis.num_my_row_nodes ();
221223 for (int i = 0 ; i < numrownodes; ++i)
222224 {
223225 Core::Nodes::Node* actnode = dis.l_row_node (i);
224- numdfrownodes [i] = num_dof_per_node (*actnode);
226+ num_dof_rownodes [i] = num_dof_per_node (*actnode);
225227 }
226228
227229 int minnodegid = get_minimal_node_gid_if_relevant (dis);
228- maxnodenumdf = numdfrownodes .max_value ();
230+ maxnodenumdf = num_dof_rownodes .max_value ();
229231 get_reserved_max_num_dofper_node (maxnodenumdf); // XFEM::XFEMDofSet set to const number!
232+ localrowdofs.reserve (numrownodes * maxnodenumdf);
233+
234+ std::vector<std::vector<int >> onoffcond; // vector of onoff status for each condition
235+ std::vector<int > numdofcond; // vector of NUMDOF for each condition
236+ std::vector<std::vector<int >> nodeids; // vector of node IDs for each condition
237+ std::vector<int > masterIds; // vector of master node IDs for each condition
238+
239+ for (const auto * condition : couplingconditions)
240+ {
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 ());
247+ }
230248
231249 for (int i = 0 ; i < numrownodes; ++i)
232250 {
233- Core::Nodes::Node* actnode = dis.l_row_node (i);
234- const int gid = actnode->id ();
251+ const int gid = dis.l_row_node (i)->id ();
235252
236253 // **********************************************************************
237254 // **********************************************************************
238255 // check for DoF coupling conditions popp 02/2016
239256 // **********************************************************************
240257 // **********************************************************************
241- int relevantcondid = - 1 ;
258+ std::vector< int > applied_condition (maxnodenumdf, - 1 ) ;
242259 if (dspos_ == 0 )
243260 {
244- for (int k = 0 ; k < ( int ) couplingconditions.size (); ++k )
261+ for (size_t condition_id = 0 ; condition_id < couplingconditions.size (); ++condition_id )
245262 {
246- if (couplingconditions[k]->contains_node (gid))
263+ // check if the node gid is contained in the coupling condition
264+ if (couplingconditions[condition_id]->contains_node (gid))
247265 {
248- if (relevantcondid != -1 ) FOUR_C_THROW (" ERROR: Two coupling conditions on one node" );
249- relevantcondid = k;
266+ for (size_t k_on = 0 ; k_on < onoffcond[condition_id].size (); ++k_on)
267+ {
268+ if (onoffcond[condition_id][k_on] == 0 ) continue ;
269+ FOUR_C_ASSERT (applied_condition[k_on] == -1 ,
270+ " ERROR: Two coupling conditions on the same degree of freedom" );
271+ applied_condition[k_on] = condition_id;
272+ }
250273 }
251274 }
252275 }
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 ;
253279
254- // check for node coupling condition and slave/master status
255- bool specialtreatment = false ;
256- if (relevantcondid >= 0 )
280+ for (int k_on = 0 ; k_on < maxnodenumdf; ++k_on)
257281 {
258- const std::vector<int >* nodeids = couplingconditions[relevantcondid]->get_nodes ();
259- if (!nodeids) FOUR_C_THROW (" ERROR: Condition does not have Node Ids" );
260-
261- // check if all nodes in this condition are on same processor
262- // (otherwise throw a FOUR_C_THROW for now - not yet implemented)
263- bool allononeproc = true ;
264- for (int k = 0 ; k < (int )(nodeids->size ()); ++k)
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)
265286 {
266- int checkgid = (*nodeids)[k];
267- if (!dis.node_row_map ()->MyGID (checkgid)) allononeproc = 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+ }
268294 }
269- if (!allononeproc)
270- FOUR_C_THROW (
271- " ERROR: Nodes in point coupling condition must all be on same processor (for now)" );
295+ }
296+ if (!allononeproc)
297+ FOUR_C_THROW (
298+ " ERROR: Nodes in point coupling condition must all be on same processor (for now)." );
272299
273- // do nothing for first (master) node in coupling condition
274- // do something for second, third, ... (slave) node
275- if ((*nodeids)[0 ] != gid)
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)
276325 {
277- // critical case
278- specialtreatment = true ;
279-
280- // check total number of dofs and determine which dofs are to be coupled
281- if (couplingconditions[relevantcondid]->parameters ().get <int >(" NUMDOF" ) !=
282- numdfrownodes[i])
283- FOUR_C_THROW (
284- " ERROR: Number of DoFs in coupling condition ({}) does not match node ({})" ,
285- couplingconditions[relevantcondid]->parameters ().get <int >(" NUMDOF" ),
286- numdfrownodes[i]);
287- const std::vector<int >& onoffcond =
288- couplingconditions[relevantcondid]->parameters ().get <std::vector<int >>(" ONOFF" );
289-
290- // get master node of this condition
291- int mgid = (*nodeids)[0 ];
292- std::vector<int >& mdofs = nodedofset[mgid];
293- if ((int )(mdofs.size ()) == 0 )
294- FOUR_C_THROW (" ERROR: Master node has not yet been initialized with DoFs" );
295-
296- // special treatment
297- int numdf = numdfrownodes[i];
298- int dof = count + (gid - minnodegid) * maxnodenumdf;
299- idxrownodes[i] = dof;
300- std::vector<int >& dofs = nodedofset[gid];
301- std::vector<int >& duplicatedofs = nodeduplicatedofset[gid];
302- dofs.reserve (numdf);
303- duplicatedofs.reserve (numdf);
304- 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)
305329 {
306- // push back master node DoF ID if coupled
307- if (onoffcond[j] == 1 )
308- {
309- dofs.push_back (mdofs[j]);
310- duplicatedofs.push_back (1 );
311- }
312- // push back new DoF ID if not coupled
313- else
314- {
315- dofs.push_back (dof + j);
316- duplicatedofs.push_back (0 );
317- }
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);
318338 }
319339 }
320340 }
321-
341+ else
322342 // standard treatment for non-coupling nodes and master coupling nodes
323- if (!specialtreatment)
324343 {
325- int numdf = numdfrownodes[i];
344+ // now treat only the nodes, which are master and thus did not get the special treatment
345+ int numdf = num_dof_rownodes[i];
326346 int dof = count + (gid - minnodegid) * maxnodenumdf;
327347 idxrownodes[i] = dof;
328348 std::vector<int >& dofs = nodedofset[gid];
329- std::vector<int >& duplicatedofs = nodeduplicatedofset[gid];
330349 dofs.reserve (numdf);
331- duplicatedofs.reserve (numdf);
332350 for (int j = 0 ; j < numdf; ++j)
333351 {
334352 dofs.push_back (dof + j);
335- duplicatedofs .push_back (0 );
353+ localrowdofs .push_back (dof + j );
336354 }
337355 }
338356 // **********************************************************************
@@ -341,8 +359,8 @@ int Core::DOFSets::DofSet::assign_degrees_of_freedom(
341359 // **********************************************************************
342360 }
343361
344- Epetra_Import nodeimporter (numdfcolnodes_->get_block_map (), numdfrownodes .get_block_map ());
345- int err = numdfcolnodes_->import (numdfrownodes , nodeimporter, Insert);
362+ Epetra_Import nodeimporter (numdfcolnodes_->get_block_map (), num_dof_rownodes .get_block_map ());
363+ int err = numdfcolnodes_->import (num_dof_rownodes , nodeimporter, Insert);
346364 if (err) FOUR_C_THROW (" Import using importer returned err={}" , err);
347365 err = idxcolnodes_->import (idxrownodes, nodeimporter, Insert);
348366 if (err) FOUR_C_THROW (" Import using importer returned err={}" , err);
@@ -415,7 +433,6 @@ int Core::DOFSets::DofSet::assign_degrees_of_freedom(
415433 Core::LinAlg::Vector<int > numdfrowelements (*dis.element_row_map ());
416434 Core::LinAlg::Vector<int > idxrowelements (*dis.element_row_map ());
417435
418- int numrowelements = dis.num_my_row_elements ();
419436 for (int i = 0 ; i < numrowelements; ++i)
420437 {
421438 Core::Elements::Element* actele = dis.l_row_element (i);
@@ -426,6 +443,7 @@ int Core::DOFSets::DofSet::assign_degrees_of_freedom(
426443
427444 int minelementgid = dis.element_row_map ()->MinAllGID ();
428445 maxelementnumdf = numdfrowelements.max_value ();
446+ localrowdofs.reserve (numrownodes * maxnodenumdf + numrowelements * maxelementnumdf);
429447
430448 for (int i = 0 ; i < numrowelements; ++i)
431449 {
@@ -451,64 +469,38 @@ int Core::DOFSets::DofSet::assign_degrees_of_freedom(
451469 }
452470
453471 // Now finally we have everything in place to build the maps.
454- int numrownodes = dis.num_my_row_nodes ();
455- int numrowelements = dis.num_my_row_elements ();
456-
457- std::vector<int > localrowdofs;
458- std::vector<int > localcoldofs;
459- localrowdofs.reserve (numrownodes * maxnodenumdf + numrowelements * maxelementnumdf);
460- localcoldofs.reserve (numrownodes * maxnodenumdf + numrowelements * maxelementnumdf);
461-
462- std::vector<int > allnodelocalcoldofs;
463- allnodelocalcoldofs.reserve (numrownodes * maxnodenumdf);
464-
465- for (std::map<int , std::vector<int >>::iterator i = nodedofset.begin (); i != nodedofset.end (); ++i)
466- {
467- std::vector<int >& dofs = i->second ;
468- std::vector<int >& duplicatedofs = nodeduplicatedofset[i->first ];
469- std::vector<int > cleandofs;
470- for (unsigned j = 0 ; j < dofs.size (); ++j)
471- {
472- if (duplicatedofs[j] == 0 ) cleandofs.push_back (dofs[j]);
473- }
474- std::copy (cleandofs.begin (), cleandofs.end (), std::back_inserter (localrowdofs));
475- // printf("Proc %d nodal gid %d ndofs %d\n",proc,i->first,(int)dofs.size());
476- // for (unsigned j=0; j<dofs.size(); ++j) printf(" %d ",dofs[j]);
477- // printf("\n");
478- }
479472 for (std::map<int , std::vector<int >>::iterator i = facedofset.begin (); i != facedofset.end (); ++i)
480473 {
481474 std::vector<int >& dofs = i->second ;
482475 std::copy (dofs.begin (), dofs.end (), std::back_inserter (localrowdofs));
483- // printf("Proc %d ele gid %d ndofs %d\n",dis.Comm().MyPID(),i->first,(int)dofs.size());
484- // for (unsigned j=0; j<dofs.size(); ++j) printf(" %d ",dofs[j]);
485- // printf("\n");
486476 }
487477 for (std::map<int , std::vector<int >>::iterator i = elementdofset.begin ();
488478 i != elementdofset.end (); ++i)
489479 {
490480 std::vector<int >& dofs = i->second ;
491481 std::copy (dofs.begin (), dofs.end (), std::back_inserter (localrowdofs));
492- // printf("Proc %d ele gid %d ndofs %d\n",dis.Comm().MyPID(),i->first,(int)dofs.size());
493- // for (unsigned j=0; j<dofs.size(); ++j) printf(" %d ",dofs[j]);
494- // printf("\n");
495482 }
496483
497484 Core::Communication::Exporter nodeexporter (
498485 *dis.node_row_map (), *dis.node_col_map (), dis.get_comm ());
499486 nodeexporter.do_export (nodedofset);
500487
501- Core::Communication::Exporter elementexporter (
502- *dis.element_row_map (), *dis.element_col_map (), dis.get_comm ());
503- elementexporter.do_export (elementdofset);
504-
505488 if (facedis != nullptr && facedis->face_row_map () != nullptr )
506489 {
507490 Core::Communication::Exporter faceexporter (
508491 *facedis->face_row_map (), *facedis->face_col_map (), dis.get_comm ());
509492 faceexporter.do_export (facedofset);
510493 }
511494
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+
512504 for (std::map<int , std::vector<int >>::iterator i = nodedofset.begin (); i != nodedofset.end (); ++i)
513505 {
514506 std::vector<int >& dofs = i->second ;
0 commit comments