1515#include < Epetra_FECrsGraph.h>
1616
1717#include < algorithm>
18+ #include < format>
1819#include < iostream>
1920
2021FOUR_C_NAMESPACE_OPEN
@@ -214,87 +215,102 @@ int Core::DOFSets::DofSet::assign_degrees_of_freedom(
214215 if ((int )couplingconditions.size () > 0 ) pccdofhandling_ = true ;
215216
216217 // do the nodes first
217- Core::LinAlg::Vector<int > numdfrownodes (*dis.node_row_map ());
218+ Core::LinAlg::Vector<int > num_dof_rownodes (*dis.node_row_map ());
218219 Core::LinAlg::Vector<int > idxrownodes (*dis.node_row_map ());
219220
220221 int numrownodes = dis.num_my_row_nodes ();
221222 for (int i = 0 ; i < numrownodes; ++i)
222223 {
223224 Core::Nodes::Node* actnode = dis.l_row_node (i);
224- numdfrownodes [i] = num_dof_per_node (*actnode);
225+ num_dof_rownodes [i] = num_dof_per_node (*actnode);
225226 }
226227
227228 int minnodegid = get_minimal_node_gid_if_relevant (dis);
228- maxnodenumdf = numdfrownodes .max_value ();
229+ maxnodenumdf = num_dof_rownodes .max_value ();
229230 get_reserved_max_num_dofper_node (maxnodenumdf); // XFEM::XFEMDofSet set to const number!
230231
232+ std::vector<std::vector<int >> onoffcond; // vector of onoff status for each condition
233+ std::vector<int > numdofcond; // vector of NUMDOF for each condition
234+ 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
236+
237+ for (int k = 0 ; k < (int )couplingconditions.size (); ++k)
238+ {
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)" );
256+ }
257+
231258 for (int i = 0 ; i < numrownodes; ++i)
232259 {
233- Core::Nodes::Node* actnode = dis.l_row_node (i);
234- const int gid = actnode->id ();
260+ const int gid = dis.l_row_node (i)->id ();
235261
236262 // **********************************************************************
237263 // **********************************************************************
238264 // check for DoF coupling conditions popp 02/2016
239265 // **********************************************************************
240266 // **********************************************************************
241- int relevantcondid = - 1 ;
267+ std::vector< int > applied_condition (maxnodenumdf, - 1 ) ;
242268 if (dspos_ == 0 )
243269 {
244- for (int k = 0 ; k < (int )couplingconditions.size (); ++k )
270+ for (int icond = 0 ; icond < (int )couplingconditions.size (); ++icond )
245271 {
246- if (couplingconditions[k]->contains_node (gid))
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 ())
247281 {
248- if (relevantcondid != -1 ) FOUR_C_THROW (" ERROR: Two coupling conditions on one node" );
249- relevantcondid = k;
282+ for (int k_on = 0 ; k_on < (int )onoffcond[icond].size (); ++k_on)
283+ {
284+ if (onoffcond[icond][k_on] == 0 ) continue ;
285+ FOUR_C_ASSERT (applied_condition[k_on] == -1 ,
286+ " ERROR: Two coupling conditions on the same degree of freedom" );
287+ applied_condition[k_on] = icond;
288+ }
250289 }
251290 }
252291 }
253-
254292 // check for node coupling condition and slave/master status
255- bool specialtreatment = false ;
256- if (relevantcondid >= 0 )
257- {
258- const std::vector<int >* nodeids = couplingconditions[relevantcondid]->get_nodes ();
259- if (!nodeids) FOUR_C_THROW (" ERROR: Condition does not have Node Ids" );
293+ bool specialtreatment (false );
260294
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)
295+ // for (int idim = 0; idim < (int)applied_condition.size(); ++idim);
296+ if (*std::ranges::max_element (applied_condition.begin (), applied_condition.end ()) >= 0 )
297+ {
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)
265303 {
266- int checkgid = (*nodeids)[k] ;
267- if (!dis. node_row_map ()-> MyGID (checkgid)) allononeproc = false ;
304+ if (condition_id == - 1 ) continue ;
305+ if (mgids[condition_id] != gid) allmaster = false ;
268306 }
269- if (!allononeproc)
270- FOUR_C_THROW (
271- " ERROR: Nodes in point coupling condition must all be on same processor (for now)" );
272-
273- // do nothing for first (master) node in coupling condition
274- // do something for second, third, ... (slave) node
275- if ((*nodeids)[0 ] != gid)
307+ if (!allmaster)
276308 {
277309 // critical case
278310 specialtreatment = true ;
279311
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-
296312 // special treatment
297- int numdf = numdfrownodes [i];
313+ int numdf = num_dof_rownodes [i];
298314 int dof = count + (gid - minnodegid) * maxnodenumdf;
299315 idxrownodes[i] = dof;
300316 std::vector<int >& dofs = nodedofset[gid];
@@ -303,9 +319,11 @@ int Core::DOFSets::DofSet::assign_degrees_of_freedom(
303319 duplicatedofs.reserve (numdf);
304320 for (int j = 0 ; j < numdf; ++j)
305321 {
306- // push back master node DoF ID if coupled
307- if (onoffcond[j] == 1 )
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)
308325 {
326+ std::vector<int >& mdofs = nodedofset[mgids[applied_condition[j]]];
309327 dofs.push_back (mdofs[j]);
310328 duplicatedofs.push_back (1 );
311329 }
@@ -322,7 +340,8 @@ int Core::DOFSets::DofSet::assign_degrees_of_freedom(
322340 // standard treatment for non-coupling nodes and master coupling nodes
323341 if (!specialtreatment)
324342 {
325- int numdf = numdfrownodes[i];
343+ // now treat only the nodes, which are master and thus did not get the special treatment
344+ int numdf = num_dof_rownodes[i];
326345 int dof = count + (gid - minnodegid) * maxnodenumdf;
327346 idxrownodes[i] = dof;
328347 std::vector<int >& dofs = nodedofset[gid];
@@ -339,11 +358,28 @@ int Core::DOFSets::DofSet::assign_degrees_of_freedom(
339358 // **********************************************************************
340359 // **********************************************************************
341360 // **********************************************************************
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;
342377 }
343378
344- Epetra_Import nodeimporter (numdfcolnodes_->get_block_map (), numdfrownodes.get_block_map ());
345- int err = numdfcolnodes_->import (numdfrownodes, nodeimporter, Insert);
346- if (err) FOUR_C_THROW (" Import using importer returned err={}" , err);
379+
380+ Epetra_Import nodeimporter (numdfcolnodes_->get_map (), num_dof_rownodes.get_map ());
381+ int err = numdfcolnodes_->import (num_dof_rownodes, nodeimporter, Insert);
382+ if (err) FOUR_C_THROW (" Import using importer returned err=%d" , err);
347383 err = idxcolnodes_->import (idxrownodes, nodeimporter, Insert);
348384 if (err) FOUR_C_THROW (" Import using importer returned err={}" , err);
349385
@@ -443,7 +479,7 @@ int Core::DOFSets::DofSet::assign_degrees_of_freedom(
443479 }
444480
445481 Epetra_Import elementimporter (
446- numdfcolelements_->get_block_map (), numdfrowelements.get_block_map ());
482+ numdfcolelements_->get_map (), numdfrowelements.get_map ());
447483 err = numdfcolelements_->import (numdfrowelements, elementimporter, Insert);
448484 if (err) FOUR_C_THROW (" Import using importer returned err={}" , err);
449485 err = idxcolelements_->import (idxrowelements, elementimporter, Insert);
0 commit comments