1 /** @file gsFieldCreator.h
2 
3     @brief Provides declaration of gsFieldCreator functions.
4 
5     This file is part of the G+Smo library.
6 
7     This Source Code Form is subject to the terms of the Mozilla Public
8     License, v. 2.0. If a copy of the MPL was not distributed with this
9     file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 
11     Author(s): A. Mantzaflaris
12 */
13 
14 #pragma once
15 
16 #include <gsCore/gsField.h>
17 
18 namespace gismo
19 {
20 
21 
22 /**
23    @brief Generates a field with value the absolute difference (error)
24    between and isogeometric function and a function defined on the
25    physical domain
26 
27    For a multipatch geometry, use the static method of gismo::gsFieldCreator
28 
29    \ingroup Core
30 */
31 template<class T>
32 class gsAbsError : public gsFunction<T>
33 {
34 public:
35     /// Shared pointer for gsAbsError
36     typedef memory::shared_ptr< gsAbsError > Ptr;
37 
38     /// Unique pointer for gsAbsError
39     typedef memory::unique_ptr< gsAbsError > uPtr;
40 
41     gsAbsError( gsFunction<T> const & f1,
42                 gsGeometry<T> const & geo,
43                 gsFunction<T> const & f2,
44                 bool _f2param = false)
m_geo(geo)45     : m_geo(geo), m_f1(f1), m_f2(f2), f2param(_f2param)
46     {
47 
48     }
49 
GISMO_CLONE_FUNCTION(gsAbsError)50     GISMO_CLONE_FUNCTION(gsAbsError)
51 
52     void eval_into(const gsMatrix<T>& u, gsMatrix<T>& result) const
53     {
54         gsMatrix<T> tmp;
55         m_geo.eval_into(u, tmp);
56 
57         if(!f2param)
58             result.noalias() = ( m_f1.eval(u) - m_f2.eval(tmp) ).cwiseAbs();
59         else
60             result.noalias() = ( m_f1.eval(u) - m_f2.eval(u) ).cwiseAbs(); // f2 parametric function
61 
62     }
63 
domainDim()64     short_t domainDim() const { return m_f1.domainDim(); }
targetDim()65     short_t targetDim() const { return m_f1.targetDim(); }
66 
67     /// Prints the object as a string.
print(std::ostream & os)68     std::ostream &print(std::ostream &os) const
69     { os << "Absolute error.\n"; return os; };
70 private:
71     const gsGeometry<T> & m_geo;
72 
73     const gsFunction<T> & m_f1;
74     const gsFunction<T> & m_f2;
75 
76     bool f2param;
77 
78 private:
79 //    gsAbsError() { }
80 };
81 
82 
83 /**
84    @brief Generates a field with value being the gradient of an isogeometric function
85 
86    For a multipatch geometry, use the static method of gismo::gsFieldCreator
87 
88    \ingroup Core
89 */
90 template<class T>
91 class gsGradientField : public gsFunction<T>
92 {
93 public:
94     /// Shared pointer for gsGradientField
95     typedef memory::shared_ptr< gsGradientField > Ptr;
96 
97     /// Unique pointer for gsGradientField
98     typedef memory::unique_ptr< gsGradientField > uPtr;
99 
gsGradientField(gsGeometry<T> const & geo,gsFunction<T> const & f)100     gsGradientField( gsGeometry<T> const & geo, gsFunction<T> const & f)
101     : m_geo(geo), m_f(f)
102     { }
103 
GISMO_CLONE_FUNCTION(gsGradientField)104     GISMO_CLONE_FUNCTION(gsGradientField)
105 
106     void eval_into(const gsMatrix<T>& u, gsMatrix<T>& result) const
107     {
108         gsMatrix<T> tmp;
109         m_geo.eval_into(u, tmp);
110         m_f.deriv_into(tmp, result);
111     }
112 
domainDim()113     short_t domainDim() const { return m_geo.parDim(); }
targetDim()114     short_t targetDim() const { return m_geo.geoDim(); }
115 
116     /// Prints the object as a string.
print(std::ostream & os)117     std::ostream &print(std::ostream &os) const
118     { os << "Gradient field of "; return os; };
119 private:
120     const gsGeometry<T> & m_geo;
121     const gsFunction<T> & m_f  ;
122 };
123 
124 /**
125    @brief Generates a field with value the Jacobian determinant of a geometry
126 
127    For a multipatch geometry, use the static method of gismo::gsFieldCreator
128 
129    \ingroup Core
130 */
131 template<class T>
132 class gsJacDetField : public gsFunction<T>
133 {
134 public:
135     /// Shared pointer for gsJacDetField
136     typedef memory::shared_ptr< gsJacDetField > Ptr;
137 
138     /// Unique pointer for gsJacDetField
139     typedef memory::unique_ptr< gsJacDetField > uPtr;
140 
gsJacDetField(gsGeometry<T> const & geo)141     gsJacDetField( gsGeometry<T> const & geo)
142     : m_geo(geo), m_dim(m_geo.parDim())
143     {
144         GISMO_ENSURE(m_dim == m_geo.geoDim(), "Not extended to surface case yet." );
145     }
146 
GISMO_CLONE_FUNCTION(gsJacDetField)147     GISMO_CLONE_FUNCTION(gsJacDetField)
148 
149     void eval_into(const gsMatrix<T>& u, gsMatrix<T>& result) const
150     {
151         result.resize(1, u.cols() );
152         gsMatrix<T> tmp;
153         for (index_t k=0; k!= u.cols(); ++k)
154             result(0,k) = m_geo.deriv(u.col(k)).reshape(m_dim,m_dim).determinant();
155     }
156 
domainDim()157     short_t domainDim() const { return m_geo.parDim(); }
targetDim()158     short_t targetDim() const { return 1; }
159 
160     /// Prints the object as a string.
print(std::ostream & os)161     std::ostream &print(std::ostream &os) const
162     { os << "Jacobian determinant field of "; return os; };
163 private:
164     const gsGeometry<T> & m_geo;
165     const int m_dim;
166 };
167 
168 /**
169    @brief Generates the normal field of a geometry
170 
171    For a multipatch geometry, use the static method of gismo::gsFieldCreator
172 
173    \ingroup Core
174 */
175 template<class T>
176 class gsNormalField : public gsFunction<T>
177 {
178 public:
179     /// Shared pointer for gsNormalField
180     typedef memory::shared_ptr< gsNormalField > Ptr;
181 
182     /// Unique pointer for gsNormalField
183     typedef memory::unique_ptr< gsNormalField > uPtr;
184 
gsNormalField(gsGeometry<T> const & geo)185     gsNormalField( gsGeometry<T> const & geo) : m_geo(geo)
186     {
187 
188     }
189 
GISMO_CLONE_FUNCTION(gsNormalField)190     GISMO_CLONE_FUNCTION(gsNormalField)
191 
192     void eval_into(const gsMatrix<T>& u, gsMatrix<T>& result) const
193     {
194         const short_t ParDim = m_geo.parDim();
195         result.resize(ParDim+1, u.cols()) ;
196 
197         gsMatrix<T> Jk;
198 
199         for( index_t j=0; j < u.cols(); ++j )
200         {
201             Jk = m_geo.jacobian( u.col(j) );
202             T alt_sgn(1.0);
203             gsMatrix<T> mm(ParDim,ParDim);
204             for (int i = 0; i <= ParDim; ++i) // for all components of the normal vector
205             {
206                 Jk.rowMinor(i, mm);
207                 result(i,j) = alt_sgn * mm.determinant();
208                 alt_sgn = -alt_sgn;
209             }
210         }
211     }
212 
domainDim()213     short_t domainDim() const { return m_geo.parDim(); }
targetDim()214     short_t targetDim() const { return m_geo.geoDim();}
215 
216     /// Prints the object as a string.
print(std::ostream & os)217     std::ostream &print(std::ostream &os) const
218     { os << "NormalField"; return os; };
219 private:
220     const gsGeometry<T> & m_geo;
221 
222 private:
223 //    gsNormalField() { }
224 };
225 
226 /**
227    @brief Generates a field that attaches the parameter values on each
228    physical point
229 
230    For a multipatch geometry, use the static method of gismo::gsFieldCreator
231 
232    \ingroup Core
233 */
234 template<class T>
235 class gsParamField : public gsFunction<T>
236 {
237 public:
238     /// Shared pointer for gsParamField
239     typedef memory::shared_ptr< gsParamField > Ptr;
240 
241     /// Unique pointer for gsParamField
242     typedef memory::unique_ptr< gsParamField > uPtr;
243 
gsParamField(gsGeometry<T> const & geo)244     gsParamField(gsGeometry<T> const & geo)
245     : m_geo(geo)
246     {
247 
248     }
249 
GISMO_CLONE_FUNCTION(gsParamField)250     GISMO_CLONE_FUNCTION(gsParamField)
251 
252     void eval_into(const gsMatrix<T>& u, gsMatrix<T>& result) const
253     { result = u; }
254 
domainDim()255     short_t domainDim() const { return m_geo.domainDim(); }
targetDim()256     short_t targetDim() const { return m_geo.domainDim(); }
257 
258     /// Prints the object as a string.
print(std::ostream & os)259     std::ostream &print(std::ostream &os) const
260     { os << "Parameter field.\n"; return os; };
261 
262 private:
263     const gsGeometry<T> & m_geo;
264 };
265 
266 /**
267    @brief Generates a field that indicates the boundary sides on the geometry
268 
269    For a multipatch geometry, use the static method of gismo::gsFieldCreator
270 
271    In Paraview, choose blot as a color map and Wireframe as representation
272 
273    \ingroup Core
274 */
275 template<class T>
276 class gsBoundaryField : public gsFunction<T>
277 {
278 public:
279     /// Shared pointer for gsBoundaryField
280     typedef memory::shared_ptr< gsBoundaryField > Ptr;
281 
282     /// Unique pointer for gsBoundaryField
283     typedef memory::unique_ptr< gsBoundaryField > uPtr;
284 
gsBoundaryField(gsGeometry<T> const & geo_)285     explicit gsBoundaryField(gsGeometry<T> const & geo_)
286     : geo(geo_), m_supp(geo.support())
287     { }
288 
GISMO_CLONE_FUNCTION(gsBoundaryField)289     GISMO_CLONE_FUNCTION(gsBoundaryField)
290 
291     void eval_into(const gsMatrix<T>& u, gsMatrix<T>& result) const
292     {
293         result.setZero(1, u.cols() );
294 
295         const int d = geo.parDim();
296         for (boxSide c=boxSide::getFirst(d); c<boxSide::getEnd(d); ++c)
297         {
298             const index_t dir = c.direction();
299             const T par = m_supp(dir, c.parameter() );
300 
301             for (index_t v = 0; v != u.cols(); ++v) // for all columns of u
302             {
303                 if ( math::abs( u(dir,v) - par ) < 1e-2 )
304                     result(0,v) = static_cast<T>(c);
305             }
306         }
307     }
308 
domainDim()309     short_t domainDim() const { return geo.domainDim(); }
targetDim()310     short_t targetDim() const { return 1; }
311 
312     /// Prints the object as a string.
print(std::ostream & os)313     std::ostream &print(std::ostream &os) const
314     { os << "Boundary side indicator field.\n"; return os; };
315 
316 private:
317     const gsGeometry<T> & geo;
318     gsMatrix<T>           m_supp;
319 };
320 
321 
322 
323 /**
324    @brief Class that creates standard fields on a given parametric
325    (multipatch) geometry.
326 
327    \ingroup Core
328 */
329 template<class T>
330 struct gsFieldCreator
331 {
332 
333     static gsField<T> absError(gsField<T> const & field, gsFunction<T> const & f, bool fparam = false)
334     {
335         const gsMultiPatch<T> & mp = field.patches();
336 
337         gsPiecewiseFunction<T> * nFields = new gsPiecewiseFunction<T>(mp.nPatches());
338 
339         for (size_t k=0; k< mp.nPatches(); ++k)
340             nFields->addPiecePointer( new gsAbsError<T>(field.function(k), mp.patch(k), f, fparam) );
341 
342         return gsField<T>(mp, typename gsPiecewiseFunction<T>::Ptr(nFields), true );
343     }
344 
345 
gradientgsFieldCreator346     static gsField<T> gradient(gsMultiPatch<T> const & mp, gsFunction<T> const & f)
347     {
348         gsPiecewiseFunction<T> * nFields = new gsPiecewiseFunction<T>(mp.nPatches());
349 
350 
351         for (size_t k=0; k< mp.nPatches(); ++k)
352             nFields->addPiecePointer( new gsGradientField<T>(mp.patch(k), f) );
353 
354         return gsField<T>(mp, typename gsPiecewiseFunction<T>::Ptr(nFields), true );
355     }
356 
normalgsFieldCreator357     static gsField<T> normal(gsMultiPatch<T> const & mp)
358     {
359         gsPiecewiseFunction<T> * nFields = new gsPiecewiseFunction<T>(mp.nPatches());
360 
361 
362         for (size_t k=0; k< mp.nPatches(); ++k)
363             nFields->addPiecePointer( new gsNormalField<T>(mp.patch(k)) );
364 
365         return gsField<T>(mp, typename gsPiecewiseFunction<T>::Ptr(nFields), true );
366     }
367 
368 
jacDetgsFieldCreator369     static gsField<T> jacDet(gsMultiPatch<T> const & mp)
370     {
371         gsPiecewiseFunction<T> * nFields = new gsPiecewiseFunction<T>(mp.nPatches());
372 
373 
374         for (size_t k=0; k< mp.nPatches(); ++k)
375             nFields->addPiecePointer( new gsJacDetField<T>(mp.patch(k)) );
376 
377         return gsField<T>(mp, typename gsPiecewiseFunction<T>::Ptr(nFields), true );
378     }
379 
parametersgsFieldCreator380     static gsField<T> parameters(gsMultiPatch<T> const & mp)
381     {
382         gsPiecewiseFunction<T> * nFields = new gsPiecewiseFunction<T>(mp.nPatches());
383 
384 
385         for (size_t k=0; k< mp.nPatches(); ++k)
386             nFields->addPiecePointer( new gsParamField<T>(mp.patch(k)) );
387 
388         return gsField<T>(mp, typename gsPiecewiseFunction<T>::Ptr(nFields), true );
389     }
390 
boundarySidesgsFieldCreator391     static gsField<T> boundarySides(gsMultiPatch<T> const & mp)
392     {
393         gsPiecewiseFunction<T> * nFields = new gsPiecewiseFunction<T>(mp.nPatches());
394         for (size_t k=0; k< mp.nPatches(); ++k)
395             nFields->addPiecePointer( new gsBoundaryField<T>(mp.patch(k)) );
396 
397         return gsField<T>(mp, typename gsPiecewiseFunction<T>::Ptr(nFields), true );
398     }
399 
400 }; // struct gsFieldCreator
401 
402 
403 
404 } // namespace gismo
405