Skip to content

Commit 7dc83b8

Browse files
committed
Add example for two connected Point Couplings
1 parent 8501e96 commit 7dc83b8

File tree

5 files changed

+429
-136
lines changed

5 files changed

+429
-136
lines changed

src/core/fem/src/discretization/4C_fem_discretization.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,8 @@ void Core::FE::Discretization::print(std::ostream& os) const
318318
// loop over dofsets
319319
for (int nds = 0; nds < num_dof_sets(); ++nds)
320320
{
321-
os << "\n------------------------ Dofset " << nds << " :\n\n";
321+
os << "\n------------------------ Dofset " << nds << " out of " << num_dof_sets()
322+
<< " :\n\n";
322323
// print elements
323324
{
324325
os << "-------------------------- Proc " << proc << " :\n";

src/core/fem/src/dofset/4C_fem_dofset.cpp

Lines changed: 91 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
#include <algorithm>
1818
#include <format>
19-
#include <iostream>
2019

2120
FOUR_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

Comments
 (0)