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