TexGen
GeometrySolver.cpp
Go to the documentation of this file.
1/*=============================================================================
2TexGen: Geometric textile modeller.
3Copyright (C) 2006 Martin Sherburn
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18=============================================================================*/
19
20#include "PrecompiledHeaders.h"
21#include "GeometrySolver.h"
22#include "TexGen.h"
23#include <iterator>
24extern "C"
25{
26#include "../CSparse/Include/cs.h"
27}
28
29using namespace TexGen;
30CGeometrySolver::CGeometrySolver(void)
31: m_dHeightTolerance(1e-3)
32, m_dDisabledStiffness(1e-4)
33, m_dContactStiffness(1e3)
34, m_bAdjustThickness(false)
35, m_dLongitudinalBendingModulus(1.0)
36, m_dTransverseBendingModulus(1.0)
37, m_dTensileStress(1.0)
38{
39}
40
42{
43}
44
45void CGeometrySolver::SetTensileStress(double dTensileStress)
46{
47 m_dTensileStress = dTensileStress;
48 vector<PLATE>::iterator itPlate;
49 for (itPlate = m_PlateElements.begin(); itPlate != m_PlateElements.end(); ++itPlate)
50 {
51 itPlate->TensionElement.SetTensileStress(m_dTensileStress);
52 }
53}
54
56{
57 m_dLongitudinalBendingModulus = dBendingModulus;
58 vector<PLATE>::iterator itPlate;
59 for (itPlate = m_PlateElements.begin(); itPlate != m_PlateElements.end(); ++itPlate)
60 {
61 itPlate->BendingElement.SetLongitudinalBendingModulus(m_dLongitudinalBendingModulus);
62 }
63}
64
66{
67 m_dTransverseBendingModulus = dBendingModulus;
68 vector<PLATE>::iterator itPlate;
69 for (itPlate = m_PlateElements.begin(); itPlate != m_PlateElements.end(); ++itPlate)
70 {
71 itPlate->BendingElement.SetTransverseBendingModulus(m_dTransverseBendingModulus);
72 }
73}
74
75void CGeometrySolver::SetContactStiffness(double dContactStiffness)
76{
77 m_dContactStiffness = dContactStiffness;
78}
79
80void CGeometrySolver::SetDisabledStiffness(double dDisabledStiffness)
81{
82 m_dDisabledStiffness = dDisabledStiffness;
83}
84
85bool CGeometrySolver::CreateSystem(string TextileName)
86{
87 CTextile* pTextile = TEXGEN.GetTextile(TextileName);
88 if (pTextile)
89 return CreateSystem(*pTextile);
90 else
91 return false;
92}
93
95{
96 SetPeriodic(true);
97
98 int i, j;
100 {
101 int iNumYarns = Textile.GetNumYarns();
102 for (i=0; i<iNumYarns; ++i)
103 {
104 CYarn* pYarn = Textile.GetYarn(i);
105 if (pYarn && pYarn->GetInterpolation())
106 {
108 Interp->SetForceInPlaneTangent(true);
109 pYarn->AssignInterpolation(*Interp);
110 }
111 }
112 }
113
114 if (!CreateBasicVolumes(Textile))
115 return false;
116
117 int iNumNodes = (int)m_ProjectedMesh.GetNumNodes();
118 m_ProjectedNodes.clear();
119 m_ProjectedNodes.resize(iNumNodes);
120 for (i=0; i<iNumNodes; ++i)
121 {
123 RaiseNodes(i);
124 }
126 m_Nodes.clear();
127 NODE Node;
128 int iGlobalIndexCount = 0;
129 for (i=0; i<iNumNodes; ++i)
130 {
131 Node.Position = m_ProjectedNodes[i].Position;
132 for (j=0; j<(int)m_ProjectedNodes[i].RaisedNodes.size(); ++j)
133 {
134 RAISED_NODE &RaisedNode = m_ProjectedNodes[i].RaisedNodes[j];
135 RaisedNode.iGlobalIndex = iGlobalIndexCount++;
136 Node.Position.z = RaisedNode.dHeight;
137 Node.dThickness = RaisedNode.dThickness;
138 Node.iYarnIndex = RaisedNode.iYarnIndex;
140 m_Nodes.push_back(Node);
141 }
142 }
143
145
147
148 // Create yarn connection springs
149// list<int> &LineIndices = m_ProjectedMesh.m_Indices[CMesh::LINE];
150// list<int>::iterator itIter;
151/* int i1, i2;
152 vector<RAISED_NODE>::iterator itRaised1, itRaised2;
153 for (itIter = LineIndices.begin(); itIter != LineIndices.end(); )
154 {
155 i1 = *(itIter++);
156 i2 = *(itIter++);
157 PROJECTED_NODE &ProjNode1 = m_ProjectedNodes[i1];
158 PROJECTED_NODE &ProjNode2 = m_ProjectedNodes[i2];
159 Spring.dLength = GetLength(ProjNode1.Position, ProjNode2.Position);
160 for (itRaised1 = ProjNode1.RaisedNodes.begin(); itRaised1 != ProjNode1.RaisedNodes.end(); ++itRaised1)
161 {
162 for (itRaised2 = ProjNode2.RaisedNodes.begin(); itRaised2 != ProjNode2.RaisedNodes.end(); ++itRaised2)
163 {
164 if (itRaised1->iYarnIndex == itRaised2->iYarnIndex)
165 {
166 if (itRaised1->dThickness < m_dHeightTolerance && itRaised2->dThickness < m_dHeightTolerance)
167 continue;
168 Spring.iNode1 = itRaised1->iGlobalIndex;
169 Spring.iNode2 = itRaised2->iGlobalIndex;
170 m_Springs.push_back(Spring);
171 }
172 }
173 }
174 }*/
175
176 // Create plate elements from surface mesh
179
180 // Add yarn contact springs
181 m_Springs.clear();
182 SPRING Spring;
183 Spring.bEnabled = true;
184 vector<PROJECTED_NODE>::iterator itProjectedNode;
185 vector<RAISED_NODE>::iterator itRaised;
186 for (itProjectedNode = m_ProjectedNodes.begin(), i = 0; itProjectedNode != m_ProjectedNodes.end(); ++itProjectedNode, ++i)
187 {
188 Spring.dArea = GetArea(i);
189 for (j=0; j < (int)itProjectedNode->RaisedNodes.size()-1; ++j)
190 {
191 Spring.iNode1 = itProjectedNode->RaisedNodes[j].iGlobalIndex;
192 Spring.iNode2 = itProjectedNode->RaisedNodes[j+1].iGlobalIndex;
193 m_Springs.push_back(Spring);
194 }
195 }
196
197 // Build the constraints
198 m_DOFConstraints.clear();
199
200 // Fix the first node's vertical displacement DOF to ensure the system is properly constrained
201 m_DOFConstraints.push_back(make_pair(0, 0));
202// m_DOFConstraints.push_back(make_pair(1, 0));
203// m_DOFConstraints.push_back(make_pair(2, 0));
204
205 // Add periodic boundary conditions
206 pair<XYZ, XYZ> AABB = m_pTextile->GetDomain()->GetMesh().GetAABB();
207 double dWidth = AABB.second.x - AABB.first.x;
208 double dHeight = AABB.second.y - AABB.first.y;
209 vector<XYZ> Repeats;
210 Repeats.push_back(XYZ(dWidth, 0, 0));
211 Repeats.push_back(XYZ(0, dHeight, 0));
212
214
215 return true;
216}
217
219{
220 int i, j, k;
221 const int iXDivs = 10, iYDivs = 10;
222 double u, v;
223 for (k=0; k<2; ++k)
224 {
225 for (i=0; i<iXDivs; ++i)
226 {
227 u = i/double(iXDivs-1);
228 for (j=0; j<iYDivs; ++j)
229 {
230 v = j/double(iYDivs-1);
231 m_SurfaceMesh.AddNode(XYZ(u, v, /*u*u-u - v*v+v+*/0.2*k));
232 if (i<iXDivs-1 && j<iYDivs-1)
233 {
234 m_SurfaceMesh.GetIndices(CMesh::TRI).push_back(i*iYDivs+j + k*iXDivs*iYDivs);
235 m_SurfaceMesh.GetIndices(CMesh::TRI).push_back((i+1)*iYDivs+j + k*iXDivs*iYDivs);
236 m_SurfaceMesh.GetIndices(CMesh::TRI).push_back(i*iYDivs+j+1 + k*iXDivs*iYDivs);
237
238 m_SurfaceMesh.GetIndices(CMesh::TRI).push_back((i+1)*iYDivs+j + k*iXDivs*iYDivs);
239 m_SurfaceMesh.GetIndices(CMesh::TRI).push_back((i+1)*iYDivs+j+1 + k*iXDivs*iYDivs);
240 m_SurfaceMesh.GetIndices(CMesh::TRI).push_back(i*iYDivs+j+1 + k*iXDivs*iYDivs);
241 }
242 }
243 }
244 }
245/* m_SurfaceMesh.AddNode(XYZ(0, 0, 0));
246 m_SurfaceMesh.AddNode(XYZ(1, 0, 0));
247 m_SurfaceMesh.AddNode(XYZ(0, 1, 0));
248 m_SurfaceMesh.AddNode(XYZ(1, 1, 0));
249
250 m_SurfaceMesh.GetIndices(CMesh::TRI).push_back(0);
251 m_SurfaceMesh.GetIndices(CMesh::TRI).push_back(1);
252 m_SurfaceMesh.GetIndices(CMesh::TRI).push_back(2);
253
254 m_SurfaceMesh.GetIndices(CMesh::TRI).push_back(1);
255 m_SurfaceMesh.GetIndices(CMesh::TRI).push_back(3);
256 m_SurfaceMesh.GetIndices(CMesh::TRI).push_back(2);*/
257
258 NODE Node;
259 for (i=0; i<m_SurfaceMesh.GetNumNodes(); ++i)
260 {
262 Node.dThickness = 0.2;
263 m_Nodes.push_back(Node);
264 }
265
266 SPRING Spring;
267 Spring.bEnabled = true;
268 Spring.dArea = 0.1;
269 for (i=0; i<iXDivs*iYDivs; ++i)
270 {
271 Spring.iNode1 = i;
272 Spring.iNode2 = i + iXDivs*iYDivs;
273 m_Springs.push_back(Spring);
274 }
275
276 // Create plate elements from surface mesh
278
279 m_DOFConstraints.clear();
280 m_DOFConstraints.push_back(make_pair(0, 0));
281 m_DOFConstraints.push_back(make_pair(1, 0.5));
282 m_DOFConstraints.push_back(make_pair(2, 0.5));
283/* m_DOFConstraints.push_back(make_pair(0, 0));
284 m_DOFConstraints.push_back(make_pair(1, 0));
285 m_DOFConstraints.push_back(make_pair(2, 0));*/
286// m_DOFConstraints.push_back(make_pair((iXDivs*iYDivs-1)*3, 0));
287/* m_DOFConstraints.push_back(make_pair(3*iXDivs*iYDivs, 0));
288 m_DOFConstraints.push_back(make_pair(3*iXDivs*iYDivs+1, 0.5));
289 m_DOFConstraints.push_back(make_pair(3*iXDivs*iYDivs+2, 0.5));*/
290
291 // Apply periodic BCs
292 vector<XYZ> Repeats;
293 Repeats.push_back(XYZ(1, 0, 0));
294 Repeats.push_back(XYZ(0, 1, 0));
296}
297
299{
300 set<int> YarnIndices;
301 insert_iterator<set<int> > iiYarnIndices(YarnIndices, YarnIndices.end());
302 set<int>::iterator itYarnIndex;
303
304 list<int>::iterator itIndex;
305 list<int> &Indices = m_ProjectedMesh.GetIndices(CMesh::TRI);
306 int i, j, iNode, iRegion;
307
308 // Find projected triangles which have node (iIndex) as a corner
309 for (itIndex = Indices.begin(), i=0; itIndex != Indices.end(); ++i)
310 {
311 for (j=0; j<3; ++j)
312 {
313 iNode = *(itIndex++);
314 if (iNode == iIndex)
315 {
316 iRegion = m_TriangleRegions[i];
317 copy(m_ProjectedRegions[iRegion].YarnIndices.begin(), m_ProjectedRegions[iRegion].YarnIndices.end(), iiYarnIndices);
318 }
319 }
320 }
321
322 // Create the raised nodes
323 XYZ Point = m_ProjectedMesh.GetNode(iIndex);
324 RAISED_NODE Node;
325 double dMin, dMax;
326 for (itYarnIndex=YarnIndices.begin(); itYarnIndex!=YarnIndices.end(); ++itYarnIndex)
327 {
328 bool bFound = GetMeshVerticalBounds(m_YarnMeshes[*itYarnIndex], Point, dMin, dMax, true);
329 assert(bFound);
330 Node.dHeight = 0.5*(dMin+dMax);
331 Node.dThickness = dMax - dMin;
332 Node.iYarnIndex = *itYarnIndex;
333 m_ProjectedNodes[iIndex].RaisedNodes.push_back(Node);
334 }
335 sort(m_ProjectedNodes[iIndex].RaisedNodes.begin(), m_ProjectedNodes[iIndex].RaisedNodes.end());
336}
337
338double CGeometrySolver::GetArea(int iIndex)
339{
340 double dArea = 0;
341 vector<PLATE>::iterator itPlate;
342 for (itPlate = m_PlateElements.begin(); itPlate != m_PlateElements.end(); ++itPlate)
343 {
344 if (itPlate->iNode1 == iIndex || itPlate->iNode2 == iIndex || itPlate->iNode3 == iIndex)
345 {
346 dArea += itPlate->BendingElement.GetArea();
347 // same as itPlate->TensionElement.GetArea();
348 }
349 }
350 return dArea / 3.0;
351}
352
354{
355 // Create yarn connection springs
356 list<int> &LineIndices = m_ProjectedMesh.GetIndices(CMesh::LINE);
357 list<int>::iterator itIter;
358 int i1, i2;
359 double dAverageLength = 0;
360 int iNumConnected = 0;
361 for (itIter = LineIndices.begin(); itIter != LineIndices.end(); )
362 {
363 i1 = *(itIter++);
364 i2 = *(itIter++);
365 if (i1 == iIndex || i2 == iIndex)
366 {
367 dAverageLength += GetLength(m_ProjectedMesh.GetNode(i1), m_ProjectedMesh.GetNode(i2));
368 ++iNumConnected;
369 }
370 }
371 dAverageLength /= iNumConnected;
372 return dAverageLength;
373}
374
376{
377 list<int>::iterator itIndex;
378 list<int> &Indices = m_ProjectedMesh.GetIndices(CMesh::TRI);
379 int i1, i2, i3;
380 vector<RAISED_NODE>::iterator itRaised1, itRaised2, itRaised3;
381 for (itIndex = Indices.begin(); itIndex != Indices.end(); )
382 {
383 i1 = *(itIndex++);
384 i2 = *(itIndex++);
385 i3 = *(itIndex++);
386 PROJECTED_NODE &ProjNode1 = m_ProjectedNodes[i1];
387 PROJECTED_NODE &ProjNode2 = m_ProjectedNodes[i2];
388 PROJECTED_NODE &ProjNode3 = m_ProjectedNodes[i3];
389 for (itRaised1 = ProjNode1.RaisedNodes.begin(); itRaised1 != ProjNode1.RaisedNodes.end(); ++itRaised1)
390 {
391 for (itRaised2 = ProjNode2.RaisedNodes.begin(); itRaised2 != ProjNode2.RaisedNodes.end(); ++itRaised2)
392 {
393 for (itRaised3 = ProjNode3.RaisedNodes.begin(); itRaised3 != ProjNode3.RaisedNodes.end(); ++itRaised3)
394 {
395 if (itRaised1->iYarnIndex == itRaised2->iYarnIndex &&
396 itRaised2->iYarnIndex == itRaised3->iYarnIndex)
397 {
398 if (itRaised1->dThickness < m_dHeightTolerance &&
399 itRaised2->dThickness < m_dHeightTolerance &&
400 itRaised3->dThickness < m_dHeightTolerance)
401 continue;
402 m_SurfaceMesh.GetIndices(CMesh::TRI).push_back(itRaised1->iGlobalIndex);
403 m_SurfaceMesh.GetIndices(CMesh::TRI).push_back(itRaised2->iGlobalIndex);
404 m_SurfaceMesh.GetIndices(CMesh::TRI).push_back(itRaised3->iGlobalIndex);
405 }
406 }
407 }
408 }
409 }
410}
411
413{
414 m_PlateElements.clear();
415 PLATE Plate;
416 list<int>::iterator itIndex;
417 list<int> &Indices = m_SurfaceMesh.GetIndices(CMesh::TRI);
418 for (itIndex = Indices.begin(); itIndex != Indices.end(); )
419 {
420 Plate.iNode1 = *(itIndex++);
421 Plate.iNode2 = *(itIndex++);
422 Plate.iNode3 = *(itIndex++);
423 Plate.iYarnIndex = m_Nodes[Plate.iNode1].iYarnIndex;
424 CMatrix P(3, 2);
425 P(0,0) = m_SurfaceMesh.GetNode(Plate.iNode1).x; P(0,1) = m_SurfaceMesh.GetNode(Plate.iNode1).y;
426 P(1,0) = m_SurfaceMesh.GetNode(Plate.iNode2).x; P(1,1) = m_SurfaceMesh.GetNode(Plate.iNode2).y;
427 P(2,0) = m_SurfaceMesh.GetNode(Plate.iNode3).x; P(2,1) = m_SurfaceMesh.GetNode(Plate.iNode3).y;
433 m_PlateElements.push_back(Plate);
434 }
435}
436
438{
439 if (!m_pTextile)
440 return;
441 vector<PLATE>::iterator itPlate;
442 vector<vector<pair<int, XYZ> > > PlateCenters;
443 int i, j, iNumYarns = m_pTextile->GetNumYarns();
444 PlateCenters.resize(iNumYarns);
445 for (itPlate = m_PlateElements.begin(), i=0; itPlate != m_PlateElements.end(); ++itPlate, ++i)
446 {
447 XYZ Center;
448 Center += m_SurfaceMesh.GetNode(itPlate->iNode1);
449 Center += m_SurfaceMesh.GetNode(itPlate->iNode2);
450 Center += m_SurfaceMesh.GetNode(itPlate->iNode3);
451 Center /= 3.0;
452 PlateCenters[itPlate->iYarnIndex].push_back(make_pair(i, Center));
453 }
454 XYZ Tangent;
455 for (i=0; i<iNumYarns; ++i)
456 {
457 CYarn* pYarn = m_pTextile->GetYarn(i);
458 vector<XYZ> Translations = m_pTextile->GetDomain()->GetTranslations(*pYarn);
459 for (j=0; j<(int)PlateCenters[i].size(); ++j)
460 {
461 bool bInside = pYarn->PointInsideYarn(PlateCenters[i][j].second, Translations, &Tangent);
462 assert(bInside);
463 PLATE &Plate = m_PlateElements[PlateCenters[i][j].first];
464 Plate.BendingElement.SetFibreDirection(Tangent);
465 Plate.TensionElement.SetFibreDirection(Tangent);
466 }
467 }
468/* vector<POINT_INFO> PointInfo;
469 vector<POINT_INFO>::iterator itPointInfo;
470 m_pTextile->GetPointInformation(PlateCenters, PointInfo);
471 for (itPlate = m_PlateElements.begin(), itPointInfo = PointInfo.begin();
472 itPlate != m_PlateElements.end() && itPointInfo != PointInfo.end();
473 ++itPlate, ++itPointInfo)
474 {
475 itPlate->BendingElement.SetFibreDirection(itPointInfo->YarnTangent);
476 itPlate->TensionElement.SetFibreDirection(itPointInfo->YarnTangent);
477 }
478 assert(itPlate == m_PlateElements.end() && itPointInfo == PointInfo.end());*/
479}
480
482{
483 int i;
484 vector<pair<int, int> > NodePairs;
485 vector<XYZ>::iterator itRepeat;
486 for (itRepeat = Repeats.begin(); itRepeat != Repeats.end(); ++itRepeat)
487 {
488 vector<pair<int, int> > Temp = m_SurfaceMesh.GetNodePairs(*itRepeat);
489 NodePairs.insert(NodePairs.end(), Temp.begin(), Temp.end());
490 }
491
492 m_DOFLinks.clear();
493 vector<pair<int, int> >::iterator itNodePair;
494 for (itNodePair = NodePairs.begin(); itNodePair != NodePairs.end(); ++itNodePair)
495 {
496 if (m_Nodes[itNodePair->first].iYarnIndex != m_Nodes[itNodePair->second].iYarnIndex)
497 {
498 // Ignore node pairs where nodes have different yarn indices
499 continue;
500 }
501 for (i=0; i<3; ++i)
502 {
503 pair<int, int> Pair = make_pair(itNodePair->first*3+i, itNodePair->second*3+i);
504// swap(Pair.first, Pair.second);
505 m_DOFLinks.push_back(Pair);
506 }
507 }
508}
509/*
510void CGeometrySolver::OutputSystem(string Filename)
511{
512 ofstream Output(Filename.c_str());
513 int i, j;
514 int iNumNodes = (int)m_ProjectedMesh.GetNumNodes();
515 Output << "[Nodes]" << endl;
516 for (i=0; i<iNumNodes; ++i)
517 {
518 XYZ Pos = m_ProjectedNodes[i].Position;
519 for (j=0; j<(int)m_ProjectedNodes[i].RaisedNodes.size(); ++j)
520 {
521 RAISED_NODE &Node = m_ProjectedNodes[i].RaisedNodes[j];
522 Output << Pos.x << " " << Pos.y << " " << Node.dHeight
523 << " " << Node.dThickness << " " << Node.iYarnIndex << endl;
524 }
525 }
526 Output << "[Springs]" << endl;
527 vector<SPRING>::iterator itSpring;
528 for (itSpring = m_Springs.begin(); itSpring != m_Springs.end(); ++itSpring)
529 {
530 Output << itSpring->iNode1 << " " << itSpring->iNode2 << " " << itSpring->dArea << endl;
531 }
532 Output << "[Surface]" << endl;
533 list<int>::iterator itIndex;
534 list<int> &Indices = m_SurfaceMesh.GetIndices(CMesh::TRI);
535 for (itIndex = Indices.begin(); itIndex != Indices.end(); )
536 {
537 Output << *(itIndex++) << " " << *(itIndex++) << " " << *(itIndex++) << endl;
538 }
539}
540*/
542{
543// int i, j, iNumProjectedNodes = (int)m_ProjectedNodes.size();
544 int iNumNodes = (int)m_Nodes.size();
545 int iNumPlates = (int)m_PlateElements.size();
546 int iDOFs = iNumNodes*3 + iNumPlates;
547 map<pair<int, int>, double> A;
548 map<pair<int, int>, double>::iterator itA;
549 vector<double> x(iDOFs/*, 0.0*/);
550 vector<double> b(iDOFs/*, 0.0*/);
551 int iNumSwitches, iIteration = 0;
552 double dInitialLength, dCurrentLength;
553 double dContactDistance, dSeperationDistance;
554 double dStiffness;
555 bool bEnabled;
556 int i, j, i1, i2, iPlateCount;
557 int iGlob, jGlob;
558 CMatrix KeB, KeT;
559 vector<SPRING>::iterator itSpring;
560 vector<PLATE>::iterator itPlate;
561
562// m_bDebug = true;
563
564 TGLOGINDENT("Solving geometry with " << iNumNodes << " nodes and " << iDOFs << " degrees of freedom");
565 do
566 {
567 ++iIteration;
568 TGLOG("Iteration " << iIteration);
569 iNumSwitches = 0;
570 A.clear();
571 fill(x.begin(), x.end(), 0.0);
572 fill(b.begin(), b.end(), 0.0);
573 // Populate the matrix A with plate elements
574 for (itPlate = m_PlateElements.begin(), iPlateCount=0; itPlate != m_PlateElements.end(); ++itPlate, ++iPlateCount)
575 {
576 int iNodes[3];
577 iNodes[0] = itPlate->iNode1;
578 iNodes[1] = itPlate->iNode2;
579 iNodes[2] = itPlate->iNode3;
580 // Fill in bending element
581 itPlate->BendingElement.GetKeMatrix(KeB);
582 for (i=0; i<10; ++i)
583 {
584 iGlob = iNodes[i/3]*3+i%3;
585 if (i/3==3)
586 iGlob = iNumNodes*3+iPlateCount;
587 assert(iGlob < iDOFs);
588 for (j=0; j<10; ++j)
589 {
590 jGlob = iNodes[j/3]*3+j%3;
591 if (j/3==3)
592 jGlob = iNumNodes*3+iPlateCount;
593 assert(jGlob < iDOFs);
594 A[make_pair(iGlob, jGlob)] += KeB(i, j);
595 }
596 }
597 // Fill in tension element
598 itPlate->TensionElement.GetKeMatrix(KeT);
599 for (i=0; i<3; ++i)
600 {
601 iGlob = iNodes[i]*3;
602 assert(iGlob < iDOFs);
603 for (j=0; j<3; ++j)
604 {
605 jGlob = iNodes[j]*3;
606 assert(jGlob < iDOFs);
607 A[make_pair(iGlob, jGlob)] += KeT(i, j);
608 }
609 }
610 }
611 // Adjust the b matrix to get rid of initial strains
612 // This can be done by doing b = -A*x0 where x0 is the matrix of initial
613 // node positions
614 for (i=0; i<iNumNodes; ++i)
615 {
616 x[i*3] = m_Nodes[i].Position.z;
617 }
618 // This screws things up big time, not sure why...
619/* for (i=0; i<iNumPlates; ++i)
620 {
621 x[iNumNodes+i] = (m_Nodes[m_PlateElements[i].iNode1].Position.z +
622 m_Nodes[m_PlateElements[i].iNode2].Position.z +
623 m_Nodes[m_PlateElements[i].iNode3].Position.z) / 3.0;
624 }*/
625 for (itA = A.begin(); itA != A.end(); ++itA)
626 {
627 b[itA->first.first] -= itA->second * x[itA->first.second];
628 }
629
630 // Populate the matrix A with contact springs
631 for (itSpring = m_Springs.begin(); itSpring != m_Springs.end(); ++itSpring)
632 {
633 i1 = itSpring->iNode1;
634 i2 = itSpring->iNode2;
635 NODE &Node1 = m_Nodes[i1];
636 NODE &Node2 = m_Nodes[i2];
637 dInitialLength = Node2.Position.z - Node1.Position.z;
639 dContactDistance = 0.5*(Node1.GetAdjustedThickness()+Node2.GetAdjustedThickness());
640 else
641 dContactDistance = 0.5*(Node1.dThickness+Node2.dThickness);
642 dCurrentLength = (Node2.Position.z+Node2.dDisplacement)-(Node1.Position.z+Node1.dDisplacement);
643 dSeperationDistance = dCurrentLength-dContactDistance;
644 /*if (abs(dSeperationDistance) < 1e-3)
645 bEnabled = itSpring->bEnabled;
646 else*/ if (dSeperationDistance > 0)
647 bEnabled = false;
648 else
649 bEnabled = true;
650 if (bEnabled != itSpring->bEnabled)
651 {
652 ++iNumSwitches;
653 }
654 itSpring->bEnabled = bEnabled;
655 if (!bEnabled)
656 {
657 dStiffness = m_dDisabledStiffness*itSpring->dArea;
658 }
659 else
660 {
661 dStiffness = m_dContactStiffness*itSpring->dArea;
662 }
663 b[i1*3] += dStiffness*(dInitialLength-dContactDistance);
664 b[i2*3] -= dStiffness*(dInitialLength-dContactDistance);
665 A[make_pair(i1*3, i1*3)] += dStiffness;
666 A[make_pair(i2*3, i2*3)] += dStiffness;
667 A[make_pair(i1*3, i2*3)] -= dStiffness;
668 A[make_pair(i2*3, i1*3)] -= dStiffness;
669 }
670
671 set<int> ConstrainedDOFs;
672
673 // Apply constraints
674 vector<pair<int, double> >::iterator itConstraint;
675 for (itConstraint=m_DOFConstraints.begin(); itConstraint != m_DOFConstraints.end(); ++itConstraint)
676 {
677 if (ConstrainedDOFs.count(itConstraint->first))
678 {
679 TGERROR("Warning: Equation " << itConstraint->first << " is already constrained! Ignoring this boundary condition.");
680 continue;
681 }
682 for (i=0; i<iDOFs; ++i)
683 {
684 pair<int, int> Index = make_pair(itConstraint->first, i);
685 if (i==itConstraint->first)
686 A[Index] = 1;
687 else
688 A.erase(Index);
689 }
690 b[itConstraint->first] = itConstraint->second;
691 ConstrainedDOFs.insert(itConstraint->first);
692 }
693
694 // Apply periodic boundary conditions
695 vector<pair<int, int> >::iterator itDOFLink;
696 for (itDOFLink=m_DOFLinks.begin(); itDOFLink != m_DOFLinks.end(); ++itDOFLink)
697// if (0)
698 {
699 int iRemovedDOF = itDOFLink->first;
700 int iCombinedDOF = itDOFLink->second;
701 if (ConstrainedDOFs.count(iRemovedDOF))
702 {
703 swap(iRemovedDOF, iCombinedDOF);
704 }
705 if (ConstrainedDOFs.count(iRemovedDOF))
706 {
707 TGERROR("Warning: Degrees of freedom " << itDOFLink->first << " and " << itDOFLink->second <<
708 " are already constrained! Ignoring this boundary condition.");
709 continue;
710 }
711 for (i=0; i<iDOFs; ++i)
712 {
713 pair<int, int> Index = make_pair(iRemovedDOF, i);
714 if (!ConstrainedDOFs.count(iCombinedDOF) && A.count(Index))
715 {
716 // Combine the stiffnesses from the removed DOF and the remaining one
717 A[make_pair(iCombinedDOF, i)] += A[Index];
718 }
719 if (i==itDOFLink->first)
720 A[Index] = 1;
721 else if (i==itDOFLink->second)
722 A[Index] = -1;
723 else
724 A.erase(Index);
725 }
726 // Combine the forces from the removed DOF and the remaining one
727 if (!ConstrainedDOFs.count(iCombinedDOF))
728 b[iCombinedDOF] += b[iRemovedDOF];
729 b[iRemovedDOF] = 0;
730 ConstrainedDOFs.insert(iRemovedDOF);
731 }
732
733 /*if (m_bDebug && iIteration == 1)
734 {
735 SaveToVTK("c://Program Files//TexGen//GeometrySolver//Initial");
736 }*/
737
738 // Solve this sucker with CSparse
739 cs* csT = cs_spalloc(iNumNodes, iNumNodes, A.size(), 1, 1);
740 for (itA = A.begin(); itA != A.end(); ++itA)
741 {
742 cs_entry(csT, itA->first.first, itA->first.second, itA->second);
743 }
744 cs* csA = cs_compress(csT);
745 cs_spfree(csT);
746 x = b;
747 int iSuccess = cs_lusol(1, csA, &x.front(), 1);
748 cs_spfree(csA);
749
750 if (!iSuccess)
751 {
752 TGERROR("Solve failed");
753 return 0;
754 }
755
756 for (i=0; i<iNumNodes; ++i)
757 {
758 m_Nodes[i].dDisplacement = x[i*3];
759 m_Nodes[i].dThetaX = x[i*3+1];
760 m_Nodes[i].dThetaY = x[i*3+2];
761 }
762 TGLOG("Number of switches: " << iNumSwitches);
763// break;
764 if (m_bDebug)
765 {
766 stringstream IterFileName;
767 IterFileName << "c://Program Files//TexGen//GeometrySolver//iter." << setfill('0') << setw(4) << iIteration;
768 SaveToVTK(IterFileName.str());
769 }
770 } while (iIteration == 1 || iNumSwitches > 0);
771
772 return iIteration;
773}
774
775void CGeometrySolver::SaveToVTK(string Filename)
776{
777 CMesh CopiedMesh = m_SurfaceMesh;
778 vector<TiXmlElement> AdditionalData;
779
780 CMeshData<double> Displacements("Displacements", CMeshDataBase::NODE);
781 CMeshData<double> ThetaX("ThetaX", CMeshDataBase::NODE);
782 CMeshData<double> ThetaY("ThetaY", CMeshDataBase::NODE);
783 CMeshData<double> Thicknesses("Thicknesses", CMeshDataBase::NODE);
784 CMeshData<double> AdjustedThicknesses("AdjustedThicknesses", CMeshDataBase::NODE);
785 CMeshData<unsigned char> YarnIndex("YarnIndex", CMeshDataBase::NODE);
786
787 int i;
788 for (i=0; i<(int)m_Nodes.size(); ++i)
789 {
790 Displacements.m_Data.push_back(m_Nodes[i].dDisplacement);
791 ThetaX.m_Data.push_back(m_Nodes[i].dThetaX);
792 ThetaY.m_Data.push_back(m_Nodes[i].dThetaY);
793 Thicknesses.m_Data.push_back(m_Nodes[i].dThickness);
794 AdjustedThicknesses.m_Data.push_back(m_Nodes[i].GetAdjustedThickness());
795 YarnIndex.m_Data.push_back(m_Nodes[i].iYarnIndex);
796 }
797
798 CMeshData<XYZ> YarnTangent("YarnTangent", CMeshDataBase::ELEMENT);
799 CMeshData<int> CellYarnIndex("YarnIndex", CMeshDataBase::ELEMENT);
800 vector<PLATE>::iterator itPlate;
801 for (itPlate = m_PlateElements.begin(); itPlate != m_PlateElements.end(); ++itPlate)
802 {
803 YarnTangent.m_Data.push_back(itPlate->BendingElement.GetFibreDirection());
804 CellYarnIndex.m_Data.push_back(itPlate->iYarnIndex);
805 }
806
807 vector<SPRING>::iterator itSpring;
808 for (itSpring = m_Springs.begin(); itSpring != m_Springs.end(); ++itSpring)
809 {
810 if (itSpring->bEnabled)
811 {
812 CopiedMesh.GetIndices(CMesh::LINE).push_back(itSpring->iNode1);
813 CopiedMesh.GetIndices(CMesh::LINE).push_back(itSpring->iNode2);
814 }
815 YarnTangent.m_Data.push_back(XYZ());
816 CellYarnIndex.m_Data.push_back(-1);
817 }
818
819 vector<CMeshDataBase*> MeshData;
820
821 MeshData.push_back(&Displacements);
822 MeshData.push_back(&ThetaX);
823 MeshData.push_back(&ThetaY);
824 MeshData.push_back(&Thicknesses);
826 MeshData.push_back(&AdjustedThicknesses);
827 MeshData.push_back(&YarnIndex);
828 MeshData.push_back(&YarnTangent);
829 MeshData.push_back(&CellYarnIndex);
830
831 CopiedMesh.SaveToVTK(Filename, &MeshData);
832}
833
835{
836 if (m_pTextile)
838}
839
841{
842 if (m_pTextile)
844 else
845 return NULL;
846}
847
848double CGeometrySolver::GetDisplacement(XYZ Pos, int iYarn, XYZ &Disp) const
849{
850 // Find out what the displacement is of the yarn at given position
851 const list<int> &Indices = m_SurfaceMesh.GetIndices(CMesh::TRI);
852 list<int>::const_iterator itIndex;
853 int i1, i2, i3;
854 double dMin;
855 double dAccuracy = -1;
856 bool bFirst = true;
857 for (itIndex = Indices.begin(); itIndex != Indices.end(); )
858 {
859 i1 = *(itIndex++);
860 i2 = *(itIndex++);
861 i3 = *(itIndex++);
862 const NODE &N1 = m_Nodes[i1];
863 const NODE &N2 = m_Nodes[i2];
864 const NODE &N3 = m_Nodes[i3];
865 if (N1.iYarnIndex != iYarn || N2.iYarnIndex != iYarn || N3.iYarnIndex != iYarn)
866 continue;
868 Convert(N2.Position), Convert(N3.Position), Convert(Pos));
869 dMin = min(Weights.x, Weights.y);
870 dMin = min(dMin, Weights.z);
871 if (bFirst || dMin > dAccuracy)
872 {
873 // If all barycentric coordinates are non-negative the point lies inside the triangle
874 dAccuracy = dMin;
875 Disp.z = Weights.x * N1.dDisplacement;
876 Disp.z += Weights.y * N2.dDisplacement;
877 Disp.z += Weights.z * N3.dDisplacement;
878 bFirst = false;
879 }
880 }
881 return dAccuracy;
882}
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
#define TGLOGINDENT(MESSAGE)
Combines the TGLOG macro and TGLOGAUTOINDENT macro in one.
Definition: Logger.h:68
#define TGERROR(MESSAGE)
Macros used to report the file name and line number to the TexGenError and TexGenLog functions.
Definition: Logger.h:29
#define TGLOG(MESSAGE)
Definition: Logger.h:36
#define NULL
Definition: ShinyConfig.h:50
#define TEXGEN
Helper macro to get the texgen instance.
Definition: TexGen.h:76
vector< CMesh > m_YarnMeshes
Definition: BasicVolumes.h:114
vector< PROJECTED_REGION > m_ProjectedRegions
Definition: BasicVolumes.h:115
vector< int > m_TriangleRegions
Definition: BasicVolumes.h:119
bool CreateBasicVolumes(CTextile &Textile)
void SetPeriodic(bool bPeriodic)
Definition: BasicVolumes.h:44
bool GetMeshVerticalBounds(const CMesh &Mesh, XYZ Point, double &dMinZ, double &dMaxZ, bool bForceFind=false)
const CMesh & GetMesh() const
Get the mesh representing the domain as a surface mesh.
Definition: Domain.h:73
vector< XYZ > GetTranslations(const CYarn &Yarn) const
Get the translation vectors necessary to fully fill the domain.
Definition: Domain.cpp:83
void SetFibreDirection(XYZ FibreDirection)
Definition: Elements.h:43
void SetNodeCoordinates(const CMatrix &P)
Definition: Elements.cpp:31
void SetLongitudinalBendingModulus(double E1)
Definition: Elements.h:103
void SetTransverseBendingModulus(double E2)
Definition: Elements.h:106
void SetTensileStress(double E)
Definition: Elements.h:145
CTextile * GetDeformedCopyOfTextile()
Create a copy of the textile and deform it, leaving the original textile intact.
void SaveToVTK(string Filename)
Save the results to a VTK file.
vector< pair< int, double > > m_DOFConstraints
void DeformTextile()
Deform the textile with the results.
vector< pair< int, int > > m_DOFLinks
void SetTransverseBendingModulus(double dBendingModulus)
void SetLongitudinalBendingModulus(double dBendingModulus)
vector< SPRING > m_Springs
vector< PLATE > m_PlateElements
void ApplyPeriodicBoundaryConditions(vector< XYZ > Repeats)
double GetDisplacement(XYZ Pos, int iYarn, XYZ &Disp) const
void RaiseNodes(int iIndex)
double GetArea(int iIndex)
int SolveSystem()
Solve the system of equations.
void SetDisabledStiffness(double dDisabledStiffness)
void SetTensileStress(double dTensileStress)
vector< PROJECTED_NODE > m_ProjectedNodes
double GetAverageLength(int iIndex)
bool CreateSystem(CTextile &Textile)
Create the finite element system of equations for a given textile.
void SetContactStiffness(double dContactStiffness)
Class to represent a matrix and perform various operations on it.
Definition: Matrix.h:33
vector< T > m_Data
Definition: MeshData.h:87
Defines the nodes and elements of a surface or volume mesh.
Definition: Mesh.h:58
vector< pair< int, int > > GetNodePairs(XYZ Vector, const double Tolerance=1e-6) const
Return a list of node pairs (A, B) where A == B + Vector.
Definition: Mesh.cpp:463
const int AddNode(XYZ Node)
Append a node to the list of nodes, the integer returns the index of the node
Definition: Mesh.cpp:2624
const XYZ & GetNode(int iIndex) const
Get the node with given ID.
Definition: Mesh.cpp:2636
bool SaveToVTK(string Filename, const vector< CMeshDataBase * > *pMeshData=NULL) const
Save the mesh to VTK unstructured grid file format (.vtu)
Definition: Mesh.cpp:2348
static int GetNumNodes(ELEMENT_TYPE Type)
Get the number of nodes a particular element type contains.
Definition: Mesh.h:81
const list< int > & GetIndices(ELEMENT_TYPE ElemType) const
Get the element indices of a given element type.
Definition: Mesh.cpp:2671
pair< XYZ, XYZ > GetAABB(double dGrowDistance=0) const
Get an axis aligned bounding box for the mesh.
Definition: Mesh.cpp:340
void Clear()
Empty mesh nodes and indices.
Definition: Mesh.cpp:1448
void ConvertToSegmentMesh()
Convert all elements to segments.
Definition: Mesh.cpp:599
Object container to help handle memory management issues.
CTextile * GetDeformedCopyOfTextile(CTextile &Textile, bool bDeformDomain=true)
virtual void DeformTextile(CTextile &Textile, bool bDeformDomain=true)
Represents a textile cell containing yarns.
Definition: Textile.h:39
const CDomain * GetDomain() const
Definition: Textile.h:287
int GetNumYarns() const
Definition: Textile.cpp:704
const CYarn * GetYarn(int iIndex) const
Definition: Textile.cpp:693
Represents a yarn consisting of master nodes, section and interpolation function.
Definition: Yarn.h:49
const CInterpolation * GetInterpolation() const
Definition: Yarn.h:450
void AssignInterpolation(const CInterpolation &Interpolation)
Assign an interpolation function to the yarn.
Definition: Yarn.cpp:641
bool PointInsideYarn(const XYZ &Point, XYZ *pTangent=NULL, XY *pLoc=NULL, double *pVolumeFraction=NULL, double *pDistanceToSurface=NULL, double dTolerance=1e-9, XYZ *pOrientation=NULL, XYZ *pUp=NULL, bool bSurface=false) const
Determine if the given point lies within the yarn (this function doesn't take the repeats into accoun...
Definition: Yarn.cpp:1336
Namespace containing a series of customised math operations not found in the standard c++ library.
XYZ GetBarycentricCoordinates(const XY &P1, const XY &P2, const XY &P3, const XY &P)
Get the barycentric coordinates of a point lying on a triangle.
Definition: mymath.h:1421
XY Convert(const XYZ &Val)
Definition: mymath.h:144
double GetLength(const XYZ &Point1, const XYZ &Point2)
Get the length between two points.
Definition: mymath.h:540
CElementTriBending BendingElement
CElementTriTension TensionElement
Struct for representing points in 3D space.
Definition: mymath.h:56
double z
Definition: mymath.h:57
double x
Definition: mymath.h:57
double y
Definition: mymath.h:57