@@ -106,8 +106,7 @@ bool SIMoutput::parseOutputTag (const tinyxml2::XMLElement* elem)
106106{
107107 IFEM ::cout <<" Parsing <" << elem -> Value () <<">" << std ::endl ;
108108
109- const char * funcval = utl ::getValue (elem ,"function" );
110- if (funcval )
109+ if (const char * funcval = utl ::getValue (elem ,"function" ); funcval )
111110 {
112111 std ::string name ;
113112 utl ::getAttribute (elem ,"name" ,name );
@@ -141,7 +140,7 @@ bool SIMoutput::parseOutputTag (const tinyxml2::XMLElement* elem)
141140 // Parse the result point specifications.
142141 // Can either be explicit points, lines or a grid.
143142 const tinyxml2 ::XMLElement * point = elem -> FirstChildElement ("point" );
144- for (int i = 1 ; point ; i ++ , point = point -> NextSiblingElement ())
143+ for (int i = 1 ; point ; i ++ , point = point -> NextSiblingElement ("point" ))
145144 {
146145 ResultPoint thePoint (3 );
147146 if (int patch = 0 ; utl ::getAttribute (point ,"patch" ,patch ) && patch > 0 )
@@ -150,21 +149,30 @@ bool SIMoutput::parseOutputTag (const tinyxml2::XMLElement* elem)
150149 IFEM ::cout <<"\tPoint " << i <<": P" << thePoint .patch ;
151150 if (utl ::getAttribute (point ,"node" ,thePoint .inod ) && thePoint .inod > 0 )
152151 IFEM ::cout <<" node = " << thePoint .inod ;
152+ else if (point -> FirstChild () &&
153+ utl ::parseVec (thePoint .X ,point -> FirstChild ()-> Value ()))
154+ {
155+ // Cartesian coordinates of a spatial point is specified,
156+ thePoint .iel = -1 ; // need to search for the matching element/node
157+ IFEM ::cout <<" X = " << thePoint .X ;
158+ }
153159 else
160+ {
154161 IFEM ::cout <<" xi =" ;
155- if (utl ::getAttribute (point ,"u" ,thePoint .u [0 ]))
156- IFEM ::cout <<' ' << thePoint .u [0 ];
157- if (utl ::getAttribute (point ,"v" ,thePoint .u [1 ]))
158- IFEM ::cout <<' ' << thePoint .u [1 ];
159- if (utl ::getAttribute (point ,"w" ,thePoint .u [2 ]))
160- IFEM ::cout <<' ' << thePoint .u [2 ];
162+ if (utl ::getAttribute (point ,"u" ,thePoint .u [0 ]))
163+ IFEM ::cout <<' ' << thePoint .u [0 ];
164+ if (utl ::getAttribute (point ,"v" ,thePoint .u [1 ]))
165+ IFEM ::cout <<' ' << thePoint .u [1 ];
166+ if (utl ::getAttribute (point ,"w" ,thePoint .u [2 ]))
167+ IFEM ::cout <<' ' << thePoint .u [2 ];
168+ }
161169 IFEM ::cout << std ::endl ;
162170
163171 addPoint (thePoint );
164172 }
165173
166174 const tinyxml2 ::XMLElement * line = elem -> FirstChildElement ("line" );
167- for (int j = 1 ; line ; j ++ , line = line -> NextSiblingElement ())
175+ for (int j = 1 ; line ; j ++ , line = line -> NextSiblingElement ("line" ))
168176 {
169177 ResultPoint thePoint (3 );
170178 if (int patch = 0 ; utl ::getAttribute (line ,"patch" ,patch ) && patch > 0 )
@@ -206,26 +214,22 @@ bool SIMoutput::parseOutputTag (const tinyxml2::XMLElement* elem)
206214 }
207215
208216 for (const tinyxml2 ::XMLElement * child = elem -> FirstChildElement ("elements" );
209- child ; child = child -> NextSiblingElement ())
217+ child ; child = child -> NextSiblingElement ("elements" ))
210218 if (const tinyxml2 ::XMLNode * elist = child -> FirstChild (); elist )
211219 {
212220 ResultPoint thePoint ;
213221 if (int patch = 0 ; utl ::getAttribute (child ,"patch" ,patch ) && patch > 0 )
214222 thePoint .patch = patch ;
215223
216- IntVec elements ;
217- utl ::parseIntegers (elements ,elist -> Value ());
218- for (int iel : elements )
219- {
220- thePoint .iel = iel ;
221- addPoint (thePoint );
222- }
223-
224- if (!elements .empty ())
224+ if (IntVec elements ; utl ::parseIntegers (elements ,elist -> Value ()))
225225 {
226226 IFEM ::cout <<"\tElement center output: P" << thePoint .patch <<" (" ;
227- for (const ResultPoint & rp : myPoints .back ().second )
228- IFEM ::cout <<" " << rp .iel ;
227+ for (int iel : elements )
228+ {
229+ IFEM ::cout <<" " << iel ;
230+ thePoint .iel = iel ;
231+ addPoint (thePoint );
232+ }
229233 IFEM ::cout <<" )" << std ::endl ;
230234 }
231235 }
@@ -236,7 +240,7 @@ bool SIMoutput::parseOutputTag (const tinyxml2::XMLElement* elem)
236240 else if (grid )
237241 idxGrid = myPoints .size ();
238242
239- for (int g = 1 ; grid ; g ++ , grid = grid -> NextSiblingElement ())
243+ for (int g = 1 ; grid ; g ++ , grid = grid -> NextSiblingElement ("grid" ))
240244 {
241245 ResultPoint thePoint ;
242246 if (int patch = 0 ; utl ::getAttribute (grid ,"patch" ,patch ) && patch > 0 )
@@ -413,7 +417,7 @@ void SIMoutput::preprocessResPtGroup (std::string& ptFile, ResPointVec& points)
413417{
414418 if (points .empty ()) return ;
415419
416- // Check if we have Cartesian grid input
420+ // Check if we have a regular Cartesian grid input
417421 size_t nX = 0 ;
418422 IntMat pointMap ;
419423 if (points .front ().inod < 0 && points .back ().inod < 0 )
@@ -426,23 +430,52 @@ void SIMoutput::preprocessResPtGroup (std::string& ptFile, ResPointVec& points)
426430 nX = 0 ;
427431 }
428432
433+ // Check if we have general spatial points input (Cartesian coordinates)
434+ using PatchPoints = std ::pair < std ::vector < ASMbase ::PointParams > ,Vec3Vec > ;
435+ std ::map < ASMbase * ,PatchPoints > pchPoints ;
436+ if (pointMap .empty ())
437+ for (ResultPoint & pt : points )
438+ if (pt .iel < 0 || pt .inod < 0 )
439+ if (ASMbase * pch = this -> getPatch (pt .patch ,true); pch && !pch -> empty ())
440+ {
441+ pchPoints [pch ].second .emplace_back (pt .X );
442+ pt .iel = - pchPoints [pch ].second .size ();
443+ }
444+
445+ // Find element and/or local parameters of the spatial points
446+ for (std ::pair < ASMbase * const ,PatchPoints > & pch : pchPoints )
447+ if (!pch .first -> findPoints (pch .second .second ,pch .second .first ))
448+ IFEM ::cout <<" ** Failed to locate some result points." << std ::endl ;
449+
429450 int iPoint = 0 ;
430451 size_t iX = 0 , iY = 0 ;
431452 for (ResPointVec ::iterator pit = points .begin (); pit != points .end ();)
432453 {
433454 bool pointIsOK = false;
434- ASMbase * pch = this -> getPatch (pit -> patch ,true);
435- if (pch && !pch -> empty ())
455+ if (ASMbase * pch = this -> getPatch (pit -> patch ,true); pch && !pch -> empty ())
436456 {
437457 if ((pointIsOK = pit -> inod > 0 )) // A nodal number is specified
438458 pit -> X = pch -> getCoord (pit -> inod );
439459
440- else if (pit -> inod < 0 ) // A spatial point is specified
441- pointIsOK = fabs (pch -> findPoint (pit -> X ,pit -> u )) < 1.0e-3 ;
442-
460+ else if (pit -> iel < 0 && !pchPoints .empty ())
461+ {
462+ // A spatial point is specified, use the point searching results
463+ size_t iP = - pit -> iel - 1 ;
464+ std ::map < ASMbase * ,PatchPoints > ::const_iterator it = pchPoints .find (pch );
465+ if (it != pchPoints .end () && iP < it -> second .first .size ())
466+ if ((pointIsOK = fabs (it -> second .first [iP ].dist ) < 1.0e-3 ))
467+ {
468+ pit -> npar = pch -> getNoParamDim ();
469+ pit -> X = it -> second .second [iP ];
470+ pit -> iel = it -> second .first [iP ].iel ;
471+ memcpy (pit -> u ,it -> second .first [iP ].u ,sizeof (double )* 3 );
472+ }
473+ }
443474 else if (pit -> npar > 0 ) // A parametric point is specified
475+ {
476+ pit -> npar = pch -> getNoParamDim ();
444477 pointIsOK = (pit -> inod = pch -> evalPoint (pit -> u ,pit -> u ,pit -> X )) >= 0 ;
445-
478+ }
446479 else if (pit -> iel < 1 ) // All nodes or element centers
447480 pointIsOK = true;
448481
@@ -455,8 +488,6 @@ void SIMoutput::preprocessResPtGroup (std::string& ptFile, ResPointVec& points)
455488
456489 if (pointIsOK )
457490 {
458- if (pit -> npar > 0 )
459- pit -> npar = pch -> getNoParamDim ();
460491 ++ pit ;
461492 ++ iPoint ;
462493 if (nX > 0 )
@@ -498,17 +529,33 @@ void SIMoutput::preprocessResPtGroup (std::string& ptFile, ResPointVec& points)
498529 IFEM ::cout <<", node #" << pt .inod ;
499530 else if (pt .iel > 0 )
500531 IFEM ::cout <<", element #" << pt .iel ;
501- if (pt .inod > 0 && myModel .size () > 1 )
532+ ASMbase * pch = this -> getPatch (pt .patch ,true);
533+ if (pch )
502534 {
503- ASMbase * pch = this -> getPatch (pt .patch ,true);
504- IFEM ::cout <<", global #" << pch -> getNodeID (pt .inod );
535+ int globalId = 0 ;
536+ if (pt .inod > 0 )
537+ {
538+ if (int nodeId = pch -> getNodeID (pt .inod );
539+ nodeId != pt .inod || myModel .size () > 1 )
540+ globalId = nodeId ;
541+ }
542+ else if (pt .iel > 0 )
543+ {
544+ if (int elmId = pch -> getElmID (pt .iel );
545+ elmId != pt .iel || myModel .size () > 1 )
546+ globalId = elmId ;
547+ }
548+ if (globalId > 0 )
549+ IFEM ::cout <<", global #" << globalId ;
505550 }
506551 if (pt .npar > 0 || pt .iel > 0 )
507552 IFEM ::cout <<", X = " << pt .X << std ::endl ;
508553 else if (pt .npar < 0 )
509554 IFEM ::cout <<", element centers will be used." << std ::endl ;
510555 else
511556 IFEM ::cout <<", nodal points will be used." << std ::endl ;
557+ if (pch && pt .iel > 0 )
558+ pch -> printElmInfo (pt .iel ,myProblem );
512559 }
513560 }
514561
@@ -539,7 +586,7 @@ void SIMoutput::preprocessResPtGroup (std::string& ptFile, ResPointVec& points)
539586 for (const ResultPoint & pt : points )
540587 {
541588 os << 0.0 <<" " ; // dummy time
542- for (short int k = 0 ; k < pt . npar ; k ++ )
589+ for (short int k = 0 ; k < nsd ; k ++ )
543590 os << std ::setw (flWidth ) << pt .X [k ];
544591 os << std ::endl ;
545592 }
@@ -561,8 +608,7 @@ bool SIMoutput::merge (SIMbase* that, const std::map<int,int>* old2new,
561608 for (ResultPoint & rp : rptp .second )
562609 {
563610 if (++ iPoint == 1 ) IFEM ::cout <<'\n' ;
564- ASMbase * pch = that -> getPatch (rp .patch ,true);
565- if (pch && rp .inod > 0 )
611+ if (ASMbase * pch = that -> getPatch (rp .patch ,true); pch && rp .inod > 0 )
566612 IFEM ::cout <<"Result point #" << iPoint <<": patch #" << rp .patch
567613 <<", local node " << rp .inod
568614 <<" global node " << pch -> getNodeID (rp .inod ) << std ::endl ;
@@ -1796,11 +1842,11 @@ bool SIMoutput::dumpMatlabGrid (std::ostream& os, const std::string& name,
17961842 os <<"]=" << name << std ::endl ;
17971843
17981844 // Write out nodes for the specified topology sets
1799- TopologySet ::const_iterator tit ;
18001845 for (const std ::string & setname : sets )
18011846 {
18021847 std ::set < int > nodeSet ;
1803- if ((tit = myEntitys .find (setname )) != myEntitys .end ())
1848+ if (TopologySet ::const_iterator tit = myEntitys .find (setname );
1849+ tit != myEntitys .end ())
18041850 for (const TopItem & top : tit -> second )
18051851 if (ASMbase * pch = this -> getPatch (top .patch ); pch )
18061852 if (top .idim + 1 == pch -> getNoParamDim ())
@@ -2021,7 +2067,7 @@ bool SIMoutput::dumpResults (const Vector& psol, double time,
20212067 }
20222068
20232069 bool newLine = false;
2024- // Convenience lambda returning proper newline character before identifier.
2070+ // Convenience lambda returning proper newline char before identifier.
20252071 auto&& newLineChr = [& newLine ]() { return newLine ? "\n\t\t" : ":\t" ; };
20262072
20272073 if (formatted && !sol1 .empty ())
@@ -2124,6 +2170,8 @@ bool SIMoutput::evalResults (const Vectors& psol, const ResPointVec& gPoints,
21242170 else if (pt .iel > 0 )
21252171 {
21262172 elms .push_back (pt .iel );
2173+ for (short int k = 0 ; k < pt .npar ; k ++ )
2174+ params [k ].push_back (pt .u [k ]);
21272175 }
21282176 else if (pt .npar < 0 )
21292177 {
@@ -2226,7 +2274,8 @@ bool SIMoutput::evalResults (const Vectors& psol, const ResPointVec& gPoints,
22262274 if (elms .empty ())
22272275 ok = patch -> evalSolution (tmp ,* myProblem ,params .data (),points .empty ());
22282276 else // evaluate at specified elements
2229- ok = patch -> evalSolution (tmp ,* myProblem ,elms );
2277+ ok = patch -> evalSolution (tmp ,* myProblem ,elms ,
2278+ params .front ().empty () ? nullptr : params .data ());
22302279
22312280 if ((ok &= augment (sol2 ,tmp )) && getNames )
22322281 for (size_t i = 0 ; i < myProblem -> getNoFields (2 ); i ++ )
0 commit comments