Skip to content

Commit 5153454

Browse files
authored
Merge pull request #512 from ischeider/ImprovePointCoupling
Improve POINT COUPLING CONDITIONS
2 parents dd172de + 7dc83b8 commit 5153454

File tree

5 files changed

+446
-117
lines changed

5 files changed

+446
-117
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: 108 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#include <Epetra_FECrsGraph.h>
1616

1717
#include <algorithm>
18-
#include <iostream>
18+
#include <format>
1919

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

Comments
 (0)