G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsPatchGenerator.h
Go to the documentation of this file.
1
14#pragma once
15
17
18namespace gismo
19{
20
21
30template <typename T>
32{
33public:
34
36 { }
37
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
57public:
58
61 virtual const gsGeometry<T> & compute() = 0;
62
65 {
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
84protected:
85
88 template<short_t d> void preparePatch(gsTensorBSplineBasis<d,T> & resultBasis,
89 gsMatrix<T> & coefs);
90
91protected:
92
95
98
99
100}; // gsPatchGenerator
101
102
103
104template <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
Struct which represents a certain side of a box.
Definition gsBoundary.h:85
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
Abstract base class representing a geometry map.
Definition gsGeometry.h:93
A matrix with arbitrary coefficient type and fixed or dynamic size.
Definition gsMatrix.h:41
Container class for a set of geometry patches and their topology, that is, the interface connections ...
Definition gsMultiPatch.h:100
Abstract class that accepts a set of input boundaries and computes a new geometry.
Definition gsPatchGenerator.h:32
gsGeometry< T > * m_result
Resulting patch.
Definition gsPatchGenerator.h:97
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
virtual const gsGeometry< T > & compute()=0
Main routine that performs the computation (to be implemented in derived classes)
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
const gsGeometry< T > & result() const
Returns the resulting patch. Assumes that compute() has been called before.
Definition gsPatchGenerator.h:72
const gsMultiPatch< T > & input()
Returns the input boundaries.
Definition gsPatchGenerator.h:79
const gsGeometry< T > & compute(const gsMultiPatch< T > &boundary)
Main routine that receives input and performs the computation.
Definition gsPatchGenerator.h:64
A tensor product B-spline basis.
Definition gsTensorBSplineBasis.h:37
index_t size() const
Returns the number of elements in the basis.
Definition gsTensorBasis.h:108
#define short_t
Definition gsConfig.h:35
#define index_t
Definition gsConfig.h:32
#define gsWarn
Definition gsDebug.h:50
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
Provides declaration of the MultiPatch class.
The G+Smo namespace, containing all definitions for the library.
Struct which represents an interface between two patches.
Definition gsBoundary.h:650
Struct that defines the boundary sides and corners and types of a geometric object.
Definition gsBoundary.h:56
Struct which represents a certain corner of a hyper-cube.
Definition gsBoundary.h:292
static boxCorner getEnd(short_t dim)
helper for iterating on corners of an n-dimensional box
Definition gsBoundary.h:372
static boxCorner getFirst(short_t)
helper for iterating on corners of an n-dimensional box
Definition gsBoundary.h:356
Traits for BSplineBasis in more dimensions.
Definition gsBSplineBasis.h:32