G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsGeoUtils.hpp
Go to the documentation of this file.
1
15#pragma once
16
18
19#include <gsCore/gsField.h>
20#include <gsCore/gsFuncData.h>
22#include <gsNurbs/gsBSpline.h>
28
34
35namespace gismo
36{
37
38//-----------------------------------//
39//--------- Mesh Analysis -----------//
40//-----------------------------------//
41
42template <class T>
43void plotGeometry(gsMultiPatch<T> const & domain, std::string fileName, index_t numSamples)
44{
45 std::string fileNameOnly = gsFileManager::getFilename(fileName);
46 gsParaviewCollection collectionMesh(fileName + "_mesh");
47 gsParaviewCollection collectionJac(fileName + "_jac");
48 index_t res;
49
50 bool plotJac = true;
51 if (numSamples == 0)
52 plotJac = false;
53
55 for (size_t p = 0; p < domain.nPatches(); ++p)
56 dets.addPiecePointer(new gsDetFunction<T>(domain,p));
57 gsField<> detField(domain,dets,true);
58 std::map<std::string,const gsField<> *> fields;
59 fields["Jacobian"] = &detField;
60 gsWriteParaviewMultiPhysics(fields,fileName,numSamples,true);
61
62 for (size_t p = 0; p < domain.nPatches(); ++p)
63 {
64 collectionMesh.addPart(fileNameOnly + "_mesh.vtp",0,"Mesh",p);
65 if (plotJac)
66 collectionJac.addPart(fileNameOnly + ".vts",0,"Solution",p);
67 else
68 res = system(("rm " + fileName + util::to_string(p) + ".vts").c_str());
69 GISMO_ENSURE(res == 0, "Problems with deleting files\n");
70 }
71 res = system(("rm " + fileName + ".pvd").c_str());
72 GISMO_ENSURE(res == 0, "Problems with deleting files\n");
73 (void)res;
74
75 collectionMesh.save();
76 if (plotJac)
77 collectionJac.save();
78}
79
80template <class T>
81void plotGeometry(const gsMultiPatch<T> & domain, std::string const & fileName,
82 gsParaviewCollection & collection, index_t step)
83{
84 for (size_t p = 0; p < domain.nPatches(); ++p)
85 {
86 gsMesh<T> mesh(domain.basis(p),8);
87 domain.patch(p).evaluateMesh(mesh);
88 std::string patchFileName = fileName + util::to_string(step) + "_" + util::to_string(p);
89 gsWriteParaview(mesh,patchFileName,false);
90 collection.addPart(gsFileManager::getFilename(patchFileName),step,"Solution",p);
91 }
92}
93
94template <class T>
95void plotDeformation(const gsMultiPatch<T> & initDomain, const std::vector<gsMultiPatch<T> > & displacements,
96 std::string fileName, index_t numSamplingPoints)
97{
98 gsInfo << "Plotting deformed configurations...\n";
99
100 std::string fileNameOnly = gsFileManager::getFilename(fileName);
101 gsParaviewCollection collectionMesh(fileName + "_mesh");
102 gsParaviewCollection collectionJac(fileName + "_jac");
103 index_t res;
104
105 gsMultiPatch<T> configuration;
106 for (size_t p = 0; p < initDomain.nPatches(); ++p)
107 configuration.addPatch(initDomain.patch(p).clone());
108
110 for (size_t p = 0; p < configuration.nPatches(); ++p)
111 dets.addPiecePointer(new gsDetFunction<T>(configuration,p));
112
113 bool plotJac = true;
114 if (numSamplingPoints == 0)
115 plotJac = false;
116
117 gsProgressBar bar;
118 bar.display(0, displacements.size());
119
120 gsField<T> detField(configuration,dets,true);
121 std::map<std::string,const gsField<T> *> fields;
122 fields["Jacobian"] = &detField;
123 gsWriteParaviewMultiPhysics(fields,fileName+util::to_string(0),numSamplingPoints == 0 ? 1 : numSamplingPoints,true);
124
125 for (size_t p = 0; p < configuration.nPatches(); ++p)
126 {
127 collectionMesh.addPart(fileNameOnly + util::to_string(0) + util::to_string(p) + "_mesh.vtp",0,"Mesh",p);
128 if (plotJac)
129 collectionJac.addPart(fileNameOnly + util::to_string(0) + util::to_string(p) + ".vts",0,"Solution",p);
130 else
131 {
132 res = system(("rm " + fileName + util::to_string(0) + util::to_string(p) + ".vts").c_str());
133 GISMO_ENSURE(res == 0, "Problems with deleting files\n");
134 }
135 }
136 res = system(("rm " + fileName + util::to_string(0) + ".pvd").c_str());
137 GISMO_ENSURE(res == 0, "Problems with deleting files\n");
138
139 for (size_t s = 0; s < displacements.size(); ++s)
140 {
141
142 bar.display(s+1, displacements.size());
143
144 for (size_t p = 0; p < configuration.nPatches(); ++p)
145 {
146 configuration.patch(p).coefs() += displacements[s].patch(p).coefs();
147 if (s > 0)
148 configuration.patch(p).coefs() -= displacements[s-1].patch(p).coefs();
149 }
150
151 gsWriteParaviewMultiPhysics(fields,fileName+util::to_string(s+1),numSamplingPoints == 0 ? 1 : numSamplingPoints,true);
152 for (size_t p = 0; p < configuration.nPatches(); ++p)
153 {
154 collectionMesh.addPart(fileNameOnly + util::to_string(s+1) + util::to_string(p) + "_mesh.vtp",s+1,"Mesh",p);
155 if (plotJac)
156 collectionJac.addPart(fileNameOnly + util::to_string(s+1) + util::to_string(p) + ".vts",s+1,"Solution",p);
157 else
158 {
159 res = system(("rm " + fileName + util::to_string(s+1) + util::to_string(p) + ".vts").c_str());
160 GISMO_ENSURE(res == 0, "Problems with deleting files\n");
161 }
162 }
163 res = system(("rm " + fileName + util::to_string(s+1) + ".pvd").c_str());
164 GISMO_ENSURE(res == 0, "Problems with deleting files\n");
165 }
166
167 collectionMesh.save();
168 if (plotJac)
169 collectionJac.save();
170
171 (void)res;
172}
173
174
175template <class T>
176void plotDeformation(const gsMultiPatch<T> & initDomain, const gsMultiPatch<T> & displacement,
177 std::string const & fileName, gsParaviewCollection & collection, index_t step)
178{
179 GISMO_ENSURE(initDomain.nPatches() == displacement.nPatches(), "Wrong number of patches! Geometry has " +
180 util::to_string(initDomain.nPatches()) + " patches. Displacement has " + util::to_string(displacement.nPatches()) + " patches.");
181
182 gsMultiPatch<T> configuration;
183 for (size_t p = 0; p < initDomain.nPatches(); ++p)
184 {
185 configuration.addPatch(initDomain.patch(p).clone());
186 configuration.patch(p).coefs() += displacement.patch(p).coefs();
187 }
188
189 for (size_t p = 0; p < configuration.nPatches(); ++p)
190 {
191 gsMesh<T> mesh(configuration.basis(p),8);
192 configuration.patch(p).evaluateMesh(mesh);
193 std::string patchFileName = fileName + util::to_string(step) + "_" + util::to_string(p);
194 gsWriteParaview(mesh,patchFileName,false);
195 collection.addPart(gsFileManager::getFilename(patchFileName),step,"Solution",p);
196 }
197}
198
199template <class T>
201{
202 index_t corruptedPatch = -1;
203 bool continueIt = true;
204 for (size_t p = 0; p < domain.nPatches() && continueIt; ++p)
205 {
206#pragma omp parallel
207 {
208 gsMapData<T> md;
209 md.flags = NEED_DERIV;
210 gsMatrix<T> points;
211
212 gsVector<index_t> numNodes(domain.dim());
213 for (short_t i = 0; i < domain.dim(); ++i)
214 numNodes.at(i) = domain.basis(p).degree(i)+1;
215 gsQuadRule<T> quRule = gsQuadrature::get<T>(gsQuadrature::GaussLegendre,numNodes);
216
217 typename gsBasis<T>::domainIter domIt = domain.basis(p).makeDomainIterator(boundary::none);
218#ifdef _OPENMP
219 const int tid = omp_get_thread_num();
220 const int nt = omp_get_num_threads();
221 for ( domIt->next(tid); domIt->good() && continueIt; domIt->next(nt) )
222#else
223 for (; domIt->good() && continueIt; domIt->next() )
224#endif
225 {
226 genSamplingPoints(domIt->lowerCorner(),domIt->upperCorner(),quRule,points);
227 md.points = points;
228 domain.patch(p).computeMap(md);
229 for (index_t q = 0; q < points.cols() && continueIt; ++q)
230
231 if (md.jacobian(q).determinant() <= 0)
232 {
233 gsInfo << "Bad patch: " << p << "\nBad point:\n" << points.col(q) << "\nDet: " << md.jacobian(q).determinant() << std::endl;
234 corruptedPatch = p;
235 continueIt = false;
236 }
237 }
238 }
239 }
240 return corruptedPatch;
241}
242
243
244template <class T>
245index_t checkDisplacement(gsMultiPatch<T> const & domain, gsMultiPatch<T> const & displacement)
246{
247 index_t corruptedPatch = -1;
248 bool continueIt = true;
249 for (size_t p = 0; p < domain.nPatches() && continueIt; ++p)
250 {
251#pragma omp parallel
252 {
253 gsMapData<T> mdG, mdU;
254 mdG.flags = NEED_DERIV;
255 mdU.flags = NEED_DERIV;
256 gsMatrix<T> points;
257
258 gsVector<index_t> numNodes(domain.dim());
259 for (short_t i = 0; i < domain.dim(); ++i)
260 numNodes.at(i) = displacement.basis(p).degree(i)+1;
261 gsQuadRule<T> quRule = gsQuadrature::get<T>(gsQuadrature::GaussLegendre,numNodes);
262
263 typename gsBasis<T>::domainIter domIt = displacement.basis(p).makeDomainIterator(boundary::none);
264#ifdef _OPENMP
265 const int tid = omp_get_thread_num();
266 const int nt = omp_get_num_threads();
267 for ( domIt->next(tid); domIt->good() && continueIt; domIt->next(nt) )
268#else
269 for (; domIt->good() && continueIt; domIt->next() )
270#endif
271 {
272 genSamplingPoints(domIt->lowerCorner(),domIt->upperCorner(),quRule,points);
273 mdG.points = points;
274 mdU.points = points;
275 domain.patch(p).computeMap(mdG);
276 displacement.patch(p).computeMap(mdU);
277 for (index_t q = 0; q < points.cols() && continueIt; ++q)
278 {
279 gsMatrix<T> physDispJac = mdU.jacobian(q)*(mdG.jacobian(q).cramerInverse());
280 gsMatrix<T> F = gsMatrix<T>::Identity(domain.dim(),domain.dim()) + physDispJac;
281 if (F.determinant() <= 0)
282 {
283 gsInfo << "Bad patch: " << p << "\nBad point:\n" << points.col(q) << "\nDet: " << F.determinant() << std::endl;
284 corruptedPatch = p;
285 continueIt = false;
286 }
287 }
288 }
289 }
290 }
291 return corruptedPatch;
292}
293
294template <class T>
295T normL2(gsMultiPatch<T> const & domain, gsMultiPatch<T> const & solution)
296{
297 T norm = 0;
298 for (size_t p = 0; p < domain.nPatches(); ++p)
299 {
300#pragma omp parallel
301 {
303 gsMatrix<T> values, quNodes;
304 gsVector<T> quWeights;
305
306 gsVector<index_t> numNodes(domain.dim());
307 for (short_t i = 0; i < domain.dim(); ++i)
308 numNodes.at(i) = solution.basis(p).degree(i)+1;
309 gsQuadRule<T> quRule = gsQuadrature::get<T>(gsQuadrature::GaussLegendre,numNodes);
310
311 typename gsBasis<T>::domainIter domIt = solution.basis(p).makeDomainIterator(boundary::none);
312#ifdef _OPENMP
313 const int tid = omp_get_thread_num();
314 const int nt = omp_get_num_threads();
315 for ( domIt->next(tid); domIt->good(); domIt->next(nt) )
316#else
317 for (; domIt->good(); domIt->next() )
318#endif
319 {
320 quRule.mapTo( domIt->lowerCorner(), domIt->upperCorner(), quNodes, quWeights );
321 mdGeo.points = quNodes;
322 domain.patch(p).computeMap(mdGeo);
323 solution.patch(p).eval_into(quNodes,values);
324 T tempNorm = 0;
325 for (index_t q = 0; q < quNodes.cols(); ++q)
326 tempNorm += mdGeo.measure(q)*quWeights.at(q)*(values.col(q).transpose()*values.col(q))(0,0);
327#pragma omp critical
328 norm += tempNorm;
329 }
330 }
331 }
332 return sqrt(norm);
333}
334
335template <class T>
337{
338 std::vector<T> maxs, mins;
339 gsMapData<T> md;
340 md.flags = NEED_DERIV;
341 gsMatrix<T> points;
342
343 for (size_t p = 0; p < domain.nPatches(); ++p)
344 {
345 gsVector<index_t> numNodes(domain.dim());
346 for (short_t i = 0; i < domain.dim(); ++i)
347 numNodes.at(i) = domain.basis(p).degree(i)+1;
348 gsQuadRule<T> quRule = gsQuadrature::get<T>(gsQuadrature::GaussLegendre,numNodes);
349
350 typename gsBasis<T>::domainIter domIt = domain.basis(p).makeDomainIterator(boundary::none);
351 for (; domIt->good(); domIt->next())
352 {
353 genSamplingPoints(domIt->lowerCorner(),domIt->upperCorner(),quRule,points);
354 md.points = points;
355 domain.patch(p).computeMap(md);
356
357 T min = md.jacobian(0).determinant();
358 T max = min;
359 for (index_t q = 1; q < points.cols(); ++q)
360 {
361 T jac = md.jacobian(q).determinant();
362 if (jac > max)
363 max = jac;
364 if (jac < min)
365 min = jac;
366 }
367
368 maxs.push_back(max);
369 mins.push_back(min);
370 }
371 }
372
373 return *(std::min_element(mins.begin(),mins.end())) / *(std::max_element(maxs.begin(),maxs.end()));
374}
375
376template <class T>
377T displacementJacRatio(const gsMultiPatch<T> & domain,const gsMultiPatch<T> & displacement)
378{
379 std::vector<T> maxs, mins;
380 gsMapData<T> mdG, mdU;
381 mdG.flags = NEED_DERIV;
382 mdU.flags = NEED_DERIV;
383 gsMatrix<T> points;
384 size_t dim = domain.parDim();
385
386 for (size_t p = 0; p < displacement.nPatches(); ++p)
387 {
388 gsVector<index_t> numNodes(domain.dim());
389 for (short_t i = 0; i < domain.dim(); ++i)
390 numNodes.at(i) = displacement.basis(p).degree(i)+1;
391 gsQuadRule<T> quRule = gsQuadrature::get<T>(gsQuadrature::GaussLegendre,numNodes);
392
393 typename gsBasis<T>::domainIter domIt = domain.basis(p).makeDomainIterator(boundary::none);
394 for (; domIt->good(); domIt->next())
395 {
396 genSamplingPoints(domIt->lowerCorner(),domIt->upperCorner(),quRule,points);
397 mdG.points = points;
398 mdU.points = points;
399 domain.patch(p).computeMap(mdG);
400 displacement.patch(p).computeMap(mdU);
401
402 T minJ = (gsMatrix<T>::Identity(dim,dim) + mdU.jacobian(0)*(mdG.jacobian(0).cramerInverse())).determinant();
403 T maxJ = minJ;
404 for (int q = 1; q < points.cols(); ++q)
405 {
406 T J = (gsMatrix<T>::Identity(dim,dim) + mdU.jacobian(q)*(mdG.jacobian(q).cramerInverse())).determinant();
407 if (J > maxJ)
408 maxJ = J;
409 if (J < minJ)
410 minJ = J;
411 }
412
413 maxs.push_back(maxJ);
414 mins.push_back(minJ);
415 }
416 }
417
418 return *(std::min_element(mins.begin(),mins.end())) / *(std::max_element(maxs.begin(),maxs.end()));
419}
420
421template <class T>
422void genSamplingPoints(const gsVector<T> & lower, const gsVector<T> & upper,
423 const gsQuadRule<T> & quRule, gsMatrix<T> & points)
424{
425 gsMatrix<T> quadPoints;
426 gsVector<T> tempVector; // temporary argument for the gsQuadrule::mapTo function
427 quRule.mapTo(lower,upper,quadPoints,tempVector);
428
429 gsVector<unsigned> nPoints(quadPoints.rows());
430 for (index_t d = 0; d < quadPoints.rows(); ++d)
431 nPoints.at(d) = 2;
432 gsMatrix<T> corners = gsPointGrid(lower,upper,nPoints);
433
434 points.resize(quadPoints.rows(),quadPoints.cols()+corners.cols());
435 points << quadPoints,corners;
436}
437
438template <class T>
440{
441 GISMO_ENSURE(dir >= 0 && dir <= geo.parDim(),"Invalid parametric direction: " + util::to_string(dir)+
442 ", geometry dimension: " + util::to_string(geo.parDim()));
443 switch (geo.parDim())
444 {
445 case 1: return curveLength<T>(geo);
446 case 2:
447 {
448 switch (dir)
449 {
450 case 0:
451 {
452 typename gsGeometry<T>::uPtr sideS = geo.boundary(boundary::south);
453 typename gsGeometry<T>::uPtr sideN = geo.boundary(boundary::north);
454 return (curveLength<T>(*sideS) + curveLength<T>(*sideN))/2;
455 }
456 case 1:
457 {
458 typename gsGeometry<T>::uPtr sideW = geo.boundary(boundary::west);
459 typename gsGeometry<T>::uPtr sideE = geo.boundary(boundary::east);
460 return (curveLength<T>(*sideW) + curveLength<T>(*sideE))/2;
461 }
462 default: return 0.;
463 }
464 }
465 case 3:
466 {
467 switch (dir)
468 {
469 case 0:
470 {
471 typename gsGeometry<T>::uPtr sideB = geo.boundary(boundary::back);
472 typename gsGeometry<T>::uPtr sideF = geo.boundary(boundary::front);
473 typename gsGeometry<T>::uPtr edgeBS = sideB->boundary(boundary::south);
474 typename gsGeometry<T>::uPtr edgeBN = sideB->boundary(boundary::north);
475 typename gsGeometry<T>::uPtr edgeFS = sideF->boundary(boundary::south);
476 typename gsGeometry<T>::uPtr edgeFN = sideF->boundary(boundary::north);
477 return (curveLength<T>(*edgeBS) + curveLength<T>(*edgeBN) +
478 curveLength<T>(*edgeFS) + curveLength<T>(*edgeFN))/4;
479 }
480 case 1:
481 {
482 typename gsGeometry<T>::uPtr sideB = geo.boundary(boundary::back);
483 typename gsGeometry<T>::uPtr sideF = geo.boundary(boundary::front);
484 typename gsGeometry<T>::uPtr edgeBW = sideB->boundary(boundary::west);
485 typename gsGeometry<T>::uPtr edgeBE = sideB->boundary(boundary::east);
486 typename gsGeometry<T>::uPtr edgeFW = sideF->boundary(boundary::west);
487 typename gsGeometry<T>::uPtr edgeFE = sideF->boundary(boundary::east);
488 return (curveLength<T>(*edgeBW) + curveLength<T>(*edgeBE) +
489 curveLength<T>(*edgeFW) + curveLength<T>(*edgeFE))/4;
490 }
491 case 2:
492 {
493 typename gsGeometry<T>::uPtr sideN = geo.boundary(boundary::north);
494 typename gsGeometry<T>::uPtr sideS = geo.boundary(boundary::south);
495 typename gsGeometry<T>::uPtr edgeNW = sideN->boundary(boundary::west);
496 typename gsGeometry<T>::uPtr edgeNE = sideN->boundary(boundary::east);
497 typename gsGeometry<T>::uPtr edgeSW = sideS->boundary(boundary::west);
498 typename gsGeometry<T>::uPtr edgeSE = sideS->boundary(boundary::east);
499 return (curveLength<T>(*edgeNW) + curveLength<T>(*edgeNE) +
500 curveLength<T>(*edgeSW) + curveLength<T>(*edgeSE))/4;
501 }
502 default: return 0.;
503 }
504 }
505 default: return 0.;
506 }
507}
508
509template <class T>
511{
512 GISMO_ENSURE(geo.parDim() == 1,"This is not a curve! Dim: " + util::to_string(geo.parDim()));
513 T length = 0.;
514
515 gsVector<index_t> numNodes(1);
516 numNodes << geo.basis().degree(0)+1;
517 gsQuadRule<T> quRule = gsQuadrature::get<T>(gsQuadrature::GaussLegendre,numNodes);
518 gsMatrix<T> qPoints;
519 gsVector<T> qWeights;
520 gsMapData<T> md;
521 md.flags = NEED_DERIV;
522
523 typename gsBasis<>::domainIter domIt = geo.basis().makeDomainIterator(boundary::none);
524 for (; domIt->good(); domIt->next())
525 {
526 quRule.mapTo(domIt->lowerCorner(),domIt->upperCorner(),qPoints,qWeights);
527 md.points = qPoints;
528 geo.computeMap(md);
529 for (index_t q = 0; q < qWeights.rows(); ++q)
530 length += qWeights.at(q)*md.jacobian(q).norm();
531 }
532 return length;
533}
534
535template <class T>
536gsVector<unsigned> distributePoints(const gsGeometry<T> & geo, unsigned numPoints)
537{
538 short_t dim = geo.parDim();
539 GISMO_ENSURE(dim >= 1 && dim <= 3,"Invalid patch dimension: " + util::to_string(dim));
540 gsVector<unsigned> numPointsPerDir(dim);
541 gsVector<T> parLengths(dim);
542
543 T volume = 1.;
544 for (short_t d = 0; d < dim; ++d)
545 {
546 parLengths.at(d) = patchLength<T>(geo,d);
547 volume *= parLengths.at(d);
548 }
549
550 T unit = pow(1.0*numPoints/volume,1./geo.parDim());
551 for (short_t d = 0; d < geo.parDim(); ++d)
552 numPointsPerDir.at(d) = math::ceil(unit*parLengths.at(d)) > 1 ? math::ceil(unit*parLengths.at(d)) : 2;
553 return numPointsPerDir;
554}
555
556
557//--------------------------------------------------------------------//
558//------------------------ Modelling ---------------------------------//
559//--------------------------------------------------------------------//
560
561template<class T>
563 index_t additionalPoints, index_t degree,
564 index_t numSamples)
565{
566 GISMO_ENSURE(curve.domainDim() == 1 ,"That's not a curve.\n");
567 index_t deg = degree == 0 ? curve.degree(0) : degree;
568 index_t num = deg + 1 + additionalPoints;
569
570 gsKnotVector<T> knots(0.0,1.0, num - deg - 1, deg + 1);
571 gsKnotVector<T> knotVector(knots);
572 gsBSplineBasis<T> basis(knotVector);
573
574 gsMatrix<T> params(1,numSamples);
575 for (index_t p = 0; p < numSamples; ++p)
576 params.at(p) = 1.*p/(numSamples-1);
577
578 gsMatrix<T> curveValues;
579 curve.eval_into(params,curveValues);
580
581 gsMatrix<T> lens(numSamples,1);
582 lens.at(0) = 0.;
583 for (index_t p = 1; p < numSamples; ++p)
584 lens.at(p) = lens.at(p-1) + distance(curveValues,p,curveValues,p-1,true);
585
586 gsMatrix<T> lenParams(1,numSamples);
587 for (index_t p = 0; p < numSamples; ++p)
588 lenParams.at(p) = lens.at(p)/lens.at(numSamples-1);
589
590 typename gsGeometry<T>::uPtr simpleCurve = fittingDirichlet(lenParams,curveValues,basis);
591
592 simpleCurve->eval_into(params,curveValues);
593 for (index_t p = 1; p < numSamples; ++p)
594 lens.at(p) = lens.at(p-1) + distance(curveValues,p,curveValues,p-1,true);
595
596 for (index_t p = 0; p < numSamples; ++p)
597 lenParams.at(p) = lens.at(p)/lens.at(numSamples-1);
598
599 return fittingDirichlet(lenParams,curveValues,curve.basis());
600}
601
602template<class T>
604 gsGeometry<T> const & curveB,
605 index_t numSamples)
606{
607 gsMatrix<T> params(1,numSamples);
608 for (index_t p = 0; p < numSamples; ++p)
609 params.at(p) = 1.*p/(numSamples-1);
610
611 gsMatrix<T> pointsA, pointsB;
612 curveA.eval_into(params,pointsA);
613 curveB.eval_into(params,pointsB);
614
615 T dist = 0.;
616 for (int p = 0; p < numSamples; ++p)
617 dist += pow(distance(pointsA,p,pointsB,p,true),2);
618
619 return sqrt(dist/numSamples);
620}
621
622template <class T>
624 gsMatrix<T> const & points,
625 gsBasis<T> const & basis)
626{
627 index_t numSamples = params.cols();
628 index_t num = basis.size();
629 index_t dim = points.rows();
630
631 gsSparseMatrix<T> A(num,num);
632 gsMatrix<T> b(num,dim);
633 b.setZero();
634
635 gsMatrix<T> basisValues;
636 gsMatrix<index_t> activeBasis;
637
638 basis.eval_into(params,basisValues);
639 basis.active_into(params,activeBasis);
640
641 for (index_t p = 1; p < numSamples; ++p)
642 {
643 index_t numActive = activeBasis.rows();
644 for (index_t i = 0; i < numActive; ++i)
645 {
646 if (activeBasis(i,p) == 0)
647 {
648 for (index_t j = 0; j < numActive; ++j)
649 {
650 if (activeBasis(j,p) != 0 && activeBasis(j,p) != num-1 )
651 b.row(activeBasis(j,p)-1) -= basisValues(i,p) * basisValues(j,p) *
652 points.col(0).transpose() * (params.at(p)-params.at(p-1));
653 }
654 }
655 else if (activeBasis(i,p) == num-1)
656 {
657 for (index_t j = 0; j < numActive; ++j)
658 {
659 if (activeBasis(j,p) != 0 && activeBasis(j,p) != num-1 )
660 b.row(activeBasis(j,p)-1) -= basisValues(i,p) * basisValues(j,p) *
661 points.col(numSamples-1).transpose() * (params.at(p)-params.at(p-1));
662 }
663 }
664 else
665 {
666 b.row(activeBasis(i,p)-1) += basisValues(i,p) * points.col(p).transpose() * (params.at(p)-params.at(p-1));
667 for (index_t j = 0; j < numActive; ++j)
668 if (activeBasis(j,p) != 0 && activeBasis(j,p) != num-1 )
669 A(activeBasis(i,p)-1, activeBasis(j,p)-1) += basisValues(i,p) * basisValues(j,p) * (params.at(p)-params.at(p-1));
670 }
671 }
672 }
673
674 A.makeCompressed();
675 typename gsSparseSolver<T>::CGDiagonal solver(A);
676 gsMatrix<T> x = solver.solve(b);
677
678 gsMatrix<T> coefs(num,dim);
679 coefs.row(0) = points.col(0).transpose();
680 coefs.block(1,0,num-2,dim) = x.block(0,0,num-2,dim);
681 coefs.row(num-1) = points.col(numSamples-1).transpose();
682
683 return basis.makeGeometry(give(coefs));
684}
685
686template<class T>
688 index_t deg, index_t num, bool xiDir)
689{
690 GISMO_ENSURE(A.parDim() == B.parDim(), "Geometries are incompatible: different parametric dimensions: " +
691 util::to_string(A.parDim()) + " and " + util::to_string(B.parDim()) + "\n");
692 short_t pDim = A.parDim();
693 GISMO_ASSERT(pDim == 1 || pDim ==2, "Can only interpolate between curves or surfaces. Given geometries have parametric dimension " +
694 util::to_string(pDim) + "\n");
695 for (index_t d = 0; d < pDim; ++d)
696 GISMO_ENSURE(A.degree(d) == B.degree(d), "Geometries are incompatible: different splines degrees in dimension" +
697 util::to_string(d) + ": " + util::to_string(A.degree(d)) +
698 " and " + util::to_string(B.degree(d)) + "\n");
699
700 GISMO_ENSURE(A.targetDim() == B.targetDim(), "Geometries are incompatible: different physical dimensions: " +
701 util::to_string(A.targetDim()) + " and " + util::to_string(B.targetDim()) + "\n");
702 short_t tDim = A.targetDim();
703 GISMO_ASSERT(A.coefsSize() == B.coefsSize(), "Geometries are incompatible: different number of control points: " +
704 util::to_string(A.coefsSize()) + " and " + util::to_string(B.coefsSize()) + "\n");
705 index_t baseNum = A.coefsSize();
706
707 gsKnotVector<T> newKnots(0.0,1.0, num - deg - 1, deg + 1);
708
709 gsMultiPatch<> temp;
710 temp.addPatch(A.clone());
711
712 if (pDim == 1)
713 {
714
715 gsMatrix<T> coefs(baseNum*num,tDim);
716 T part = 1./(num-deg);
717 T pos = 0.;
718 for (index_t i = 0; i < num; ++i)
719 {
720 if (i < deg)
721 pos += part/deg*i;
722 else if (deg <= i && i < num-deg )
723 pos += part;
724 else
725 pos += part/deg*(num-i);
726
727 for (index_t j = 0; j < baseNum; ++j)
728 {
729 if (xiDir)
730 coefs.row(j*num+i) = combine(A.coefs(),B.coefs(),pos,j,j).row(0);
731 else
732 coefs.row(i*baseNum+j) = combine(A.coefs(),B.coefs(),pos,j,j).row(0);
733 }
734 }
735
736 if (xiDir)
737 {
738 gsTensorBSplineBasis<2,T> basis(newKnots,
739 (static_cast<gsBSpline<T> &>(temp.patch(0))).knots());
740 return basis.makeGeometry(give(coefs));
741 }
742 else
743 {
744 gsTensorBSplineBasis<2,T> basis((static_cast<gsBSpline<T> &>(temp.patch(0))).knots(),
745 newKnots);
746 return basis.makeGeometry(give(coefs));
747 }
748 }
749 else
750 {
751 gsTensorBSplineBasis<3,T> basis((static_cast<gsTensorBSpline<2,T> &>(temp.patch(0))).knots(0),
752 (static_cast<gsTensorBSpline<2,T> &>(temp.patch(0))).knots(1),
753 newKnots);
754
755 gsMatrix<T> coefs(baseNum*num,tDim);
756 T part = 1./(num-deg);
757 T pos = 0.;
758 for (index_t i = 0; i < num; ++i)
759 {
760 if (i < deg)
761 pos += part/deg*i;
762 else if (deg <= i && i < num-deg )
763 pos += part;
764 else
765 pos += part/deg*(num-i);
766
767 for (index_t j = 0; j < baseNum; ++j)
768 coefs.row(i*baseNum+j) = combine(A.coefs(),B.coefs(),pos,j,j).row(0);
769 }
770
771 return basis.makeGeometry(give(coefs));
772 }
773}
774
775template<class T>
777 index_t deg, index_t num,
778 T scaling, gsVector<T> const & center)
779{
780 typename gsGeometry<T>::uPtr scaledBoundary = boundary.clone();
781 scaledBoundary->translate(-1*center);
782 scaledBoundary->scale(scaling);
783 scaledBoundary->translate(center);
784 return genPatchInterpolation(boundary,*scaledBoundary,deg,num);
785}
786
787template<class T>
789 gsMatrix<T> const & A, gsMatrix<T> const & B,
790 index_t iA, index_t iB)
791{
792 GISMO_ENSURE(num - deg - 1 >= 0,"Too few DoFs\n");
793 GISMO_ENSURE(A.cols() == B.cols(),"Points have different dimensions\n");
794
795 gsKnotVector<T> knotsCoarse(0.0,1.0, 0, 2);
796 index_t dim = A.cols();
797 gsMatrix<T> coefs(2,dim);
798 coefs.row(0) = A.row(iA);
799 coefs.row(1) = B.row(iB);
800 // gen simplest possible Bspline line
801 typename gsBSpline<T>::uPtr line1 = typename gsBSpline<T>::uPtr(new gsBSpline<T>(knotsCoarse,coefs));
802 // refine it
803 for (index_t i = 0; i < deg - 1; ++i)
804 line1->degreeElevate();
805 gsKnotVector<T> knotsFine(0.0,1.0, num - deg - 1, deg + 1);
806 for (index_t i = 0; i < num - deg - 1; ++i)
807 line1->insertKnot(knotsFine.at(i+deg+1));
808
809 return line1;
810}
811
812template<class T>
814 T radius, T x0, T y0,
815 T angle0, T arcAngle)
816{
817 GISMO_ENSURE(num - deg - 1 >= 0,"Too few DoFs\n");
818 gsKnotVector<T> knots(0.0,1.0, num - deg - 1, deg + 1);
819 gsBSplineBasis<T> basis(knots);
820 return genCircle(basis,radius,x0,y0,angle0,arcAngle);
821}
822
823template<class T>
825 T radius,
826 T x0, T y0,
827 T angle0, T arcAngle)
828{
829 index_t numPoints = 1000;
830 gsMatrix<> params(1,numPoints);
831 gsMatrix<> points(2,numPoints);
832 for (index_t i = 0; i < numPoints; ++i)
833 {
834 params(0,i) = 1.*i/(numPoints-1);
835 points(0,i) = x0 + radius*cos(angle0 + i*arcAngle/(numPoints-1));
836 points(1,i) = y0 + radius*sin(angle0 + i*arcAngle/(numPoints-1));
837 }
838
839 return fittingDirichlet(params,points,basis);
840}
841
842template<class T>
843typename gsGeometry<T>::uPtr genQuad(index_t xiDeg, index_t xiNum, index_t etaDeg, index_t etaNum,
844 gsMatrix<T> const & A, gsMatrix<T> const & B,
845 gsMatrix<T> const & C, gsMatrix<T> const & D,
846 index_t iA, index_t iB, index_t iC, index_t iD)
847{
848 typename gsGeometry<T>::uPtr sideAB = genLine(xiDeg,xiNum,A,B,iA,iB);
849 typename gsGeometry<T>::uPtr sideCD = genLine(xiDeg,xiNum,C,D,iC,iD);
850
851 return genPatchInterpolation(*sideAB,*sideCD,etaDeg,etaNum);
852}
853
854template<class T>
855typename gsGeometry<T>::uPtr genSphere(index_t xiDeg, index_t xiNum, index_t etaDeg, index_t etaNum,
856 T xi0, T xi1, T eta0, T eta1)
857{
858 GISMO_ENSURE(xiNum - xiDeg - 1 >= 0,"Too few DoFs\n");
859 GISMO_ENSURE(etaNum - etaDeg - 1 >= 0,"Too few DoFs\n");
860
861 gsKnotVector<T> xiKnots(0.,1.,xiNum - xiDeg - 1, xiDeg + 1);
862 gsKnotVector<T> etaKnots(0.,1.,etaNum - etaDeg - 1, etaDeg + 1);
863 return genSphere(xiKnots,etaKnots,xi0,xi1,eta0,eta1);
864
865}
866
867template<class T>
869 T xi0, T xi1, T eta0, T eta1)
870{
871 GISMO_UNUSED(eta0);
872 GISMO_UNUSED(eta1);
873 gsBSplineBasis<T> xiBasis(xiKnots);
874 typename gsGeometry<T>::uPtr xiCircle = genCircle(xiBasis,(T)1.,(T)0.,(T)0.,xi0,xi1-xi0);
875 gsBSplineBasis<T> etaBasis(etaKnots);
876 typename gsGeometry<T>::uPtr etaCircle = genCircle(xiBasis,(T)1.,(T)0.,(T)0.,xi0,xi1-xi0);
877
878 gsTensorBSplineBasis<2,T> basis(xiKnots,etaKnots);
879
880 index_t xiNum = xiCircle->coefsSize();
881 index_t etaNum = etaCircle->coefsSize();
882 gsMatrix<T> coefs(xiNum*etaNum,3);
883 for (index_t i = 0; i < xiNum; ++i)
884 {
885 for (index_t j = 0; j < etaNum; ++j)
886 {
887 coefs(j*xiNum+i,0) = xiCircle->coef(i,0)*etaCircle->coef(j,1);
888 coefs(j*xiNum+i,1) = xiCircle->coef(i,1)*etaCircle->coef(j,1);
889 coefs(j*xiNum+i,2) = etaCircle->coef(j,0);
890 }
891 }
892
893 return basis.makeGeometry(give(coefs));
894}
895
896template<class T>
898 index_t deg, index_t num, T height)
899{
900 GISMO_ENSURE(num - deg - 1 >= 0,"Too few DoFs\n");
901
902 typename gsGeometry<T>::uPtr botBoundary = base.clone();
903 typename gsGeometry<T>::uPtr topBoundary = base.clone();
904 if (base.targetDim() < 3)
905 {
906 botBoundary->embed3d();
907 topBoundary->embed3d();
908 }
909
910 topBoundary->translate(gsVector<T,3>::vec(0.,0.,height));
911 return genPatchInterpolation(*botBoundary,*topBoundary,deg,num);
912}
913
914template<class T>
916 index_t deg, index_t num,
917 T height, T pitch, T x0, T y0)
918{
919 GISMO_ENSURE(num - deg - 1 >= 0,"Too few DoFs\n");
920
921 short_t pDim = base.parDim();
922 GISMO_ASSERT(pDim == 1 || pDim ==2,"Wrong geometry type\n");
923
924 gsKnotVector<> zKnots(0.0,1.0, num - deg - 1, deg + 1);
925 gsBSplineBasis<> zBasis(zKnots);
926
927 index_t numBase = base.coefsSize();
928
929 index_t numPoints = 10000;
930 gsMatrix<> params(1,numPoints);
931 gsMatrix<> points(3,numPoints);
932 for (index_t i = 0; i < numPoints; ++i)
933 {
934 params(0,i) = 1.*i/(numPoints-1);
935 points(0,i) = cos(params(0,i)*2*EIGEN_PI*pitch/360);
936 points(1,i) = sin(params(0,i)*2*EIGEN_PI*pitch/360);
937 points(2,i) = height*params(0,i);
938 }
939
940 typename gsGeometry<T>::uPtr helix = fittingDirichlet(params,points,zBasis);
941
942 gsMatrix<T> coefs(numBase*num,3);
943 gsMultiPatch<T> temp;
944 temp.addPatch(base.clone());
945
946 T oldAngle = 0.;
947 T oldRadius = 1.;
948 for (index_t i = 0; i < num; ++i)
949 {
950 T x = helix->coef(i,0);
951 T y = helix->coef(i,1);
952 T radius = sqrt(x*x+y*y);
953 T angle = atan2(y,x);
954 temp.patch(0).translate(gsVector<T,2>::vec(-1*x0,-1*y0));
955 temp.patch(0).rotate(angle-oldAngle);
956 temp.patch(0).scale(radius/oldRadius);
957 temp.patch(0).translate(gsVector<T,2>::vec(x0,y0));
958
959 for (index_t j = 0; j < numBase; j++)
960 {
961 coefs(i*numBase + j,0) = temp.patch(0).coef(j,0);
962 coefs(i*numBase + j,1) = temp.patch(0).coef(j,1);
963 coefs(i*numBase + j,2) = helix->coef(i,2);
964 }
965 oldRadius = radius;
966 oldAngle = angle;
967 }
968
969 if (pDim == 1)
970 {
971 gsTensorBSplineBasis<2,T> basis(static_cast<gsBSpline<T> &>(temp.patch(0)).knots(0),
972 zKnots);
973 return basis.makeGeometry(give(coefs));
974 }
975 else
976 {
977 gsTensorBSplineBasis<3,T> basis(static_cast<gsTensorBSpline<2,T> &>(temp.patch(0)).knots(0),
978 static_cast<gsTensorBSpline<2,T> &>(temp.patch(0)).knots(1),
979 zKnots);
980 return basis.makeGeometry(give(coefs));
981 }
982}
983
984template<class T>
985typename gsGeometry<T>::uPtr genSpring(gsGeometry<T> const & crossSection,
986 T R, T springPitch,
987 index_t N, bool nurbs)
988{
989 GISMO_ENSURE(crossSection.parDim() == 2, "Wrong dimension of the cross-section: " + util::to_string(crossSection.parDim()));
990
991 // cross-section knot vectors
992 gsKnotVector<T> xKnots = nurbs ? static_cast<const gsTensorNurbsBasis<2,T> &>(crossSection.basis()).knots(0)
993 : static_cast<const gsTensorBSplineBasis<2,T> &>(crossSection.basis()).knots(0);
994 gsKnotVector<T> yKnots = nurbs ? static_cast<const gsTensorNurbsBasis<2,T> &>(crossSection.basis()).knots(1)
995 : static_cast<const gsTensorBSplineBasis<2,T> &>(crossSection.basis()).knots(1);
996 // knot vector for the helical guiding line
997 std::vector<T> knots;
998 for (index_t i = 0; i < 3; ++i)
999 knots.push_back(0.);
1000 for (index_t i = 0; i < N-1; ++i)
1001 for (index_t j = 0; j < 2; ++j)
1002 knots.push_back(1./N*(i+1));
1003 for (index_t i = 0; i < 3; ++i)
1004 knots.push_back(1.);
1005 gsKnotVector<T> zKnots(knots,2);
1006
1007 // NURBS weights
1008 index_t numP = crossSection.coefs().rows();
1009 gsMatrix<T> crossWeights = nurbs ? static_cast<const gsTensorNurbsBasis<2,T> &>(crossSection.basis()).weights()
1010 : gsMatrix<T>::Ones(numP,1);
1011 gsMatrix<T> weights(numP*(2*N+1),1);
1012 for (index_t i = 0; i < 2*N+1; ++i)
1013 weights.middleRows(i*numP,numP) = crossWeights*(i%2==0 ? 1 : 1./sqrt(2));
1014
1015 // control points of the cross-section
1016 gsMatrix<T> crossCoefs(numP,3);
1017 crossCoefs.setZero();
1018 crossCoefs.col(0) = crossSection.coefs().col(0);
1019 crossCoefs.col(2) = crossSection.coefs().col(1);
1020 for (index_t i = 0; i < numP; ++i)
1021 crossCoefs(i,0) += R;
1022
1023 // control points of the spring
1024 gsMatrix<T> coefs(numP*(2*N+1),3);
1025 for (index_t i = 0; i < 2*N+1; ++i)
1026 {
1027 gsMatrix<T> rotation = gsEigen::AngleAxis<T>(-1.0*EIGEN_PI/4*i,gsEigen::Vector3f(0.,0.,1.)).toRotationMatrix().transpose();
1028 gsMatrix<T> scaling = gsEigen::DiagonalMatrix<T,3>((i%2 == 0 ? 1. : sqrt(2)),1.,1.);
1029 coefs.middleRows(i*numP,numP) = crossCoefs * scaling * rotation;
1030 for (index_t j = 0; j < numP; ++j)
1031 coefs(i*numP + j,2) += i*springPitch/8;
1032 }
1033
1034 return typename gsGeometry<T>::uPtr(new gsTensorNurbs<3,T>(xKnots,yKnots,zKnots,coefs,weights));
1035}
1036
1037template<class T>
1038void genMuscleMP(gsGeometry<T> const & muscleSurface, gsMultiPatch<T> & result)
1039{
1040 index_t innerDim = 2;
1041
1042 gsMultiPatch<T> temp;
1043 temp.addPatch(muscleSurface.clone());
1044 static_cast<gsTensorBSpline<2,T> &>(temp.patch(0)).insertKnot(
1045 static_cast<const gsTensorBSplineBasis<2,T> &>(muscleSurface.basis()).knots(1).at(4),1);
1046 static_cast<gsTensorBSpline<2,T> &>(temp.patch(0)).insertKnot(
1047 static_cast<const gsTensorBSplineBasis<2,T> &>(muscleSurface.basis()).knots(1).at(4),1);
1048 static_cast<gsTensorBSpline<2,T> &>(temp.patch(0)).insertKnot(0.5,1);
1049 static_cast<gsTensorBSpline<2,T> &>(temp.patch(0)).insertKnot(0.5,1);
1050 static_cast<gsTensorBSpline<2,T> &>(temp.patch(0)).insertKnot(
1051 static_cast<const gsTensorBSplineBasis<2,T> &>(muscleSurface.basis()).knots(1).at(7),1);
1052 static_cast<gsTensorBSpline<2,T> &>(temp.patch(0)).insertKnot(
1053 static_cast<const gsTensorBSplineBasis<2,T> &>(muscleSurface.basis()).knots(1).at(7),1);
1054
1055 std::vector<T> knotsEtaShort;
1056 for (index_t i = 0; i < 4; ++i)
1057 knotsEtaShort.push_back(0.);
1058 for (index_t i = 0; i < 4; ++i)
1059 knotsEtaShort.push_back(1.);
1060 gsKnotVector<T> knotVectorEtaShort(knotsEtaShort,3);
1061
1062 std::vector<T> knotsEtaLong;
1063 for (index_t i = 0; i < 4; ++i)
1064 knotsEtaLong.push_back(0.);
1065 knotsEtaLong.push_back(0.5);
1066 for (index_t i = 0; i < 4; ++i)
1067 knotsEtaLong.push_back(1.);
1068 gsKnotVector<T> knotVectorEtaLong(knotsEtaLong,3);
1069
1070 std::vector<T> knotsInner;
1071 for (index_t i = 0; i < innerDim+1; ++i)
1072 knotsInner.push_back(0.);
1073 for (index_t i = 0; i < innerDim+1; ++i)
1074 knotsInner.push_back(1.);
1075 gsKnotVector<T> knotVectorInner(knotsInner,innerDim);
1076
1077 gsTensorBSplineBasis<3,T> basis1(static_cast<const gsTensorBSplineBasis<2,T> &>(temp.basis(0)).knots(0),
1078 knotVectorEtaShort,knotVectorInner);
1079 gsTensorBSplineBasis<3,T> basis2(static_cast<const gsTensorBSplineBasis<2,T> &>(temp.basis(0)).knots(0),
1080 knotVectorEtaLong,knotVectorInner);
1081 gsTensorBSplineBasis<3,T> basis3(static_cast<const gsTensorBSplineBasis<2,T> &>(temp.basis(0)).knots(0),
1082 knotVectorEtaShort,knotVectorInner);
1083 gsTensorBSplineBasis<3,T> basis4(static_cast<const gsTensorBSplineBasis<2,T> &>(temp.basis(0)).knots(0),
1084 knotVectorEtaLong,knotVectorInner);
1085 gsTensorBSplineBasis<3,T> basis5(static_cast<const gsTensorBSplineBasis<2,T> &>(temp.basis(0)).knots(0),
1086 knotVectorEtaShort,knotVectorEtaLong);
1087
1088 gsMatrix<T> coefs1(7*4*(innerDim+1),3);
1089 gsMatrix<T> coefs2(7*5*(innerDim+1),3);
1090 gsMatrix<T> coefs3(7*4*(innerDim+1),3);
1091 gsMatrix<T> coefs4(7*5*(innerDim+1),3);
1092 gsMatrix<T> coefs5(7*4*5,3);
1093 for (index_t i = 0; i < 7; ++i)
1094 { // for each cross-section
1095 // compute four corners of the interior hub-patch
1096 gsMatrix<T> cornerA = combine(temp.patch(0).coefs(),temp.patch(0).coefs(),(T)1./3.,0*7+i,7*7+i); // right 1/3 left 1/3
1097 gsMatrix<T> cornerC = combine(temp.patch(0).coefs(),temp.patch(0).coefs(),(T)2./3.,0*7+i,7*7+i); // right 3/5 left 2/3
1098 gsMatrix<T> cornerB = combine(temp.patch(0).coefs(),temp.patch(0).coefs(),(T)1./3.,3*7+i,10*7+i); // right 2/5 left 1/3
1099 gsMatrix<T> cornerD = combine(temp.patch(0).coefs(),temp.patch(0).coefs(),(T)2./3.,3*7+i,10*7+i); // right 2/3 left 2/3
1100
1101 if (i == 0) // only for the left
1102 {
1103 cornerB = combine(cornerB,cornerC,(T)0.5);
1104 cornerD = combine(cornerD,cornerC,(T)0.5);
1105 }
1106
1107 // gen patch1
1108 gsMultiPatch<T> patch1Curves;
1109 patch1Curves.addPatch(genLine(innerDim,innerDim+1,temp.patch(0).coefs(),cornerA,0*7+i));
1110 patch1Curves.addPatch(genLine(innerDim,innerDim+1,temp.patch(0).coefs(),cornerB,3*7+i));
1111 gsMatrix<T> bdryABcoefs(4,3);
1112 for (index_t j = 0; j < 4; ++j)
1113 bdryABcoefs.row(j) = temp.patch(0).coefs().row(j*7+i);
1114 patch1Curves.addPatch(typename gsGeometry<T>::uPtr(new gsBSpline<T>(knotVectorEtaShort,bdryABcoefs)));
1115 patch1Curves.addPatch(genLine(3,4,cornerA,cornerB));
1116 gsCoonsPatch<T> coonsPatch1(patch1Curves);
1117 coonsPatch1.compute();
1118
1119 for (index_t j = 0; j < 4; ++j)
1120 for (index_t k = 0; k < innerDim+1; ++k)
1121 coefs1.row(k*4*7+j*7+(6-i)) = coonsPatch1.result().coefs().row(k*4+j);
1122
1123 // gen patch2
1124 gsMultiPatch<T> patch2Curves;
1125 patch2Curves.addPatch(genLine(innerDim,innerDim+1,temp.patch(0).coefs(),cornerB,3*7+i));
1126 patch2Curves.addPatch(genLine(innerDim,innerDim+1,temp.patch(0).coefs(),cornerC,7*7+i));
1127 gsMatrix<T> bdryBCcoefs(5,3);
1128 for (index_t j = 0; j < 5; ++j)
1129 bdryBCcoefs.row(j) = temp.patch(0).coefs().row((j+3)*7+i);
1130 patch2Curves.addPatch(typename gsGeometry<T>::uPtr(new gsBSpline<T>(knotVectorEtaLong,bdryBCcoefs)));
1131 patch2Curves.addPatch(genLine(3,5,cornerB,cornerC));
1132 gsCoonsPatch<T> coonsPatch2(patch2Curves);
1133 coonsPatch2.compute();
1134
1135 for (index_t j = 0; j < 5; ++j)
1136 for (index_t k = 0; k < innerDim+1; ++k)
1137 coefs2.row(k*5*7+j*7+(6-i)) = coonsPatch2.result().coefs().row(k*5+j);
1138
1139 // gen patch3
1140 gsMultiPatch<T> patch3Curves;
1141 patch3Curves.addPatch(genLine(innerDim,innerDim+1,temp.patch(0).coefs(),cornerC,7*7+i));
1142 patch3Curves.addPatch(genLine(innerDim,innerDim+1,temp.patch(0).coefs(),cornerD,10*7+i));
1143 gsMatrix<T> bdryCDcoefs(4,3);
1144 for (index_t j = 0; j < 4; ++j)
1145 bdryCDcoefs.row(j) = temp.patch(0).coefs().row((j+7)*7+i);
1146 patch3Curves.addPatch(typename gsGeometry<T>::uPtr(new gsBSpline<T>(knotVectorEtaShort,bdryCDcoefs)));
1147 patch3Curves.addPatch(genLine(3,4,cornerC,cornerD));
1148 gsCoonsPatch<T> coonsPatch3(patch3Curves);
1149 coonsPatch3.compute();
1150
1151 for (index_t j = 0; j < 4; ++j)
1152 for (index_t k = 0; k < innerDim+1; ++k)
1153 coefs3.row(k*4*7+j*7+(6-i)) = coonsPatch3.result().coefs().row(k*4+j);
1154
1155 // gen patch4
1156 gsMultiPatch<T> patch4Curves;
1157 patch4Curves.addPatch(genLine(innerDim,innerDim+1,temp.patch(0).coefs(),cornerD,10*7+i));
1158 patch4Curves.addPatch(genLine(innerDim,innerDim+1,temp.patch(0).coefs(),cornerA,14*7+i));
1159 gsMatrix<T> bdryDAcoefs(5,3);
1160 for (index_t j = 0; j < 5; ++j)
1161 bdryDAcoefs.row(j) = temp.patch(0).coefs().row((j+10)*7+i);
1162 patch4Curves.addPatch(typename gsGeometry<T>::uPtr(new gsBSpline<T>(knotVectorEtaLong,bdryDAcoefs)));
1163 patch4Curves.addPatch(genLine(3,5,cornerD,cornerA));
1164 gsCoonsPatch<T> coonsPatch4(patch4Curves);
1165 coonsPatch4.compute();
1166
1167 for (index_t j = 0; j < 5; ++j)
1168 for (index_t k = 0; k < innerDim+1; ++k)
1169 coefs4.row(k*5*7+j*7+(6-i)) = coonsPatch4.result().coefs().row(k*5+j);
1170
1171 // gen patch5
1172 gsMultiPatch<T> patch5Curves;
1173 patch5Curves.addPatch(genLine(3,5,cornerA,cornerD));
1174 patch5Curves.addPatch(genLine(3,5,cornerB,cornerC));
1175 patch5Curves.addPatch(genLine(3,4,cornerA,cornerB));
1176 patch5Curves.addPatch(genLine(3,4,cornerD,cornerC));
1177
1178 gsCoonsPatch<T> coonsPatch5(patch5Curves);
1179 coonsPatch5.compute();
1180
1181 for (index_t j = 0; j < 4; ++j)
1182 for (index_t k = 0; k < 5; ++k)
1183 coefs5.row(k*4*7+j*7+(6-i)) = coonsPatch5.result().coefs().row(k*4+j);
1184
1185 }
1186
1187 result.addPatch(basis1.makeGeometry(coefs1));
1188 result.addPatch(basis2.makeGeometry(coefs2));
1189 result.addPatch(basis3.makeGeometry(coefs3));
1190 result.addPatch(basis4.makeGeometry(coefs4));
1191 result.addPatch(basis5.makeGeometry(coefs5));
1192
1193 result.computeTopology();
1194}
1195
1196//------------------------------------------------------//
1197//----------------- Auxiliary functions ----------------//
1198//------------------------------------------------------//
1199
1200template<class T>
1201gsMatrix<T> combine(gsMatrix<T> const & A, gsMatrix<T> const & B, T x,
1202 index_t iA, index_t iB, bool cols)
1203{
1204 if (cols)
1205 {
1206 GISMO_ENSURE(A.rows() == B.rows(),"Points have different dimensions\n");
1207 index_t dim = A.rows();
1208 gsMatrix<T> combination(dim,1);
1209 combination.col(0) = (1-x)*A.col(iA) + x*B.col(iB);
1210 return combination;
1211 }
1212 else
1213 {
1214 GISMO_ENSURE(A.cols() == B.cols(),"Points have different dimensions\n");
1215 index_t dim = A.cols();
1216 gsMatrix<T> combination(1,dim);
1217 combination.row(0) = (1-x)*A.row(iA) + x*B.row(iB);
1218 return combination;
1219 }
1220}
1221
1222template <class T>
1223T distance(gsMatrix<T> const & A, index_t i, gsMatrix<T> const & B, index_t j, bool cols)
1224{
1225 T dist = 0.;
1226
1227 if (cols)
1228 {
1229 GISMO_ENSURE(A.rows() == B.rows(),"Wrong matrix size\n");
1230 for (index_t d = 0; d < A.rows(); ++d)
1231 dist = sqrt(pow(dist,2)+pow(A(d,i)-B(d,j),2));
1232 }
1233 else
1234 {
1235 GISMO_ENSURE(A.cols() == B.cols(),"Wrong matrix size\n");
1236 for (index_t d = 0; d < A.cols(); ++d)
1237 dist = sqrt(pow(dist,2)+pow(A(i,d)-B(j,d),2));
1238 }
1239
1240 return dist;
1241}
1242
1243} // namespace ends
A univariate B-spline basis.
Definition gsBSplineBasis.h:700
A B-spline function of one argument, with arbitrary target dimension.
Definition gsBSpline.h:51
void degreeElevate(short_t const i=1, short_t const dir=-1)
Elevate the degree by the given amount i for the direction dir. If dir is -1 then degree elevation is...
Definition gsBSpline.hpp:347
memory::unique_ptr< gsBSpline > uPtr
Unique pointer for gsBSpline.
Definition gsBSpline.h:63
void insertKnot(T knot, index_t i=1)
Definition gsBSpline.hpp:249
KnotVectorType & knots(const int i=0)
Returns a reference to the knot vector.
Definition gsBSpline.h:170
A basis represents a family of scalar basis functions defined over a common parameter domain.
Definition gsBasis.h:79
virtual memory::unique_ptr< gsGeometry< T > > makeGeometry(gsMatrix< T > coefs) const =0
Create a gsGeometry of proper type for this basis with the given coefficient matrix.
short_t dim() const
Dimension of the boxes.
Definition gsBoxTopology.h:98
Computes a Coons' patch parametrization given a set of boundary geometries. Parametrization is not gu...
Definition gsCoonsPatch.h:33
const gsGeometry< T > & compute()
Main routine that performs the computation (to be implemented in derived classes)
Definition gsCoonsPatch.hpp:25
Compute jacobian determinant of the geometry mapping. Can be pushed into gsPiecewiseFunction to const...
Definition gsElasticityFunctions.h:134
A scalar of vector field defined on a m_parametric geometry.
Definition gsField.h:55
static std::string getFilename(std::string const &fn)
Returns the filename without the path of fn.
Definition gsFileManager.cpp:597
uPtr clone()
Clone methode. Produceds a deep copy inside a uPtr.
virtual void computeMap(gsMapData< T > &InOut) const
Computes map function data.
Definition gsFunction.hpp:817
Abstract base class representing a geometry map.
Definition gsGeometry.h:93
gsMatrix< T > & coefs()
Definition gsGeometry.h:340
std::vector< gsGeometry * > boundary() const
Get boundary of this geometry as a vector of new gsGeometry instances.
Definition gsGeometry.hpp:437
void scale(T s, int coord=-1)
Apply Scaling by factor s.
Definition gsGeometry.h:413
gsMatrix< T >::RowXpr coef(index_t i)
Returns the i-th coefficient of the geometry as a row expression.
Definition gsGeometry.h:346
void translate(gsVector< T > const &v)
Apply translation by vector v.
Definition gsGeometry.h:429
short_t degree(const short_t &i) const
Returns the degree wrt direction i.
Definition gsGeometry.hpp:333
memory::unique_ptr< gsGeometry > uPtr
Unique pointer for gsGeometry.
Definition gsGeometry.h:100
short_t targetDim() const
Dimension of the ambient physical space (overriding gsFunction::targetDim())
Definition gsGeometry.h:286
void eval_into(const gsMatrix< T > &u, gsMatrix< T > &result) const
Evaluate the function at points u into result.
Definition gsGeometry.hpp:166
virtual short_t domainDim() const
Dimension d of the parameter domain (overriding gsFunction::domainDim()).
Definition gsGeometry.hpp:184
virtual const gsBasis< T > & basis() const =0
Returns a const reference to the basis of the geometry.
short_t parDim() const
Dimension d of the parameter domain (same as domainDim()).
Definition gsGeometry.hpp:190
index_t coefsSize() const
Return the number of coefficients (control points)
Definition gsGeometry.h:371
void embed3d()
Embeds coefficients in 3D.
Definition gsGeometry.h:467
Class for representing a knot vector.
Definition gsKnotVector.h:80
T at(const size_t &i) const
Returns the value of the i - th knot (counted with repetitions).
Definition gsKnotVector.h:865
the gsMapData is a cache of pre-computed function (map) values.
Definition gsFuncData.h:349
gsMatrix< T > points
input (parametric) points
Definition gsFuncData.h:372
A matrix with arbitrary coefficient type and fixed or dynamic size.
Definition gsMatrix.h:41
T at(index_t i) const
Returns the i-th element of the vectorization of the matrix.
Definition gsMatrix.h:211
Class Representing a triangle mesh with 3D vertices.
Definition gsMesh.h:32
Container class for a set of geometry patches and their topology, that is, the interface connections ...
Definition gsMultiPatch.h:100
bool computeTopology(T tol=1e-4, bool cornersOnly=false, bool tjunctions=false)
Attempt to compute interfaces and boundaries automatically.
Definition gsMultiPatch.hpp:377
gsGeometry< T > & patch(size_t i) const
Return the i-th patch.
Definition gsMultiPatch.h:292
index_t addPatch(typename gsGeometry< T >::uPtr g)
Add a patch from a gsGeometry<T>::uPtr.
Definition gsMultiPatch.hpp:211
short_t parDim() const
Dimension of the parameter domain (must match for all patches).
Definition gsMultiPatch.h:249
gsBasis< T > & basis(const size_t i) const
Return the basis of the i-th patch.
Definition gsMultiPatch.hpp:172
size_t nPatches() const
Number of patches.
Definition gsMultiPatch.h:274
This class is used to create a Paraview .pvd (collection) file.
Definition gsParaviewCollection.h:77
void addPart(String const &fn, real_t tStep=-1, std::string name="", index_t part=-1)
Appends a file to the Paraview collection (.pvd file).
Definition gsParaviewCollection.h:114
void save()
Definition gsParaviewCollection.h:203
const gsGeometry< T > & result() const
Returns the resulting patch. Assumes that compute() has been called before.
Definition gsPatchGenerator.h:72
A function depending on an index i, typically referring to a patch/sub-domain. On each patch a differ...
Definition gsPiecewiseFunction.h:29
Simple progress bar class.
Definition gsBaseUtils.h:172
void display(double progress)
display the progress from 0 to 1
Definition gsBaseUtils.h:178
Class representing a reference quadrature rule.
Definition gsQuadRule.h:29
virtual void mapTo(const gsVector< T > &lower, const gsVector< T > &upper, gsMatrix< T > &nodes, gsVector< T > &weights) const
Maps quadrature rule (i.e., points and weights) from the reference domain to an element.
Definition gsQuadRule.h:177
Sparse matrix class, based on gsEigen::SparseMatrix.
Definition gsSparseMatrix.h:139
A tensor product B-spline basis.
Definition gsTensorBSplineBasis.h:37
A tensor product of d B-spline functions, with arbitrary target dimension.
Definition gsTensorBSpline.h:45
KnotVectorType & knots(const int i)
Returns a reference to the knot vector in direction i.
Definition gsTensorBSpline.h:185
A tensor product Non-Uniform Rational B-spline (NURBS) basis.
Definition gsTensorNurbsBasis.h:38
A tensor product Non-Uniform Rational B-spline function (NURBS) of parametric dimension d,...
Definition gsTensorNurbs.h:41
A vector with arbitrary coefficient type and fixed or dynamic size.
Definition gsVector.h:37
T at(index_t i) const
Returns the i-th element of the vector.
Definition gsVector.h:177
std::string to_string(const C &value)
Converts value to string, assuming "operator<<" defined on C.
Definition gsUtils.h:56
gsMatrix< T > gsPointGrid(gsVector< T > const &a, gsVector< T > const &b, gsVector< unsigned > const &np)
Construct a Cartesian grid of uniform points in a hypercube, using np[i] points in direction i.
Definition gsPointGrid.hpp:82
Represents a B-spline curve/function with one parameter.
#define short_t
Definition gsConfig.h:35
#define index_t
Definition gsConfig.h:32
Provides Coons's patch construction from boundary data.
#define GISMO_UNUSED(x)
Definition gsDebug.h:112
#define GISMO_ENSURE(cond, message)
Definition gsDebug.h:102
#define gsInfo
Definition gsDebug.h:43
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
Provides linear and nonlinear elasticity systems for 2D plain strain and 3D continua.
Provides useful classes derived from gsFunction which can be used for visualization or coupling.
Provides declaration of the Field class.
This object is a cache for computed values from an evaluator.
Provides declaration of FunctionExpr class.
Provides isogeometric meshing and modelling routines.
Provides declaration of the Mesh class.
Provides a base class for a quadrature rule.
Creates a variety of quadrature rules.
Provides declaration of TensorBSplineBasis abstract interface.
Represents a tensor-product NURBS patch.
Allows to write several fields defined on the same geometry in one file, making it easier to operate ...
Provides declaration of functions writing Paraview files.
The G+Smo namespace, containing all definitions for the library.
T geometryJacRatio(gsMultiPatch< T > const &domain)
Returns min(Jacobian determinant) divided by max(Jacobian determinant); samples the Jacobian elementw...
Definition gsGeoUtils.hpp:336
gsGeometry< T >::uPtr genSphere(index_t xiDeg, index_t xiNum, index_t etaDeg, index_t etaNum, T xi0=0., T xi1=2 *EIGEN_PI, T eta0=-EIGEN_PI/2, T eta1=EIGEN_PI/2)
generates a tensor product B-spline spherical patch with radius 1 and center at 0 given the degrees a...
Definition gsGeoUtils.hpp:855
void genSamplingPoints(const gsVector< T > &lower, const gsVector< T > &upper, const gsQuadRule< T > &quRule, gsMatrix< T > &points)
Generates a matrix of sampling points for a given parametric element; includes quadrature points for ...
Definition gsGeoUtils.hpp:422
T normL2(gsMultiPatch< T > const &domain, gsMultiPatch< T > const &solution)
@ Compute norm of the isogeometric solution
Definition gsGeoUtils.hpp:295
gsVector< unsigned > distributePoints(const gsGeometry< T > &geo, unsigned numPoints)
distributes sampling points according to the length of the patch in each parametric direction
Definition gsGeoUtils.hpp:536
gsGeometry< T >::uPtr genLine(index_t deg, index_t num, gsMatrix< T > const &A, gsMatrix< T > const &B, index_t iA=0, index_t iB=0)
Definition gsGeoUtils.hpp:788
gsGeometry< T >::uPtr fittingDirichlet(gsMatrix< T > const &params, gsMatrix< T > const &points, gsBasis< T > const &basis)
fits a given parametrized point cloud with a curve using a given basis; the resulting curve interpola...
Definition gsGeoUtils.hpp:623
gsGeometry< T >::uPtr simplifyCurve(gsGeometry< T > const &curve, index_t additionalPoints=0, index_t degree=0, index_t numSamples=1000)
generates a simplified curve by fitting with the coarsest basis of the same degree; then reparametriz...
Definition gsGeoUtils.hpp:562
T displacementJacRatio(gsMultiPatch< T > const &domain, gsMultiPatch< T > const &displacement)
Returns min(Jacobian determinant) divided by max(Jacobian determinant) for geo+disp samples the Jacob...
Definition gsGeoUtils.hpp:377
void gsWriteParaviewMultiPhysics(std::map< std::string, const gsField< T > * > fields, std::string const &fn, unsigned npts=NS, bool mesh=false, bool ctrlNet=false)
Write a file containing several fields defined on the same geometry to ONE paraview file.
Definition gsWriteParaviewMultiPhysics.hpp:76
T curveLength(const gsGeometry< T > &geo)
compute curve length
Definition gsGeoUtils.hpp:510
index_t checkDisplacement(gsMultiPatch< T > const &domain, gsMultiPatch< T > const &displacement)
Checks whether the deformed configuration is bijective, i.e. det(Jac(geo+disp)) > 0; returns -1 if ye...
Definition gsGeoUtils.hpp:245
gsGeometry< T >::uPtr genCylinder(gsGeometry< T > const &base, index_t deg, index_t num, T height)
generates a 3D tensor product B-spline cylindrical patch
Definition gsGeoUtils.hpp:897
gsGeometry< T >::uPtr genSpring(gsGeometry< T > const &crossSection, T springRadius=6.0, T springPitch=2.60258, index_t numQuarterSegments=12, bool nurbs=false)
generates a 3D NURBS spring using provided geometry as a cross-section
Definition gsGeoUtils.hpp:985
T combine(T a, T b, T x)
compute a convex combintation (1-x)a+xb
Definition gsGeoUtils.h:206
T curveDistance(gsGeometry< T > const &curveA, gsGeometry< T > const &curveB, index_t numSamples=1000)
returns a distance in L2 sense between two curves parametrized from 0 to 1
Definition gsGeoUtils.hpp:603
gsGeometry< T >::uPtr genCircle(index_t deg, index_t num, T radius=1., T x0=0., T y0=0., T angle0=0., T arcAngle=2 *EIGEN_PI)
Definition gsGeoUtils.hpp:813
gsGeometry< T >::uPtr genPatchScaling(gsGeometry< T > const &boundary, index_t deg, index_t num, T scaling, gsVector< T > const &center)
generates a tensor product B-spline bdry south | front patch by scaling a given geometry object \ / |...
Definition gsGeoUtils.hpp:776
@ NEED_DERIV
Gradient of the object.
Definition gsForwardDeclarations.h:73
@ NEED_MEASURE
The density of the measure pull back.
Definition gsForwardDeclarations.h:76
T patchLength(const gsGeometry< T > &geo, short_t dir=0)
compute length of a patch in a given parametric direction as a mean of all boundary edges correspondi...
Definition gsGeoUtils.hpp:439
gsGeometry< T >::uPtr genScrew(gsGeometry< T > const &base, index_t deg, index_t num, T height, T pitch, T x0=0., T y0=0.)
generates a 3D tensor product B-spline screw-like patch
Definition gsGeoUtils.hpp:915
T distance(gsMatrix< T > const &A, gsMatrix< T > const &B, index_t i=0, index_t j=0, bool cols=false)
compute a distance between the point number in the set and the point number <j> in the set ; by def...
void plotDeformation(const gsMultiPatch< T > &initDomain, const std::vector< gsMultiPatch< T > > &displacements, std::string fileName, index_t numSamplingPoints=10000)
Definition gsGeoUtils.hpp:95
S give(S &x)
Definition gsMemory.h:266
gsGeometry< T >::uPtr genQuad(index_t xiDeg, index_t xiNum, index_t etaDeg, index_t etaNum, gsMatrix< T > const &A, gsMatrix< T > const &B, gsMatrix< T > const &C, gsMatrix< T > const &D, index_t iA=0, index_t iB=0, index_t iC=0, index_t iD=0)
generates a quad patch given by its four C—D corners with the following orientation; | | the points a...
Definition gsGeoUtils.hpp:843
gsGeometry< T >::uPtr genPatchInterpolation(gsGeometry< T > const &A, gsGeometry< T > const &B, index_t deg, index_t num, bool xiDir=false)
Definition gsGeoUtils.hpp:687
index_t checkGeometry(gsMultiPatch< T > const &domain)
Checks whether configuration is bijective, i.e. det(Jac(geo)) > 0; returns -1 if yes or the number of...
Definition gsGeoUtils.hpp:200
void genMuscleMP(gsGeometry< T > const &muscleSurface, gsMultiPatch< T > &result)
This is more of a script than a function. I use it to generate a multi-parametrization for the biceps...
Definition gsGeoUtils.hpp:1038
void plotGeometry(gsMultiPatch< T > const &domain, std::string fileName, index_t numSamples)
Plots the mesh and the jacobian (if <numSamples> > 0) to Paraview.
Definition gsGeoUtils.hpp:43
Struct that defines the boundary sides and corners and types of a geometric object.
Definition gsBoundary.h:56
@ GaussLegendre
Gauss-Legendre quadrature.
Definition gsQuadrature.h:37