99*******************************************************************************/
1010#include < PCU.h>
1111#include " maSize.h"
12+ #include " maSolutionTransferHelper.h"
1213#include " apfMatrix.h"
1314#include < apfShape.h>
1415#include < cstdlib>
@@ -20,6 +21,32 @@ SizeField::~SizeField()
2021{
2122}
2223
24+ void SizeField::onRefine (Entity*, EntityArray&)
25+ {
26+ PCU_ALWAYS_ASSERT_VERBOSE (0 ,
27+ " unimplemented onRefine was called for a size-field!" );
28+ }
29+
30+ void SizeField::onCavity (EntityArray&, EntityArray&)
31+ {
32+ PCU_ALWAYS_ASSERT_VERBOSE (0 ,
33+ " unimplemented onCavity was called for a size-field!" );
34+ }
35+
36+ int SizeField::getTransferDimension ()
37+ {
38+ // By default there should be no size_field transfer.
39+ // This is used in a loop to get the lowest dimension
40+ // entities that require transfer. So something bigger
41+ // than mesh dimension will ignore that loop
42+ return 4 ;
43+ }
44+
45+ bool SizeField::hasNodesOn (int )
46+ {
47+ return false ;
48+ }
49+
2350IdentitySizeField::IdentitySizeField (Mesh* m):
2451 mesh (m)
2552{
@@ -96,14 +123,14 @@ static void orthogonalizeR(Matrix& R)
96123
97124static void orthogonalEigenDecompForSymmetricMatrix (Matrix const & A, Vector& v, Matrix& R)
98125{
99- /* here we assume A to be real symmetric 3x3 matrix,
126+ /* here we assume A to be real symmetric 3x3 matrix,
100127 * we should be able to get 3 orthogonal eigen vectors
101128 * we also normalize the eigen vectors */
102129 double eigenValues[3 ];
103130 Vector eigenVectors[3 ];
104-
131+
105132 apf::eigen (A, eigenVectors, eigenValues);
106-
133+
107134 Matrix RT (eigenVectors); // eigen vectors are stored in the rows of RT
108135
109136 RT[0 ] = RT[0 ].normalize ();
@@ -132,8 +159,8 @@ static double parentMeasure[apf::Mesh::TYPES] =
132159class SizeFieldIntegrator : public apf ::Integrator
133160{
134161 public:
135- SizeFieldIntegrator (SizeField* sF ):
136- Integrator (2 ),
162+ SizeFieldIntegrator (SizeField* sF , int order ):
163+ Integrator (order ),
137164 measurement (0 ),
138165 sizeField (sF ),
139166 meshElement (0 ),
@@ -181,7 +208,8 @@ struct MetricSizeField : public SizeField
181208{
182209 double measure (Entity* e)
183210 {
184- SizeFieldIntegrator sFI (this );
211+ SizeFieldIntegrator sFI (this ,
212+ std::max (mesh->getShape ()->getOrder (), order)+1 );
185213 apf::MeshElement* me = apf::createMeshElement (mesh, e);
186214 sFI .process (me);
187215 apf::destroyMeshElement (me);
@@ -201,6 +229,7 @@ struct MetricSizeField : public SizeField
201229 return measure (e) / parentMeasure[mesh->getType (e)];
202230 }
203231 Mesh* mesh;
232+ int order; // this is the underlying sizefield order (default 1)
204233};
205234
206235AnisotropicFunction::~AnisotropicFunction ()
@@ -337,13 +366,16 @@ struct AnisoSizeField : public MetricSizeField
337366{
338367 AnisoSizeField ()
339368 {
369+ mesh = 0 ;
370+ order = 1 ;
340371 }
341372 AnisoSizeField (Mesh* m, AnisotropicFunction* f):
342373 bothEval (f),
343374 sizesEval (&bothEval),
344375 frameEval (&bothEval)
345376 {
346377 mesh = m;
378+ order = 1 ;
347379 hField = apf::createUserField (m, " ma_sizes" , apf::VECTOR,
348380 apf::getLagrange (1 ), &sizesEval);
349381 rField = apf::createUserField (m, " ma_frame" , apf::MATRIX,
@@ -357,6 +389,7 @@ struct AnisoSizeField : public MetricSizeField
357389 void init (Mesh* m, apf::Field* sizes, apf::Field* frames)
358390 {
359391 mesh = m;
392+ order = apf::getShape (sizes)->getOrder ();
360393 hField = sizes;
361394 rField = frames;
362395 }
@@ -424,11 +457,14 @@ struct LogAnisoSizeField : public MetricSizeField
424457{
425458 LogAnisoSizeField ()
426459 {
460+ mesh = 0 ;
461+ order = 1 ;
427462 }
428463 LogAnisoSizeField (Mesh* m, AnisotropicFunction* f):
429464 logMEval (f)
430465 {
431466 mesh = m;
467+ order = 1 ;
432468 logMField = apf::createUserField (m, " ma_logM" , apf::MATRIX,
433469 apf::getLagrange (1 ), &logMEval);
434470 }
@@ -439,20 +475,34 @@ struct LogAnisoSizeField : public MetricSizeField
439475 void init (Mesh* m, apf::Field* sizes, apf::Field* frames)
440476 {
441477 mesh = m;
442- logMField = apf::createField (m, " ma_logM" , apf::MATRIX, apf::getLagrange (1 ));
443- Entity* v;
444- Iterator* it = m->begin (0 );
445- while ( (v = m->iterate(it)) ) {
446- Vector h;
447- Matrix f;
448- apf::getVector (sizes, v, 0 , h);
449- apf::getMatrix (frames, v, 0 , f);
450- Vector s (log (1 /h[0 ]/h[0 ]), log (1 /h[1 ]/h[1 ]), log (1 /h[2 ]/h[2 ]));
451- Matrix S (s[0 ], 0 , 0 ,
452- 0 , s[1 ], 0 ,
453- 0 , 0 , s[2 ]);
454- apf::setMatrix (logMField, v, 0 , f * S * transpose (f));
478+ order = apf::getShape (sizes)->getOrder ();
479+ logMField = apf::createField (m, " ma_logM" , apf::MATRIX,
480+ apf::getShape (sizes));
481+ int dim = m->getDimension ();
482+ Entity* ent;
483+ Iterator* it;
484+ for (int d = 0 ; d <= dim; d++) {
485+ if (!apf::getShape (logMField)->countNodesOn (apf::Mesh::simplexTypes[d]))
486+ continue ;
487+ it = m->begin (d);
488+ while ( (ent = m->iterate(it)) ){
489+ int type = m->getType (ent);
490+ int non = apf::getShape (logMField)->countNodesOn (type);
491+ for (int i = 0 ; i < non; i++) {
492+ Vector h;
493+ Matrix f;
494+ apf::getVector (sizes, ent, i, h);
495+ apf::getMatrix (frames, ent, i, f);
496+ Vector s (log (1 /h[0 ]/h[0 ]), log (1 /h[1 ]/h[1 ]), log (1 /h[2 ]/h[2 ]));
497+ Matrix S (s[0 ], 0 , 0 ,
498+ 0 , s[1 ], 0 ,
499+ 0 , 0 , s[2 ]);
500+ apf::setMatrix (logMField, ent, i, f * S * transpose (f));
501+ }
502+ }
503+ m->end (it);
455504 }
505+ fieldVal.allocate (apf::countComponents (logMField));
456506 }
457507 void getTransform (
458508 apf::MeshElement* me,
@@ -497,6 +547,34 @@ struct LogAnisoSizeField : public MetricSizeField
497547 0 ,value,0 ,
498548 0 ,0 ,value));
499549 }
550+ void onRefine (
551+ Entity* parent,
552+ EntityArray& newEntities)
553+ {
554+ transfer (logMField, &(fieldVal[0 ]), 1 , &parent, newEntities);
555+ }
556+ void onCavity (
557+ EntityArray& oldElements,
558+ EntityArray& newEntities)
559+ {
560+ transfer (logMField, &(fieldVal[0 ]),
561+ oldElements.getSize (), &(oldElements[0 ]), newEntities);
562+ }
563+ int getTransferDimension ()
564+ {
565+ int transferDimension = 4 ;
566+ for (int d = 1 ; d <=3 ; d++)
567+ if (hasNodesOn (d)) {
568+ transferDimension = d;
569+ break ;
570+ }
571+ return transferDimension;
572+ }
573+ bool hasNodesOn (int dimension)
574+ {
575+ return apf::getShape (logMField)->hasNodesIn (dimension);
576+ }
577+ apf::NewArray<double > fieldVal;
500578 apf::Field* logMField;
501579 LogMEval logMEval;
502580};
0 commit comments