G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsPatchGenerator.h
Go to the documentation of this file.
1 
14 #pragma once
15 
16 #include<gsCore/gsMultiPatch.h>
17 
18 namespace gismo
19 {
20 
21 
30 template <typename T>
32 {
33 public:
34 
35  gsPatchGenerator() : m_result(NULL)
36  { }
37 
45  : m_boundary(boundary), m_result(NULL)
46  {
47  GISMO_ASSERT( static_cast<int>(m_boundary.nPatches()) == 2*(m_boundary.parDim()+1),
48  "Expecting "<<2*(m_boundary.parDim()+1)
49  <<" boundaries, received "<< m_boundary.nPatches()<<".");
50  }
51 
52  virtual ~gsPatchGenerator()
53  {
54  delete m_result;
55  }
56 
57 public:
58 
61  virtual const gsGeometry<T> & compute() = 0;
62 
65  {
66  m_boundary = boundary;
67  return compute();
68  }
69 
72  const gsGeometry<T> & result() const
73  {
74  GISMO_ASSERT(m_result != NULL, "Result not computed.");
75  return *m_result;
76  }
77 
80  {
81  return m_boundary;
82  }
83 
84 protected:
85 
88  template<short_t d> void preparePatch(gsTensorBSplineBasis<d,T> & resultBasis,
89  gsMatrix<T> & coefs);
90 
91 protected:
92 
95 
98 
99 
100 }; // gsPatchGenerator
101 
102 
103 
104 template <typename T> template <short_t d>
106 {
107  GISMO_ASSERT(m_boundary.nPatches() == 2*d,
108  "Expecting "<<2*d<<" boundaries");
109 
110  typedef typename gsBSplineTraits<static_cast<short_t>(d-1),T>::Geometry Boundary_t;
111 
112  //-------- 1. Find the pairs of facing boundaries
113 
114  // A. Compute the topology of the input boundaries based on corners
115  m_boundary.computeTopology(1e-3);
116  GISMO_ASSERT(m_boundary.nBoundary()==0,"The input boundary is not closed.");
117  //gsDebugVar( m_boundary.detail() );
118 
119  // Make sure that the shell is water-tight (remove small gaps)
120  m_boundary.closeGaps(1e-3);
121 
122  // B. Permute boundaries so that we get a sequence of facing
123  // geometries: 0-1, 2-3, 4-5, ..
124 
125  std::vector<Boundary_t*> input;// permutation of the input boundaries
126  input.reserve(2*d);
127  std::vector<short_t> perm;// permutation to be computed
128  perm.reserve(2*d);
129 
130  for (unsigned k = 0; k!=2*d; ++k) //for all boundaries
131  {
132  for (unsigned l = k+1; l!=2*d; ++l)
133  if ( (k!=l) && (m_boundary.findInterface(k,l)==NULL) )
134  {
135  input.push_back( dynamic_cast<Boundary_t*>(&m_boundary.patch(k)) );
136  perm.push_back(k);
137  GISMO_ASSERT(input.back()!=NULL,
138  "Could not convert to the expected geometry type.");
139  input.push_back( dynamic_cast<Boundary_t*>(&m_boundary.patch(l)) );
140  perm.push_back(l);
141  GISMO_ASSERT(input.back()!=NULL,
142  "Could not convert to the expected geometry type.");
143  break;
144  }
145  }
146 
147  //gsDebugVar(gsAsMatrix<int>(perm));//debug
148  GISMO_ASSERT(input.size()==2*d,"Pairs not correctly identified.");
149 
150  //-------- 2. Resolve the configuration: Force orientation
151  // according to the positive orthant. Origin (0,..,0) is
152  // pinched to the first vertex of boundary 0, and all other
153  // boundaries are oriented accordingly.
154 
155  // A. Origin corner
156 
157  gsMatrix<T> v = input[0]->coef(0);
158  for (unsigned k = 2; k<2*d; k+=2) //for all pairs but the first
159  {
160  // Find joint with direction k/2
161  if ( ! input[k]->isPatchCorner(v) )
162  {
163  std::swap(input[k], input[k+1]);
164  std::swap(perm [k], perm [k+1]);
165  GISMO_ASSERT(input[k]->isPatchCorner(v),"No joint found");
166  }
167  // Set the origin of the parametrization to v
168  input[k]->setOriginCorner(v);
169  }
170 
171  // Apply the same permutation to m_boundary
172  m_boundary.permute(perm);
173  //gsDebugVar(gsAsMatrix<int>(perm));
174 
175  // B. Furthest corner
176  int count = 0;// becomes true if a common corner is found for all odd boundaries
177  for (boxCorner c = boxCorner::getFirst(d-1); c<boxCorner::getEnd(d-1); ++c)
178  {
179  v = input[1]->coefAtCorner(c);
180  count = 1;
181  for (unsigned k = 3; k<2*d; k+=2)
182  if ( input[k]->isPatchCorner(v) )
183  ++count;
184 
185  if (count == d)
186  break;
187  }
188 
189  GISMO_ASSERT(count==d, "Furthest corner not found");
190  // Set furthest corner of all parametrizations to v
191  for (unsigned k = 1; k<2*d; k+=2)
192  input[k]->setFurthestCorner(v);
193 
194  // C. Fix orientation
195  m_boundary.computeTopology();
196  //gsDebugVar( m_boundary.detail() );
197  GISMO_ASSERT(m_boundary.nBoundary()==0, "Something went wrong with boundary identification.");
198 
199  if ( d>2)
200  {
201  std::fill(perm.begin(),perm.end(),0);
202  for (unsigned k = 0; k!=2*(d-1); ++k) //for all pairs
203  {
204  if ( typename gsMultiPatch<T>::InterfacePtr bi = m_boundary.findInterface(k,k+2) )
205  {
206  if (bi->first() .side() - k-1 != 0 )//side!=k+1
207  perm[k] = 1;
208  if (bi->second().side() - k-1 != 0 )//side!=k+1
209  perm[k+2] = 1;
210  }
211  else
212  {
213  gsWarn<<"Topology is not the expected one.";
214  }
215  }
216 
217  for (unsigned k = 0; k!=2*d; ++k)
218  if ( perm[k] )
219  input[k]->swapDirections(0,1);
220 
221  m_boundary.computeTopology();
222  // gsDebugVar(gsAsMatrix<int>(perm));
223  // gsDebugVar( m_boundary.detail() );
224 
225  GISMO_ASSERT(m_boundary.nBoundary()==0,
226  "Something went wrong with boundary identification.");
227  }
228 
229  //-------- 3. At this point the configuration of the boundaries is
230  // correct. Decide on a common knot vector and degree for each
231  // coordinate.
232 
233  std::vector<gsBSplineBasis<T>*> cBases(d);
234  // Issues: 1. find the correct knot-vectors per direction
235  // 2. do the input patches meet in the right way at facets ? flips needed ?
236 
237  // A. Check initial compatibility of knot-vectors
238 
239  for (unsigned k = 0; k<2*d; k+=2) //for all pairs
240  {
241  for (unsigned l = 0; l!=d-1; ++l)
242  {
243  if ( input[k]->basis().degree(l) != input[k+1]->basis().degree(l) )
244  // to do
245  gsWarn<< "*** Degrees: "<< input[k]->basis().degree(l) <<", "
246  << input[k+1]->basis().degree(l) << "differ.\n";
247 
248  if ( input[k]->knots(l) != input[k+1]->knots(l) )
249  {
250  // to do
251  gsWarn<< "*** Knots differ.\n";
252  //1. Normalize both and check again
253  //2. Merge
254  }
255  }
256  }
257 
258  // B. Try to reorder the input so that we get a compatible ordering for in dD.
259 
260  for (unsigned k = 0; k!=d-1; ++k) // For now use the input knot-vectors
261  {
262  cBases[k] = input[2*d-2]->basis().component( k ).clone().release();//
263  }
264  // Last one
265  cBases[d-1] = input.front()->basis().component(d-2).clone().release();
266 
267 /* For debugging
268  for (unsigned k = 0; k!=d; ++k)
269  {
270  gsDebug<<"*** Boundaries "<<k<<":\n";
271  gsDebugVar( input[2*k ]->basis() );
272  gsDebugVar( input[2*k+1]->basis() );
273  }
274 */
275 
276  // Create the final tensor basis
277  resultBasis = gsTensorBSplineBasis<d,T>(cBases); //Note: constructor consumes pointers
278 
279  //gsDebug<<"*** Choice "<<resultBasis<<"\n";
280 
281  //-------- 4. Fill in the boundary of the patch
282 
283  gsMatrix<index_t> bdr; // indices of the boundary control points
284  coefs.setZero(resultBasis.size(), m_boundary.geoDim());
285 
286  // Fill in boundary coefficients
287  for ( short_t i = 0; i<d; i++ )
288  {
289  for ( int s = 0; s<2; s++ )
290  {
291  // Get the input coefficients for this boundary
292  const gsMatrix<T> & bCoefs = input[2*i+s]->coefs();
293 
294  //Get the boundary indices ("1+" is because boxSides start from 1)
295  bdr = resultBasis.boundary(static_cast<boxSide>(1+2*i+s));
296 
297  GISMO_ASSERT( bdr.rows() == bCoefs.rows(),
298  "Wrong dim "<<s <<": "<<bdr.rows()<<" != "<<bCoefs.rows()
299  <<" at patch "<< 2*i+s <<", side "<<static_cast<boxSide>(1+2*i+s)
300  <<".\n Component:\n"<< input[2*i+s]->basis()
301  << "\n ResultBasis:\n"<< resultBasis//.component(2*i+s)
302  );
303 
304  // Fill in resulting patch CPs
305  for ( index_t k = 0; k< bCoefs.rows(); k++ )
306  coefs.row( bdr(k,0) ) = bCoefs.row(k);
307  }
308  }
309 
310 }
311 
312 
313 }// namespace gismo
Abstract base class representing a geometry map.
Definition: gsGeometry.h:92
Traits for BSplineBasis in more dimensions.
Definition: gsBSplineBasis.h:31
index_t size() const
Returns the number of elements in the basis.
Definition: gsTensorBasis.h:108
#define short_t
Definition: gsConfig.h:35
Struct that defines the boundary sides and corners and types of a geometric object.
Definition: gsBoundary.h:55
virtual const gsGeometry< T > & compute()=0
Main routine that performs the computation (to be implemented in derived classes) ...
const gsGeometry< T > & result() const
Returns the resulting patch. Assumes that compute() has been called before.
Definition: gsPatchGenerator.h:72
#define index_t
Definition: gsConfig.h:32
A tensor product B-spline basis.
Definition: gsTensorBSplineBasis.h:36
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
void preparePatch(gsTensorBSplineBasis< d, T > &resultBasis, gsMatrix< T > &coefs)
Resolves the configuration of the input boundaries and creates a patch filled with the boundary coeff...
Definition: gsPatchGenerator.h:105
#define gsWarn
Definition: gsDebug.h:50
Provides declaration of the MultiPatch class.
const gsGeometry< T > & compute(const gsMultiPatch< T > &boundary)
Main routine that receives input and performs the computation.
Definition: gsPatchGenerator.h:64
Container class for a set of geometry patches and their topology, that is, the interface connections ...
Definition: gsMultiPatch.h:33
Struct which represents a certain side of a box.
Definition: gsBoundary.h:84
gsGeometry< T > * m_result
Resulting patch.
Definition: gsPatchGenerator.h:97
Abstract class that accepts a set of input boundaries and computes a new geometry.
Definition: gsPatchGenerator.h:31
gsMultiPatch< T > m_boundary
Input boundaries.
Definition: gsPatchGenerator.h:94
gsPatchGenerator(const gsMultiPatch< T > &boundary)
Constructs a patch generator object by a collection of geometries defining the boundaries of a patch...
Definition: gsPatchGenerator.h:44
static boxCorner getFirst(short_t)
helper for iterating on corners of an n-dimensional box
Definition: gsBoundary.h:356
Struct which represents an interface between two patches.
Definition: gsBoundary.h:649
const gsMultiPatch< T > & input()
Returns the input boundaries.
Definition: gsPatchGenerator.h:79
static boxCorner getEnd(short_t dim)
helper for iterating on corners of an n-dimensional box
Definition: gsBoundary.h:372
Struct which represents a certain corner of a hyper-cube.
Definition: gsBoundary.h:291
gsMatrix< index_t > boundary(boxSide const &s) const
Returns the indices of the basis functions that are nonzero at the domain boundary as single-column-m...
Definition: gsBasis.h:520