G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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>
21 #include <gsCore/gsFunctionExpr.h>
22 #include <gsNurbs/gsBSpline.h>
24 #include <gsNurbs/gsTensorNurbs.h>
25 #include <gsAssembler/gsQuadRule.h>
28 
32 #include <gsUtils/gsMesh/gsMesh.h>
33 #include <gsIO/gsWriteParaview.h>
34 
35 namespace gismo
36 {
37 
38 //-----------------------------------//
39 //--------- Mesh Analysis -----------//
40 //-----------------------------------//
41 
42 template <class T>
43 void 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,"Jac",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 
80 template <class T>
81 void 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,"",p);
91  }
92 }
93 
94 template <class T>
95 void 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,"Jac",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,"Jac",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 
175 template <class T>
176 void 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,"",p);
196  }
197 }
198 
199 template <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 
244 template <class T>
245 index_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 
294 template <class T>
295 T 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  {
302  gsMapData<T> mdGeo(NEED_MEASURE);
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 
335 template <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 
376 template <class T>
377 T 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 
421 template <class T>
422 void 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 
438 template <class T>
439 T patchLength(const gsGeometry<T> & geo, short_t dir)
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 
509 template <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 
535 template <class T>
536 gsVector<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 
561 template<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 
602 template<class T>
603 T curveDistance(gsGeometry<T> const & curveA,
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 
622 template <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 
686 template<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 
775 template<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 
787 template<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 
812 template<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 
823 template<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 
842 template<class T>
843 typename 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 
854 template<class T>
855 typename 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 
867 template<class T>
869  T xi0, T xi1, T eta0, T eta1)
870 {
871  gsBSplineBasis<T> xiBasis(xiKnots);
872  typename gsGeometry<T>::uPtr xiCircle = genCircle(xiBasis,(T)1.,(T)0.,(T)0.,xi0,xi1-xi0);
873  gsBSplineBasis<T> etaBasis(etaKnots);
874  typename gsGeometry<T>::uPtr etaCircle = genCircle(xiBasis,(T)1.,(T)0.,(T)0.,xi0,xi1-xi0);
875 
876  gsTensorBSplineBasis<2,T> basis(xiKnots,etaKnots);
877 
878  index_t xiNum = xiCircle->coefsSize();
879  index_t etaNum = etaCircle->coefsSize();
880  gsMatrix<T> coefs(xiNum*etaNum,3);
881  for (index_t i = 0; i < xiNum; ++i)
882  {
883  for (index_t j = 0; j < etaNum; ++j)
884  {
885  coefs(j*xiNum+i,0) = xiCircle->coef(i,0)*etaCircle->coef(j,1);
886  coefs(j*xiNum+i,1) = xiCircle->coef(i,1)*etaCircle->coef(j,1);
887  coefs(j*xiNum+i,2) = etaCircle->coef(j,0);
888  }
889  }
890 
891  return basis.makeGeometry(give(coefs));
892 }
893 
894 template<class T>
896  index_t deg, index_t num, T height)
897 {
898  GISMO_ENSURE(num - deg - 1 >= 0,"Too few DoFs\n");
899 
900  typename gsGeometry<T>::uPtr botBoundary = base.clone();
901  typename gsGeometry<T>::uPtr topBoundary = base.clone();
902  if (base.targetDim() < 3)
903  {
904  botBoundary->embed3d();
905  topBoundary->embed3d();
906  }
907 
908  topBoundary->translate(gsVector<T,3>::vec(0.,0.,height));
909  return genPatchInterpolation(*botBoundary,*topBoundary,deg,num);
910 }
911 
912 template<class T>
914  index_t deg, index_t num,
915  T height, T pitch, T x0, T y0)
916 {
917  GISMO_ENSURE(num - deg - 1 >= 0,"Too few DoFs\n");
918 
919  short_t pDim = base.parDim();
920  GISMO_ASSERT(pDim == 1 || pDim ==2,"Wrong geometry type\n");
921 
922  gsKnotVector<> zKnots(0.0,1.0, num - deg - 1, deg + 1);
923  gsBSplineBasis<> zBasis(zKnots);
924 
925  index_t numBase = base.coefsSize();
926 
927  index_t numPoints = 10000;
928  gsMatrix<> params(1,numPoints);
929  gsMatrix<> points(3,numPoints);
930  for (index_t i = 0; i < numPoints; ++i)
931  {
932  params(0,i) = 1.*i/(numPoints-1);
933  points(0,i) = cos(params(0,i)*2*EIGEN_PI*pitch/360);
934  points(1,i) = sin(params(0,i)*2*EIGEN_PI*pitch/360);
935  points(2,i) = height*params(0,i);
936  }
937 
938  typename gsGeometry<T>::uPtr helix = fittingDirichlet(params,points,zBasis);
939 
940  gsMatrix<T> coefs(numBase*num,3);
941  gsMultiPatch<T> temp;
942  temp.addPatch(base.clone());
943 
944  T oldAngle = 0.;
945  T oldRadius = 1.;
946  for (index_t i = 0; i < num; ++i)
947  {
948  T x = helix->coef(i,0);
949  T y = helix->coef(i,1);
950  T radius = sqrt(x*x+y*y);
951  T angle = atan2(y,x);
952  temp.patch(0).translate(gsVector<T,2>::vec(-1*x0,-1*y0));
953  temp.patch(0).rotate(angle-oldAngle);
954  temp.patch(0).scale(radius/oldRadius);
955  temp.patch(0).translate(gsVector<T,2>::vec(x0,y0));
956 
957  for (index_t j = 0; j < numBase; j++)
958  {
959  coefs(i*numBase + j,0) = temp.patch(0).coef(j,0);
960  coefs(i*numBase + j,1) = temp.patch(0).coef(j,1);
961  coefs(i*numBase + j,2) = helix->coef(i,2);
962  }
963  oldRadius = radius;
964  oldAngle = angle;
965  }
966 
967  if (pDim == 1)
968  {
969  gsTensorBSplineBasis<2,T> basis(static_cast<gsBSpline<T> &>(temp.patch(0)).knots(0),
970  zKnots);
971  return basis.makeGeometry(give(coefs));
972  }
973  else
974  {
975  gsTensorBSplineBasis<3,T> basis(static_cast<gsTensorBSpline<2,T> &>(temp.patch(0)).knots(0),
976  static_cast<gsTensorBSpline<2,T> &>(temp.patch(0)).knots(1),
977  zKnots);
978  return basis.makeGeometry(give(coefs));
979  }
980 }
981 
982 template<class T>
983 typename gsGeometry<T>::uPtr genSpring(gsGeometry<T> const & crossSection,
984  T R, T springPitch,
985  index_t N, bool nurbs)
986 {
987  GISMO_ENSURE(crossSection.parDim() == 2, "Wrong dimension of the cross-section: " + util::to_string(crossSection.parDim()));
988 
989  // cross-section knot vectors
990  gsKnotVector<T> xKnots = nurbs ? static_cast<const gsTensorNurbsBasis<2,T> &>(crossSection.basis()).knots(0)
991  : static_cast<const gsTensorBSplineBasis<2,T> &>(crossSection.basis()).knots(0);
992  gsKnotVector<T> yKnots = nurbs ? static_cast<const gsTensorNurbsBasis<2,T> &>(crossSection.basis()).knots(1)
993  : static_cast<const gsTensorBSplineBasis<2,T> &>(crossSection.basis()).knots(1);
994  // knot vector for the helical guiding line
995  std::vector<T> knots;
996  for (index_t i = 0; i < 3; ++i)
997  knots.push_back(0.);
998  for (index_t i = 0; i < N-1; ++i)
999  for (index_t j = 0; j < 2; ++j)
1000  knots.push_back(1./N*(i+1));
1001  for (index_t i = 0; i < 3; ++i)
1002  knots.push_back(1.);
1003  gsKnotVector<T> zKnots(knots,2);
1004 
1005  // NURBS weights
1006  index_t numP = crossSection.coefs().rows();
1007  gsMatrix<T> crossWeights = nurbs ? static_cast<const gsTensorNurbsBasis<2,T> &>(crossSection.basis()).weights()
1008  : gsMatrix<T>::Ones(numP,1);
1009  gsMatrix<T> weights(numP*(2*N+1),1);
1010  for (index_t i = 0; i < 2*N+1; ++i)
1011  weights.middleRows(i*numP,numP) = crossWeights*(i%2==0 ? 1 : 1./sqrt(2));
1012 
1013  // control points of the cross-section
1014  gsMatrix<T> crossCoefs(numP,3);
1015  crossCoefs.setZero();
1016  crossCoefs.col(0) = crossSection.coefs().col(0);
1017  crossCoefs.col(2) = crossSection.coefs().col(1);
1018  for (index_t i = 0; i < numP; ++i)
1019  crossCoefs(i,0) += R;
1020 
1021  // control points of the spring
1022  gsMatrix<T> coefs(numP*(2*N+1),3);
1023  for (index_t i = 0; i < 2*N+1; ++i)
1024  {
1025  gsMatrix<T> rotation = gsEigen::AngleAxis<T>(-1.0*EIGEN_PI/4*i,gsEigen::Vector3f(0.,0.,1.)).toRotationMatrix().transpose();
1026  gsMatrix<T> scaling = gsEigen::DiagonalMatrix<T,3>((i%2 == 0 ? 1. : sqrt(2)),1.,1.);
1027  coefs.middleRows(i*numP,numP) = crossCoefs * scaling * rotation;
1028  for (index_t j = 0; j < numP; ++j)
1029  coefs(i*numP + j,2) += i*springPitch/8;
1030  }
1031 
1032  return typename gsGeometry<T>::uPtr(new gsTensorNurbs<3,T>(xKnots,yKnots,zKnots,coefs,weights));
1033 }
1034 
1035 template<class T>
1036 void genMuscleMP(gsGeometry<T> const & muscleSurface, gsMultiPatch<T> & result)
1037 {
1038  index_t innerDim = 2;
1039 
1040  gsMultiPatch<T> temp;
1041  temp.addPatch(muscleSurface.clone());
1042  static_cast<gsTensorBSpline<2,T> &>(temp.patch(0)).insertKnot(
1043  static_cast<const gsTensorBSplineBasis<2,T> &>(muscleSurface.basis()).knots(1).at(4),1);
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(0.5,1);
1047  static_cast<gsTensorBSpline<2,T> &>(temp.patch(0)).insertKnot(0.5,1);
1048  static_cast<gsTensorBSpline<2,T> &>(temp.patch(0)).insertKnot(
1049  static_cast<const gsTensorBSplineBasis<2,T> &>(muscleSurface.basis()).knots(1).at(7),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 
1053  std::vector<T> knotsEtaShort;
1054  for (index_t i = 0; i < 4; ++i)
1055  knotsEtaShort.push_back(0.);
1056  for (index_t i = 0; i < 4; ++i)
1057  knotsEtaShort.push_back(1.);
1058  gsKnotVector<T> knotVectorEtaShort(knotsEtaShort,3);
1059 
1060  std::vector<T> knotsEtaLong;
1061  for (index_t i = 0; i < 4; ++i)
1062  knotsEtaLong.push_back(0.);
1063  knotsEtaLong.push_back(0.5);
1064  for (index_t i = 0; i < 4; ++i)
1065  knotsEtaLong.push_back(1.);
1066  gsKnotVector<T> knotVectorEtaLong(knotsEtaLong,3);
1067 
1068  std::vector<T> knotsInner;
1069  for (index_t i = 0; i < innerDim+1; ++i)
1070  knotsInner.push_back(0.);
1071  for (index_t i = 0; i < innerDim+1; ++i)
1072  knotsInner.push_back(1.);
1073  gsKnotVector<T> knotVectorInner(knotsInner,innerDim);
1074 
1075  gsTensorBSplineBasis<3,T> basis1(static_cast<const gsTensorBSplineBasis<2,T> &>(temp.basis(0)).knots(0),
1076  knotVectorEtaShort,knotVectorInner);
1077  gsTensorBSplineBasis<3,T> basis2(static_cast<const gsTensorBSplineBasis<2,T> &>(temp.basis(0)).knots(0),
1078  knotVectorEtaLong,knotVectorInner);
1079  gsTensorBSplineBasis<3,T> basis3(static_cast<const gsTensorBSplineBasis<2,T> &>(temp.basis(0)).knots(0),
1080  knotVectorEtaShort,knotVectorInner);
1081  gsTensorBSplineBasis<3,T> basis4(static_cast<const gsTensorBSplineBasis<2,T> &>(temp.basis(0)).knots(0),
1082  knotVectorEtaLong,knotVectorInner);
1083  gsTensorBSplineBasis<3,T> basis5(static_cast<const gsTensorBSplineBasis<2,T> &>(temp.basis(0)).knots(0),
1084  knotVectorEtaShort,knotVectorEtaLong);
1085 
1086  gsMatrix<T> coefs1(7*4*(innerDim+1),3);
1087  gsMatrix<T> coefs2(7*5*(innerDim+1),3);
1088  gsMatrix<T> coefs3(7*4*(innerDim+1),3);
1089  gsMatrix<T> coefs4(7*5*(innerDim+1),3);
1090  gsMatrix<T> coefs5(7*4*5,3);
1091  for (index_t i = 0; i < 7; ++i)
1092  { // for each cross-section
1093  // compute four corners of the interior hub-patch
1094  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
1095  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
1096  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
1097  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
1098 
1099  if (i == 0) // only for the left
1100  {
1101  cornerB = combine(cornerB,cornerC,(T)0.5);
1102  cornerD = combine(cornerD,cornerC,(T)0.5);
1103  }
1104 
1105  // gen patch1
1106  gsMultiPatch<T> patch1Curves;
1107  patch1Curves.addPatch(genLine(innerDim,innerDim+1,temp.patch(0).coefs(),cornerA,0*7+i));
1108  patch1Curves.addPatch(genLine(innerDim,innerDim+1,temp.patch(0).coefs(),cornerB,3*7+i));
1109  gsMatrix<T> bdryABcoefs(4,3);
1110  for (index_t j = 0; j < 4; ++j)
1111  bdryABcoefs.row(j) = temp.patch(0).coefs().row(j*7+i);
1112  patch1Curves.addPatch(typename gsGeometry<T>::uPtr(new gsBSpline<T>(knotVectorEtaShort,bdryABcoefs)));
1113  patch1Curves.addPatch(genLine(3,4,cornerA,cornerB));
1114  gsCoonsPatch<T> coonsPatch1(patch1Curves);
1115  coonsPatch1.compute();
1116 
1117  for (index_t j = 0; j < 4; ++j)
1118  for (index_t k = 0; k < innerDim+1; ++k)
1119  coefs1.row(k*4*7+j*7+(6-i)) = coonsPatch1.result().coefs().row(k*4+j);
1120 
1121  // gen patch2
1122  gsMultiPatch<T> patch2Curves;
1123  patch2Curves.addPatch(genLine(innerDim,innerDim+1,temp.patch(0).coefs(),cornerB,3*7+i));
1124  patch2Curves.addPatch(genLine(innerDim,innerDim+1,temp.patch(0).coefs(),cornerC,7*7+i));
1125  gsMatrix<T> bdryBCcoefs(5,3);
1126  for (index_t j = 0; j < 5; ++j)
1127  bdryBCcoefs.row(j) = temp.patch(0).coefs().row((j+3)*7+i);
1128  patch2Curves.addPatch(typename gsGeometry<T>::uPtr(new gsBSpline<T>(knotVectorEtaLong,bdryBCcoefs)));
1129  patch2Curves.addPatch(genLine(3,5,cornerB,cornerC));
1130  gsCoonsPatch<T> coonsPatch2(patch2Curves);
1131  coonsPatch2.compute();
1132 
1133  for (index_t j = 0; j < 5; ++j)
1134  for (index_t k = 0; k < innerDim+1; ++k)
1135  coefs2.row(k*5*7+j*7+(6-i)) = coonsPatch2.result().coefs().row(k*5+j);
1136 
1137  // gen patch3
1138  gsMultiPatch<T> patch3Curves;
1139  patch3Curves.addPatch(genLine(innerDim,innerDim+1,temp.patch(0).coefs(),cornerC,7*7+i));
1140  patch3Curves.addPatch(genLine(innerDim,innerDim+1,temp.patch(0).coefs(),cornerD,10*7+i));
1141  gsMatrix<T> bdryCDcoefs(4,3);
1142  for (index_t j = 0; j < 4; ++j)
1143  bdryCDcoefs.row(j) = temp.patch(0).coefs().row((j+7)*7+i);
1144  patch3Curves.addPatch(typename gsGeometry<T>::uPtr(new gsBSpline<T>(knotVectorEtaShort,bdryCDcoefs)));
1145  patch3Curves.addPatch(genLine(3,4,cornerC,cornerD));
1146  gsCoonsPatch<T> coonsPatch3(patch3Curves);
1147  coonsPatch3.compute();
1148 
1149  for (index_t j = 0; j < 4; ++j)
1150  for (index_t k = 0; k < innerDim+1; ++k)
1151  coefs3.row(k*4*7+j*7+(6-i)) = coonsPatch3.result().coefs().row(k*4+j);
1152 
1153  // gen patch4
1154  gsMultiPatch<T> patch4Curves;
1155  patch4Curves.addPatch(genLine(innerDim,innerDim+1,temp.patch(0).coefs(),cornerD,10*7+i));
1156  patch4Curves.addPatch(genLine(innerDim,innerDim+1,temp.patch(0).coefs(),cornerA,14*7+i));
1157  gsMatrix<T> bdryDAcoefs(5,3);
1158  for (index_t j = 0; j < 5; ++j)
1159  bdryDAcoefs.row(j) = temp.patch(0).coefs().row((j+10)*7+i);
1160  patch4Curves.addPatch(typename gsGeometry<T>::uPtr(new gsBSpline<T>(knotVectorEtaLong,bdryDAcoefs)));
1161  patch4Curves.addPatch(genLine(3,5,cornerD,cornerA));
1162  gsCoonsPatch<T> coonsPatch4(patch4Curves);
1163  coonsPatch4.compute();
1164 
1165  for (index_t j = 0; j < 5; ++j)
1166  for (index_t k = 0; k < innerDim+1; ++k)
1167  coefs4.row(k*5*7+j*7+(6-i)) = coonsPatch4.result().coefs().row(k*5+j);
1168 
1169  // gen patch5
1170  gsMultiPatch<T> patch5Curves;
1171  patch5Curves.addPatch(genLine(3,5,cornerA,cornerD));
1172  patch5Curves.addPatch(genLine(3,5,cornerB,cornerC));
1173  patch5Curves.addPatch(genLine(3,4,cornerA,cornerB));
1174  patch5Curves.addPatch(genLine(3,4,cornerD,cornerC));
1175 
1176  gsCoonsPatch<T> coonsPatch5(patch5Curves);
1177  coonsPatch5.compute();
1178 
1179  for (index_t j = 0; j < 4; ++j)
1180  for (index_t k = 0; k < 5; ++k)
1181  coefs5.row(k*4*7+j*7+(6-i)) = coonsPatch5.result().coefs().row(k*4+j);
1182 
1183  }
1184 
1185  result.addPatch(basis1.makeGeometry(coefs1));
1186  result.addPatch(basis2.makeGeometry(coefs2));
1187  result.addPatch(basis3.makeGeometry(coefs3));
1188  result.addPatch(basis4.makeGeometry(coefs4));
1189  result.addPatch(basis5.makeGeometry(coefs5));
1190 
1191  result.computeTopology();
1192 }
1193 
1194 //------------------------------------------------------//
1195 //----------------- Auxiliary functions ----------------//
1196 //------------------------------------------------------//
1197 
1198 template<class T>
1199 gsMatrix<T> combine(gsMatrix<T> const & A, gsMatrix<T> const & B, T x,
1200  index_t iA, index_t iB, bool cols)
1201 {
1202  if (cols)
1203  {
1204  GISMO_ENSURE(A.rows() == B.rows(),"Points have different dimensions\n");
1205  index_t dim = A.rows();
1206  gsMatrix<T> combination(dim,1);
1207  combination.col(0) = (1-x)*A.col(iA) + x*B.col(iB);
1208  return combination;
1209  }
1210  else
1211  {
1212  GISMO_ENSURE(A.cols() == B.cols(),"Points have different dimensions\n");
1213  index_t dim = A.cols();
1214  gsMatrix<T> combination(1,dim);
1215  combination.row(0) = (1-x)*A.row(iA) + x*B.row(iB);
1216  return combination;
1217  }
1218 }
1219 
1220 template <class T>
1221 T distance(gsMatrix<T> const & A, index_t i, gsMatrix<T> const & B, index_t j, bool cols)
1222 {
1223  T dist = 0.;
1224 
1225  if (cols)
1226  {
1227  GISMO_ENSURE(A.rows() == B.rows(),"Wrong matrix size\n");
1228  for (index_t d = 0; d < A.rows(); ++d)
1229  dist = sqrt(pow(dist,2)+pow(A(d,i)-B(d,j),2));
1230  }
1231  else
1232  {
1233  GISMO_ENSURE(A.cols() == B.cols(),"Wrong matrix size\n");
1234  for (index_t d = 0; d < A.cols(); ++d)
1235  dist = sqrt(pow(dist,2)+pow(A(i,d)-B(j,d),2));
1236  }
1237 
1238  return dist;
1239 }
1240 
1241 } // namespace ends
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 addPatch(typename gsGeometry< T >::uPtr g)
Add a patch from a gsGeometry&lt;T&gt;::uPtr.
Definition: gsMultiPatch.hpp:210
Provides a base class for a quadrature rule.
Abstract base class representing a geometry map.
Definition: gsGeometry.h:92
T geometryJacRatio(gsMultiPatch< T > const &domain)
Returns min(Jacobian determinant) divided by max(Jacobian determinant); samples the Jacobian elementw...
Definition: gsGeoUtils.hpp:336
Class representing a reference quadrature rule.
Definition: gsQuadRule.h:28
gsMatrix< T >::RowXpr coef(index_t i)
Returns the i-th coefficient of the geometry as a row expression.
Definition: gsGeometry.h:346
Provides declaration of FunctionExpr class.
Provides Coons&#39;s patch construction from boundary data.
Gradient of the object.
Definition: gsForwardDeclarations.h:73
virtual void computeMap(gsMapData< T > &InOut) const
Computes map function data.
Definition: gsFunction.hpp:822
short_t dim() const
Dimension of the boxes.
Definition: gsBoxTopology.h:98
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 &lt;j&gt; in the set ; by def...
T curveLength(const gsGeometry< T > &geo)
compute curve length
Definition: gsGeoUtils.hpp:510
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
A scalar of vector field defined on a m_parametric geometry.
Definition: gsField.h:54
#define short_t
Definition: gsConfig.h:35
void embed3d()
Embeds coefficients in 3D.
Definition: gsGeometry.h:467
A tensor product of d B-spline functions, with arbitrary target dimension.
Definition: gsTensorBSpline.h:44
gsBasis< T > & basis(const size_t i) const
Return the basis of the i-th patch.
Definition: gsMultiPatch.hpp:171
std::string to_string(const C &value)
Converts value to string, assuming &quot;operator&lt;&lt;&quot; defined on C.
Definition: gsUtils.h:56
Struct that defines the boundary sides and corners and types of a geometric object.
Definition: gsBoundary.h:55
short_t degree(const short_t &i) const
Returns the degree wrt direction i.
Definition: gsGeometry.hpp:333
A tensor product Non-Uniform Rational B-spline function (NURBS) of parametric dimension d...
Definition: gsTensorNurbs.h:40
short_t parDim() const
Dimension of the parameter domain (must match for all patches).
Definition: gsMultiPatch.h:183
the gsMapData is a cache of pre-computed function (map) values.
Definition: gsFuncData.h:324
const gsGeometry< T > & result() const
Returns the resulting patch. Assumes that compute() has been called before.
Definition: gsPatchGenerator.h:72
virtual index_t size() const
size
Definition: gsFunctionSet.h:578
S give(S &x)
Definition: gsMemory.h:266
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
memory::unique_ptr< gsBSpline > uPtr
Unique pointer for gsBSpline.
Definition: gsBSpline.h:63
#define index_t
Definition: gsConfig.h:32
#define GISMO_ENSURE(cond, message)
Definition: gsDebug.h:102
static std::string getFilename(std::string const &fn)
Returns the filename without the path of fn.
Definition: gsFileManager.cpp:597
Provides declaration of functions writing Paraview files.
T combine(T a, T b, T x)
compute a convex combintation (1-x)a+xb
Definition: gsGeoUtils.h:206
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
Represents a tensor-product NURBS patch.
A tensor product B-spline basis.
Definition: gsTensorBSplineBasis.h:36
index_t coefsSize() const
Return the number of coefficients (control points)
Definition: gsGeometry.h:371
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
Provides useful classes derived from gsFunction which can be used for visualization or coupling...
A B-spline function of one argument, with arbitrary target dimension.
Definition: gsBSpline.h:50
A univariate B-spline basis.
Definition: gsBSplineBasis.h:694
void insertKnot(T knot, index_t i=1)
Definition: gsBSpline.hpp:249
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
Class Representing a triangle mesh with 3D vertices.
Definition: gsMesh.h:31
T at(index_t i) const
Returns the i-th element of the vectorization of the matrix.
Definition: gsMatrix.h:211
void plotGeometry(gsMultiPatch< T > const &domain, std::string fileName, index_t numSamples)
Plots the mesh and the jacobian (if &lt;numSamples&gt; &gt; 0) to Paraview.
Definition: gsGeoUtils.hpp:43
void scale(T s, int coord=-1)
Apply Scaling by factor s.
Definition: gsGeometry.h:413
Provides isogeometric meshing and modelling routines.
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
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
gsGeometry< T > & patch(size_t i) const
Return the i-th patch.
Definition: gsMultiPatch.h:226
virtual short_t domainDim() const
Dimension d of the parameter domain (overriding gsFunction::domainDim()).
Definition: gsGeometry.hpp:184
size_t nPatches() const
Number of patches.
Definition: gsMultiPatch.h:208
Provides linear and nonlinear elasticity systems for 2D plain strain and 3D continua.
Gauss-Legendre quadrature.
Definition: gsQuadrature.h:34
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
#define gsInfo
Definition: gsDebug.h:43
std::vector< gsGeometry * > boundary() const
Get boundary of this geometry as a vector of new gsGeometry instances.
Definition: gsGeometry.hpp:423
void save()
Definition: gsParaviewCollection.h:203
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.
T at(index_t i) const
Returns the i-th element of the vector.
Definition: gsVector.h:177
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:913
Container class for a set of geometry patches and their topology, that is, the interface connections ...
Definition: gsMultiPatch.h:33
void display(double progress)
display the progress from 0 to 1
Definition: gsBaseUtils.h:178
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
Creates a variety of quadrature rules.
A tensor product Non-Uniform Rational B-spline (NURBS) basis.
Definition: gsTensorNurbsBasis.h:38
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
This class is used to create a Paraview .pvd (collection) file.
Definition: gsParaviewCollection.h:76
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
short_t parDim() const
Dimension d of the parameter domain (same as domainDim()).
Definition: gsGeometry.hpp:190
The density of the measure pull back.
Definition: gsForwardDeclarations.h:76
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:895
Provides declaration of the Mesh class.
uPtr clone()
Clone methode. Produceds a deep copy inside a uPtr.
const gsGeometry< T > & compute()
Main routine that performs the computation (to be implemented in derived classes) ...
Definition: gsCoonsPatch.hpp:25
memory::unique_ptr< gsGeometry > uPtr
Unique pointer for gsGeometry.
Definition: gsGeometry.h:100
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
virtual void eval_into(const gsMatrix< T > &u, gsMatrix< T > &result) const
Evaluates nonzero basis functions at point u into result.
Definition: gsBasis.hpp:443
Represents a B-spline curve/function with one parameter.
Computes a Coons&#39; patch parametrization given a set of boundary geometries. Parametrization is not gu...
Definition: gsCoonsPatch.h:32
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:1036
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
T at(const size_t &i) const
Returns the value of the i - th knot (counted with repetitions).
Definition: gsKnotVector.h:865
index_t checkDisplacement(gsMultiPatch< T > const &domain, gsMultiPatch< T > const &displacement)
Checks whether the deformed configuration is bijective, i.e. det(Jac(geo+disp)) &gt; 0; returns -1 if ye...
Definition: gsGeoUtils.hpp:245
Simple progress bar class.
Definition: gsBaseUtils.h:171
Compute jacobian determinant of the geometry mapping. Can be pushed into gsPiecewiseFunction to const...
Definition: gsElasticityFunctions.h:133
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
void eval_into(const gsMatrix< T > &u, gsMatrix< T > &result) const
Evaluate the function at points u into result.
Definition: gsGeometry.hpp:166
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:983
Class for representing a knot vector.
Definition: gsKnotVector.h:79
Allows to write several fields defined on the same geometry in one file, making it easier to operate ...
gsMatrix< T > points
input (parametric) points
Definition: gsFuncData.h:348
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 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
short_t targetDim() const
Dimension of the ambient physical space (overriding gsFunction::targetDim())
Definition: gsGeometry.h:286
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
A function depending on an index i, typically referring to a patch/sub-domain. On each patch a differ...
Definition: gsPiecewiseFunction.h:28
T normL2(gsMultiPatch< T > const &domain, gsMultiPatch< T > const &solution)
@ Compute norm of the isogeometric solution
Definition: gsGeoUtils.hpp:295
void plotDeformation(const gsMultiPatch< T > &initDomain, const std::vector< gsMultiPatch< T > > &displacements, std::string fileName, index_t numSamplingPoints=10000)
Definition: gsGeoUtils.hpp:95
index_t checkGeometry(gsMultiPatch< T > const &domain)
Checks whether configuration is bijective, i.e. det(Jac(geo)) &gt; 0; returns -1 if yes or the number of...
Definition: gsGeoUtils.hpp:200
virtual const gsBasis< T > & basis() const =0
Returns a const reference to the basis of the geometry.
This object is a cache for computed values from an evaluator.
void translate(gsVector< T > const &v)
Apply translation by vector v.
Definition: gsGeometry.h:429
A basis represents a family of scalar basis functions defined over a common parameter domain...
Definition: gsBasis.h:78
bool computeTopology(T tol=1e-4, bool cornersOnly=false, bool tjunctions=false)
Attempt to compute interfaces and boundaries automatically.
Definition: gsMultiPatch.hpp:366
Provides declaration of the Field class.
gsMatrix< T > & coefs()
Definition: gsGeometry.h:340
virtual void active_into(const gsMatrix< T > &u, gsMatrix< index_t > &result) const
Returns the indices of active basis functions at points u, as a list of indices, in result...
Definition: gsBasis.hpp:293
EIGEN_STRONG_INLINE jac_expr< E > jac(const symbol_expr< E > &u)
The Jacobian matrix of a FE variable.
Definition: gsExpressions.h:4528
Provides declaration of TensorBSplineBasis abstract interface.