Skip to content

Commit 8501e96

Browse files
committed
Make the Point Coupling dof based not node based
Now each degree of freedom is considered separately
1 parent 23d49b8 commit 8501e96

File tree

1 file changed

+89
-53
lines changed

1 file changed

+89
-53
lines changed

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

Lines changed: 89 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <Epetra_FECrsGraph.h>
1616

1717
#include <algorithm>
18+
#include <format>
1819
#include <iostream>
1920

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

Comments
 (0)