77//!
88//! \author Knut Morten Okstad / SINTEF
99//!
10- //! \brief Rigid Coupling handler for elasticity problems.
10+ //! \brief Rigid and nodal coupling handler for elasticity problems.
1111//!
1212//==============================================================================
1313
1919#include "IFEM.h"
2020#include "Vec3Oper.h"
2121#include "tinyxml2.h"
22+ #include <iostream>
23+ #include <fstream>
24+ #include <sstream>
2225
2326
2427bool SIMRigid ::parseRigid (const tinyxml2 ::XMLElement * elem , SIMinput * mySim )
@@ -63,13 +66,69 @@ bool SIMRigid::parseRigid (const tinyxml2::XMLElement* elem, SIMinput* mySim)
6366}
6467
6568
69+ bool SIMRigid ::parseCouplings (const tinyxml2 ::XMLElement * elem )
70+ {
71+ // Lambda function parsing the nodal couplings for a patch.
72+ auto&& parseCpl = [](std ::istream & is , Couplin & cpl , char delim = '\n' )
73+ {
74+ std ::string cline ;
75+ int slave , master ;
76+ double weight ;
77+ while (std ::getline (is ,cline ,delim ))
78+ {
79+ std ::istringstream ss (cline );
80+ ss >> slave >> master >> weight ;
81+ while (ss )
82+ {
83+ cpl [slave ].emplace_back (master ,weight );
84+ ss >> master >> weight ;
85+ }
86+ #if INT_DEBUG > 1
87+ std ::cout <<"Slave (" << slave <<") coupled to master(s):" ;
88+ for (const Master & mst : cpl [slave ])
89+ std ::cout <<" (" << mst .first <<")*" << mst .second ;
90+ std ::cout << std ::endl ;
91+ #endif
92+ }
93+ };
94+
95+ IFEM ::cout <<" Parsing <" << elem -> Value () <<">" << std ::endl ;
96+
97+ int patch = 1 ;
98+ utl ::getAttribute (elem ,"patch" ,patch );
99+ if (std ::string fName ; utl ::getAttribute (elem ,"file" ,fName ))
100+ {
101+ std ::ifstream fs (fName );
102+ parseCpl (fs ,myCouplings [patch ]);
103+ }
104+ else if (elem -> FirstChild ())
105+ {
106+ std ::istringstream ss (elem -> FirstChild ()-> Value ());
107+ parseCpl (ss ,myCouplings [patch ],'\\' );
108+ }
109+ else
110+ return false;
111+
112+ IFEM ::cout <<"\tParsed " << myCouplings [patch ].size ()
113+ <<" nodal couplings for Patch " << patch ;
114+ if (double xtol = 0.0 ; utl ::getAttribute (elem ,"xtol" ,xtol ) && xtol > 0.0 )
115+ {
116+ myGeomTols [patch ] = xtol ;
117+ IFEM ::cout <<" (tolerance = " << xtol <<")" ;
118+ }
119+
120+ IFEM ::cout << std ::endl ;
121+ return true;
122+ }
123+
124+
66125bool SIMRigid ::addRigidMPCs (SIMinput * mySim , int & ngnod ) const
67126{
68- PropertyVec ::const_iterator pit ;
69- for ( pit = mySim -> begin_prop (); pit != mySim -> end_prop (); ++ pit )
127+ for ( PropertyVec ::const_iterator pit = mySim -> begin_prop () ;
128+ pit != mySim -> end_prop (); ++ pit )
70129 if (pit -> pcode == Property ::RIGID )
71130 {
72- std :: map < int , TopItem > ::const_iterator mit = myMasters .find (pit -> pindx );
131+ PntMap ::const_iterator mit = myMasters .find (pit -> pindx );
73132 if (mit == myMasters .end ())
74133 {
75134 std ::cerr <<" *** SIMRigid::addRigidMPCs: Local error"
@@ -86,17 +145,51 @@ bool SIMRigid::addRigidMPCs (SIMinput* mySim, int& ngnod) const
86145
87146 // Find master point and the affected patch,
88147 // and create a rigid coupling between them
89- SIMinput ::IdxVec3 * mst = mySim -> getDiscretePoint (mit -> second .item );
90- ASMbase * pch = mySim -> getPatch (pit -> patch );
91- if (mst && pch )
92- if (pch -> addRigidCpl (pit -> lindx ,pit -> ldim ,pit -> basis ,
93- mst -> first ,mst -> second )) ++ ngnod ;
148+ if (SIMinput ::IdxVec3 * mp = mySim -> getDiscretePoint (mit -> second .item ); mp )
149+ if (ASMbase * pch = mySim -> getPatch (pit -> patch ); pch )
150+ if (pch -> addRigidCpl (pit -> lindx ,pit -> ldim ,pit -> basis ,
151+ mp -> first ,mp -> second )) ++ ngnod ;
94152 }
95153
96154 return true;
97155}
98156
99157
158+ bool SIMRigid ::addGeneralCouplings (SIMinput * mySim ) const
159+ {
160+ bool status = true;
161+ for (const CplMap ::value_type & cpl : myCouplings )
162+ if (ASMbase * pch = mySim -> getPatch (cpl .first ); pch )
163+ {
164+ std ::vector < Ipair > connectedNodes ;
165+ for (const Couplin ::value_type & mpc : cpl .second )
166+ if (mpc .second .size () == 1 && mpc .second .front ().second == 1.0 )
167+ // Direct coupling of matching nodes
168+ connectedNodes .emplace_back (mpc .first ,mpc .second .front ().first );
169+ else
170+ {
171+ // Create linear couplings
172+ IntVec masters ;
173+ RealArray weights ;
174+ for (const Master & mst : mpc .second )
175+ {
176+ masters .push_back (mst .first );
177+ weights .push_back (mst .second );
178+ }
179+ pch -> addNodalCouplings (mpc .first ,masters ,weights );
180+ }
181+
182+ if (TolMap ::const_iterator it = myGeomTols .find (cpl .first );
183+ it != myGeomTols .end ())
184+ status &= pch -> selfInterconnect (connectedNodes ,it -> second );
185+ else
186+ status &= pch -> selfInterconnect (connectedNodes );
187+ }
188+
189+ return status ;
190+ }
191+
192+
100193ElementBlock * SIMRigid ::rigidGeometry (SIMinput * mySim ) const
101194{
102195 if (myMasters .empty ()) return nullptr ; // no rigid couplings
@@ -105,31 +198,27 @@ ElementBlock* SIMRigid::rigidGeometry (SIMinput* mySim) const
105198 std ::map < int ,size_t > imap ;
106199 ElementBlock * rgd = new ElementBlock (2 );
107200 rgd -> unStructResize (0 ,myMasters .size ());
108- for (const std :: pair < const int , TopItem > & master : myMasters )
201+ for (const PntMap :: value_type & master : myMasters )
109202 {
110- SIMinput ::IdxVec3 * mst = mySim -> getDiscretePoint (master .second .item );
111- if ( mst ) rgd -> setCoor (inod ,mst -> second );
203+ if ( SIMinput ::IdxVec3 * mp = mySim -> getDiscretePoint (master .second .item ); mp )
204+ rgd -> setCoor (inod ,mp -> second );
112205 imap [master .first ] = inod ++ ;
113206 }
114207
115208 int slvThick = mySim -> opt .discretization == ASM ::SplineC1 ? 2 : 1 ;
116209
117- PropertyVec ::const_iterator pit ;
118- std ::map < int ,TopItem > ::const_iterator mit ;
119- for (pit = mySim -> begin_prop (); pit != mySim -> end_prop (); ++ pit )
210+ for (PropertyVec ::const_iterator pit = mySim -> begin_prop ();
211+ pit != mySim -> end_prop (); ++ pit )
120212 if (pit -> pcode == Property ::RIGID )
121- if ((mit = myMasters .find (pit -> pindx )) != myMasters .end ())
122- if (mit -> second .patch == 0 )
213+ if (PntMap ::const_iterator mit = myMasters .find (pit -> pindx );
214+ mit != myMasters .end () && mit -> second .patch == 0 )
215+ if (ASMbase * pch = mySim -> getPatch (pit -> patch ); pch &&
216+ mySim -> getDiscretePoint (mit -> second .item ))
123217 {
124- SIMinput ::IdxVec3 * mst = mySim -> getDiscretePoint (mit -> second .item );
125- ASMbase * pch = mySim -> getPatch (pit -> patch );
126- if (mst && pch )
127- {
128- IntVec nodes ;
129- pch -> getBoundaryNodes (pit -> lindx ,nodes ,pit -> basis ,slvThick ,0 ,true);
130- for (int node : nodes )
131- rgd -> addLine (imap [mit -> first ],pch -> getCoord (node ));
132- }
218+ IntVec nodes ;
219+ pch -> getBoundaryNodes (pit -> lindx ,nodes ,pit -> basis ,slvThick ,0 ,true);
220+ for (int node : nodes )
221+ rgd -> addLine (imap [mit -> first ],pch -> getCoord (node ));
133222 }
134223
135224 return rgd ;
0 commit comments