atlas.c
Go to the documentation of this file.
1 #include "atlas.h"
2 
3 #include "defines.h"
4 #include "error.h"
5 #include "random.h"
6 #include "algebra.h"
7 #include "samples.h"
8 
9 #include <string.h>
10 #include <math.h>
11 #ifdef _OPENMP
12  #include <omp.h>
13 #endif
14 
25 /***************************************************************/
26 
32 typedef struct {
33  unsigned int st;
34  unsigned int nc;
36  unsigned int ns;
37  unsigned int ms;
38  double **path;
39 } TMinTrace;
40 
41 
42 
43 /***************************************************************/
44 
50 typedef struct {
51  double cost;
52  double heuristic;
53  unsigned int status;
54 } TAStarInfo;
55 
56 /***************************************************************/
57 
66 
75 
145 
162 
195 
208 
217 
229 
239 
249 
266 
267 /***********************************************************************/
268 /***********************************************************************/
269 /***********************************************************************/
270 
286 void PostProcessNewCharts(Tparameters *pr,boolean bif,unsigned int parentID,
287  TAtlasStatistics *st,Tatlas *a);
288 
314 void NewChartFromPoint(Tparameters *pr,unsigned int parentID,double *t,
315  Tchart **newChart,Tatlas *a);
316 
338 void ReconstructAtlasPath(Tparameters *pr,unsigned int *pred,
339  unsigned int mID,double *goal,unsigned int nv,
340  boolean *systemVars,
341  double *pl,unsigned int *ns,double ***path,Tatlas *a);
342 
382 boolean DetermineChartNeighbours(Tparameters *pr,boolean bif,
383  unsigned int cmID,unsigned int parentID,Tatlas *a);
384 
412 double GeodesicDistance(Tparameters *pr,unsigned int parentID,unsigned int childID,
413  Tatlas *a);
414 
426 void ComputeAtlasHessian(Tatlas *a);
427 
435 void DeleteAtlasHessian(Tatlas *a);
436 
445 void SetAtlasTopology(Tparameters *pr,Tatlas *a);
446 
447 /***********************************************************************/
448 /***********************************************************************/
449 /***********************************************************************/
450 
468 boolean DetectBifurcation(Tparameters *pr,unsigned int mID1,unsigned int mID2,Tatlas *a);
469 
491 boolean FindSingularPoint(Tparameters *pr,unsigned int bID,Tatlas *a);
492 
524 boolean RefineSingularPoint(Tparameters *pr,unsigned int bID,Tatlas *a);
525 
552 unsigned int FindRightNullVector(Tparameters *pr,unsigned int bID,
553  double **phi,Tatlas *a);
554 
555 
594 boolean FindPointInOtherBranch(Tparameters *pr,unsigned int bID,double *phi,double **p,Tatlas *a);
595 
596 
615 void DefineChartsAtBifurcation(Tparameters *pr,unsigned int bID,double *v,
616  TAtlasStatistics *ast,Tatlas *a);
617 
634 void ProcessBifurcation(Tparameters *pr,unsigned int bID,TAtlasStatistics *ast,Tatlas *a);
635 
644 void LoadBifurcations(FILE *f,Tatlas *a);
645 
654 void SaveBifurcations(FILE *f,Tatlas *a);
655 
672 void PlotBifurcations(Tparameters *pr,Tplot3d *p3d,
673  unsigned int xID,unsigned int yID,unsigned int zID,Tatlas *a);
674 
682 void DeleteBifurcations(Tatlas *a);
683 
684 /***********************************************************************/
685 /***********************************************************************/
686 /***********************************************************************/
687 
689 {
690  if (ast!=NULL)
691  {
692  ast->nExtensions=0;
693  ast->nBoundaryAttempts=0;
694  ast->nNotInBoundary=0;
695  ast->nLargeError=0;
696  ast->nNonRegularPoint=0;
697  ast->nNotInManifold=0;
698  ast->nQRSVDError=0;
699  ast->nFarFromParent=0;
700  ast->nInCollision=0;
701  ast->nRadiousChange=0;
702  ast->nGoodExtension=0;
703  ast->nImpossible=0;
704  ast->nSingImpossible=0;
705  ast->nBifurcations=0;
706  ast->nSmallAngle=0;
707  ast->nSPMissed=0;
708  ast->nNoSingularEnough=0;
709  ast->nNoJumpBranch=0;
710  }
711 }
712 
714 {
715  if (ast!=NULL)
716  ast->nExtensions++;
717 }
718 
720 {
721  if (ast!=NULL)
722  ast->nBoundaryAttempts++;
723 }
724 
726 {
727  if (ast!=NULL)
728  ast->nNotInBoundary++;
729 }
730 
732 {
733  if (ast!=NULL)
734  ast->nLargeError++;
735 }
736 
738 {
739  if (ast!=NULL)
740  ast->nNonRegularPoint++;
741 }
742 
744 {
745  if (ast!=NULL)
746  ast->nNotInManifold++;
747 }
748 
750 {
751  if (ast!=NULL)
752  ast->nQRSVDError++;
753 }
754 
756 {
757  if (ast!=NULL)
758  ast->nFarFromParent++;
759 }
760 
762 {
763  if (ast!=NULL)
764  ast->nInCollision++;
765 }
766 
768 {
769  if (ast!=NULL)
770  ast->nRadiousChange++;
771 }
772 
774 {
775  if (ast!=NULL)
776  ast->nGoodExtension++;
777 }
778 
780 {
781  if (ast!=NULL)
782  ast->nImpossible++;
783 }
784 
786 {
787  if (ast!=NULL)
788  ast->nSingImpossible++;
789 }
790 
792 {
793  if (ast!=NULL)
794  ast->nBifurcations++;
795 }
796 
798 {
799  if (ast!=NULL)
800  ast->nSmallAngle++;
801 }
802 
804 {
805  if (ast!=NULL)
806  ast->nSPMissed++;
807 }
808 
810 {
811  if (ast!=NULL)
812  ast->nNoSingularEnough++;
813 }
814 
816 {
817  if (ast!=NULL)
818  ast->nNoJumpBranch++;
819 }
820 
822 {
823  unsigned int db;
824 
825  if (ast!=NULL)
826  {
827  printf("Boundary attempts: %u\n",ast->nBoundaryAttempts);
828  printf(" Not in Boundary : %u (%3.2f)\n",
829  ast->nNotInBoundary,
830  100*(double)ast->nNotInBoundary/(double)ast->nBoundaryAttempts);
831  printf("Num Extensions : %u\n",ast->nExtensions);
832  printf(" Errors : %u (%3.2f)\n",
833  ast->nImpossible,
834  100*(double)ast->nImpossible/(double)ast->nExtensions);
835  printf(" Errors (Sing) : %u (%3.2f)\n",
836  ast->nSingImpossible,
837  100*(double)ast->nSingImpossible/(double)ast->nExtensions);
838  printf(" Large Error : %u (%3.2f)\n",
839  ast->nLargeError,
840  100*(double)ast->nLargeError/(double)ast->nExtensions);
841  printf(" Non-regular point : %u (%3.2f)\n",
842  ast->nNonRegularPoint,
843  100*(double)ast->nNonRegularPoint/(double)ast->nExtensions);
844  printf(" Not in Manifold : %u (%3.2f)\n",
845  ast->nNotInManifold,
846  100*(double)ast->nNotInManifold/(double)ast->nExtensions);
847  printf(" Decomp. Error : %u (%3.2f)\n",
848  ast->nQRSVDError,
849  100*(double)ast->nQRSVDError/(double)ast->nExtensions);
850  printf(" Far From Parent : %u (%3.2f)\n",
851  ast->nFarFromParent,
852  100*(double)ast->nFarFromParent/(double)ast->nExtensions);
853  printf(" Radius Changes : %u (%3.2f)\n",
854  ast->nRadiousChange,
855  100*(double)ast->nRadiousChange/(double)ast->nExtensions);
856  printf(" Collisions : %u (%3.2f)\n",
857  ast->nInCollision,
858  100*(double)ast->nInCollision/(double)ast->nExtensions);
859  printf(" Good ones : %u (%3.2f)\n",
860  ast->nGoodExtension,
861  100*(double)ast->nGoodExtension/(double)ast->nExtensions);
862 
863  db=(unsigned int)GetParameter(CT_DETECT_BIFURCATIONS,pr);
864  if (db==0)
865  printf("Bifurcation detection disabled\n");
866  else
867  {
868  printf("Detected bifurcations: %u\n",ast->nBifurcations);
869  if (ast->nBifurcations>0)
870  {
871  unsigned int n;
872 
873  n=(ast->nBifurcations-ast->nSPMissed-ast->nNoSingularEnough-ast->nNoJumpBranch);
874  printf(" Correct jumps : %u (%3.2f)\n",
875  n,100*n/(double)ast->nBifurcations);
876  printf(" Num Small angle : %u (%3.2f)\n",ast->nSmallAngle,
877  100*(double)ast->nSmallAngle/(double)n);
878  printf(" Missed singular points: %u (%3.2f)\n",ast->nSPMissed,
879  100*(double)ast->nSPMissed/(double)ast->nBifurcations);
880  printf(" Not enough singular : %u (%3.2f)\n",ast->nNoSingularEnough,
881  100*(double)ast->nNoSingularEnough/(double)ast->nBifurcations);
882  printf(" Error jumping : %u (%3.2f)\n",ast->nNoJumpBranch,
883  100*(double)ast->nNoJumpBranch/(double)ast->nBifurcations);
884  }
885  }
886  }
887 }
888 
889 /***********************************************************************/
890 /***********************************************************************/
891 /***********************************************************************/
892 
893 void PostProcessNewCharts(Tparameters *pr,boolean bif,unsigned int parentID,
894  TAtlasStatistics *st,Tatlas *a)
895 {
896  unsigned int i;
897 
898  for(i=a->npCharts;i<a->currentChart;i++)
899  {
900  if (!DetermineChartNeighbours(pr,bif,i,parentID,a))
901  Warning("Bifurcation undetected in PostProcessNewCharts. Redude epsilon?");
902  }
903  a->npCharts=a->currentChart;
904 
905  /* If parentID is NO_UINT we are defining charts at a bifurcation (we are inside
906  ProcessBifurcation) and, thus, we have to avoid infitinte loops. */
907  if (parentID!=NO_UINT)
908  {
909  /* if bif==FALSE no new bifurcations will be detected and, thus, the code
910  below is not used (nBifurcations==npBifurcations). In some cases, though
911  bifurcations are detected externally (see AddChart2AtlasNS) and, thus
912  they are processed here. */
913  for(i=a->npBifurcations;i<a->nBifurcations;i++)
914  ProcessBifurcation(pr,i,st,a);
916  }
917 }
918 
919 void NewChartFromPoint(Tparameters *pr,unsigned int parentID,double *t,
920  Tchart **newChart,Tatlas *a)
921 {
922  /* If the vertex is already inside the ball, we are refining the approximation of the
923  domain border. Thus, we have to avoid the eventual creation of new charts.*/
924  if (Norm(a->k,t)<0.99*a->r)
925  *newChart=NULL;
926  else
927  {
928  double s;
929  boolean canContinue,chartCreated,smallError,closeEnough,wrong,outOfDomain;
930  double *pt,*ct;
931  unsigned int chartCode;
932  double epsilon;
933 
934  NEW(pt,a->m,double);
935 
936  NEW(*newChart,1,Tchart);
937 
938  /* current set of parameters */
939  NEW(ct,a->k,double);
940 
941  epsilon=GetParameter(CT_EPSILON,pr);
942 
943  s=1.0;
944  canContinue=TRUE;
945  chartCreated=FALSE;
946  closeEnough=FALSE;
947  smallError=FALSE;
948  outOfDomain=FALSE;
949 
950  do {
951  /* update the current set of paremter (ct) using the given parameters (t)
952  and the current scale factor (s) */
953  memcpy(ct,t,a->k*sizeof(double));
954  ScaleVector(s,a->k,ct);
955 
956  smallError=(Chart2Manifold(pr,&(a->J),ct,NULL,NULL,pt,a->charts[parentID])<=a->e);
957 
958  if (smallError)
959  {
960  chartCode=InitChart(pr,a->simpleChart,a->ambient,a->tp,
961  a->m,a->k,pt,a->e,a->ce, a->r,&(a->J),a->w,
962  *newChart);
963  chartCreated=(chartCode==0);
964 
965  if (chartCreated)
966  {
967  if ((CollisionChart(*newChart))||
968  (!PointInBoxTopology(NULL,TRUE,a->m,pt,epsilon,a->tp,a->ambient))||
969  (!CS_WD_SIMP_INEQUALITIES_HOLD(pr,pt,a->w)))
970  outOfDomain=TRUE;
971  else
972  closeEnough=(CloseCharts(pr,a->tp,
973  a->charts[parentID],
974  *newChart));
975  }
976  }
977 
978  if (!outOfDomain)
979  {
980  wrong=((!smallError)||(!chartCreated)||(!closeEnough));
981 
982  if (wrong)
983  {
984  canContinue=(s>MIN_SAMPLING_RADIUS);
985  if (canContinue)
986  {
988 
989  /* We will create a new chart -> delete the just generated one, if any */
990  if (chartCreated)
991  {
992  DeleteChart(*newChart);
993  chartCreated=FALSE;
994  }
995  }
996  }
997  }
998  } while((!outOfDomain)&&(wrong)&&(canContinue));
999 
1000  /* If we didn't manage to create the new chart, we remove any possibly created chart. */
1001  if ((outOfDomain)||(!canContinue))
1002  {
1003  if (outOfDomain)
1004  ChartIsFrontier(a->charts[parentID]);
1005  if (chartCreated)
1006  DeleteChart(*newChart);
1007  free(*newChart);
1008  *newChart=NULL;
1009  }
1010  free(ct);
1011  free(pt);
1012  }
1013 }
1014 
1015 boolean ExtendAtlasFromPoint(Tparameters *pr,unsigned int parentID,double *t,
1016  TAtlasStatistics *st,Tatlas *a)
1017 {
1018  double s;
1019  boolean canContinue,canInitChart,smallError,closeEnough,wrong;
1020  boolean searchBorder,inside;
1021  double *pt,*ct;
1022  boolean ok;
1023  unsigned int chartCode;
1024  double epsilon;
1025  #if (!SIMPLE_BORDER)
1026  boolean outOfDomain;
1027  double l,u;
1028  #endif
1029 
1030  ok=FALSE; /* No new chart is generated */
1031 
1032  NEW(pt,a->m,double);
1033 
1034  if (a->currentChart==a->maxCharts)
1035  MEM_DUP(a->charts,a->maxCharts,Tchart *);
1036 
1037  NEW(a->charts[a->currentChart],1,Tchart);
1038 
1039  /* current set of parameters */
1040  NEW(ct,a->k,double);
1041 
1042  /* If the vertex is already inside the ball, we are refining the approximation of the
1043  domain border. Thus, we have to avoid the eventual creation of new charts.*/
1044  inside=(Norm(a->k,t)<0.99*a->r);
1045 
1046  epsilon=GetParameter(CT_EPSILON,pr);
1047 
1048  s=1.0;
1049  canContinue=TRUE;
1050  canInitChart=FALSE;
1051  closeEnough=FALSE;
1052  smallError=FALSE;
1053  searchBorder=FALSE;
1054  #if (!SIMPLE_BORDER)
1055  outOfDomain=FALSE;
1056  #endif
1057 
1058  do {
1059  NewAtlasExtension(st);
1060 
1061  canInitChart=FALSE; /* Just to indicate that no chart has been created so far in this iteration */
1062 
1063  /* update the current set of paremter (ct) using the given parameters (t)
1064  and the current scale factor (s) */
1065  memcpy(ct,t,a->k*sizeof(double));
1066  ScaleVector(s,a->k,ct);
1067 
1068  smallError=(Chart2Manifold(pr,&(a->J),ct,NULL,NULL,pt,a->charts[parentID])<=a->e);
1069 
1070  if (smallError)
1071  {
1072  /* We skip the chart construction during the dichotomic search for the border.
1073  A valid chart was already been defined when triggering the search. */
1074  if (searchBorder)
1075  {
1076  #if (!SIMPLE_BORDER)
1077  outOfDomain=((!PointInBoxTopology(NULL,TRUE,a->m,pt,epsilon,a->tp,a->ambient))||
1078  (!CS_WD_SIMP_INEQUALITIES_HOLD(pr,pt,a->w)));
1079  if (!outOfDomain)
1080  CS_WD_IN_COLLISION(outOfDomain,pr,pt,NULL,a->w);
1081  #endif
1082 
1083  chartCode=NO_UINT; /* -> chart actually not created */
1084  }
1085  else
1086  {
1087  chartCode=InitChart(pr,a->simpleChart,a->ambient,a->tp,
1088  a->m,a->k,pt,a->e,a->ce, a->r,&(a->J),a->w,
1089  a->charts[a->currentChart]);
1090  canInitChart=(chartCode==0);
1091 
1092  if (canInitChart)
1093  {
1094  if ((CollisionChart(a->charts[a->currentChart]))||
1095  (!PointInBoxTopology(NULL,TRUE,a->m,pt,epsilon,a->tp,a->ambient))||
1096  (!CS_WD_SIMP_INEQUALITIES_HOLD(pr,pt,a->w)))
1097  {
1098  #if (!SIMPLE_BORDER)
1099  outOfDomain=TRUE;
1100  #endif
1101  searchBorder=TRUE;
1102  #if (!SIMPLE_BORDER)
1103  l=0;
1104  u=s;
1105  #endif
1106  }
1107  else
1108  {
1109  #if (!SIMPLE_BORDER)
1110  outOfDomain=FALSE;
1111  #endif
1112 
1113  closeEnough=(CloseCharts(pr,a->tp,
1114  a->charts[parentID],
1115  a->charts[a->currentChart]));
1116  if (!closeEnough)
1117  {
1118  NewFarFromParent(st);
1119  searchBorder=FALSE; /* if searching for border -> stop the search */
1120  }
1121  else
1122  NewGoodExtension(st);
1123  }
1124  }
1125  else
1126  {
1127  switch (chartCode)
1128  {
1129  case 1:
1130  case 2:
1131  NewNonRegularPoint(st);
1132  break;
1133  case 3:
1135  break;
1136  case 4:
1137  NewNotInManifold(st);
1138  break;
1139  default:
1140  Error("Unknown chart creation error code");
1141  }
1142  }
1143  }
1144  }
1145  else
1146  {
1147  NewLargeError(st);
1148  searchBorder=FALSE; /* if searching for border -> stop the search */
1149  }
1150 
1151  wrong=((searchBorder)||(!smallError)||(!canInitChart)||(!closeEnough));
1152 
1153  if (wrong)
1154  {
1155  /* If something when wrong but we created a chart -> delete it */
1156  if (canInitChart)
1157  {
1159  canInitChart=FALSE; /* this indicates that the chart is already deleted */
1160  }
1161 
1162  if (searchBorder)
1163  {
1164  /* dichotomic search for the border */
1165  #if (SIMPLE_BORDER)
1166  /* Simple boder -> vertices out of the domain are marked as such
1167  and no refinement is triggered. */
1168  canContinue=FALSE;
1169  #else
1170  canContinue=((u-l)>MIN_SAMPLING_RADIUS);
1171  if (canContinue)
1172  {
1173  if (outOfDomain)
1174  u=s;
1175  else
1176  l=s;
1177  s=(u+l)/2.0;
1178  }
1179  #endif
1180  }
1181  else
1182  {
1183  canContinue=(s>MIN_SAMPLING_RADIUS);
1184  if (canContinue)
1185  {
1187  NewRadiousChange(st);
1188  }
1189  }
1190  }
1191  } while((wrong)&&(canContinue));
1192 
1193  if (searchBorder)
1194  {
1195  #if (!SIMPLE_BORDER)
1196  /* Define a linear constraint to the parent chart along the border */
1197  AddBorderConstraint(pr,ct,a->tp,a->ambient,a->charts[parentID]);
1198  #endif
1199 
1200  ChartIsFrontier(a->charts[parentID]);
1201  }
1202  else
1203  {
1204  if (!inside)
1205  {
1206  if (!canContinue)
1207  {
1208  if (SingularChart(a->charts[parentID]))
1209  {
1211  printf(" Could not extend singular chart\n");
1212  }
1213  else
1214  {
1215  //Error("The impossible happened (I)");
1216  NewImpossible(st);
1217  }
1218  }
1219  else
1220  {
1221  #if (ATLAS_VERBOSE)
1222  printf(" New Chart %u\n",a->currentChart);
1223  #endif
1224  a->currentChart++;
1225  PostProcessNewCharts(pr,TRUE,parentID,st,a);
1226  ok=TRUE; /* We actually generated a new chart */
1227  }
1228  }
1229  }
1230 
1231  /* If no chart is actually generated, just release the allocated memory */
1232  if (!ok)
1233  {
1234  /* Just in case we cancelled the chart */
1235  if (canInitChart)
1237  free(a->charts[a->currentChart]);
1238  }
1239 
1240  free(ct);
1241  free(pt);
1242 
1243  return(ok);
1244 }
1245 
1246 boolean ExtendAtlasTowardPoint(Tparameters *pr,unsigned int parentID,double *t,
1247  boolean collisionStops,
1248  TAtlasStatistics *st,Tatlas *a)
1249 {
1250  double delta,s;
1251  double *tp,*pt,*ptGood;
1252  Tchart mTmp;
1253  boolean moved,inCollision,canInitChart,smallError,closeEnough;
1254  double r,n;
1255  unsigned int chartCode;
1256  double currentDelta;
1257  double epsilon;
1258 
1259  NEW(pt,a->m,double);
1260  NEW(tp,a->k,double);
1261  /* ptGood is the last point where we managed to generate a valid chart.
1262  Inintially, the center of the current chart but we try to move
1263  far from here. */
1264  NEW(ptGood,a->m,double);
1265  memcpy(ptGood,GetChartCenter(a->charts[parentID]),a->m*sizeof(double));
1266 
1267  n=Norm(a->k,t);
1268  r=GetChartRadius(a->charts[parentID]);
1269  epsilon=GetParameter(CT_EPSILON,pr);
1270  delta=GetParameter(CT_DELTA,pr);
1271  s=0.0; /* how much we advanced so far */
1272  currentDelta=delta; /* size of current step */
1273 
1274  inCollision=FALSE;
1275  canInitChart=TRUE;
1276  closeEnough=TRUE;
1277  smallError=TRUE;
1278  moved=FALSE;
1279 
1280  /* When extending a chart it is crucial to be able to generate at least
1281  one point in the given direction (except if there is an obstacle
1282  blocking this direction). Once we have at least one point in the
1283  given direction, we can generate a new chart on it that extends
1284  the atlas. Therefore we carefully adjust the advance step
1285  in case we are in a problematic area (singular, large curvature). */
1286  do {
1287  NewAtlasExtension(st);
1288  NewRadiousChange(st);
1289  /* See if vector t scaled by 's' is collision free and has small error */
1290  memcpy(tp,t,a->k*sizeof(double));
1291  ScaleVector((s+currentDelta)/n,a->k,tp);
1292 
1293  smallError=(Chart2Manifold(pr,&(a->J),tp,NULL,ptGood,pt,a->charts[parentID])<=a->e);
1294 
1295  if (smallError)
1296  {
1297  chartCode=InitChart(pr,a->simpleChart,a->ambient,a->tp,
1298  a->m,a->k,pt,a->e,a->ce,a->r,
1299  &(a->J),a->w,&mTmp);
1300  canInitChart=(chartCode==0);
1301 
1302  if (canInitChart)
1303  {
1304  closeEnough=(CloseCharts(pr,a->tp,
1305  a->charts[parentID],&mTmp));
1306  if (closeEnough)
1307  {
1308  if (collisionStops)
1309  inCollision=CollisionChart(&mTmp);
1310 
1311  if (!inCollision)
1312  {
1313  moved=TRUE;
1314  /* consolidate the advance */
1315  s+=currentDelta;
1316 
1317  /* If we moved beyond the chart radious-> stop here */
1318  if (s>=r)
1319  smallError=FALSE;
1320 
1321  /* Store the just generated valid point (this is how
1322  far we managed to get so far). */
1323  memcpy(ptGood,pt,sizeof(double)*a->m);
1324 
1325  NewGoodExtension(st);
1326 
1327  if (currentDelta!=delta)
1328  {
1329  /* We managed to generate a problematic
1330  initial point -> stop here */
1331  closeEnough=FALSE;
1332  }
1333  }
1334  else
1335  NewInCollision(st);
1336  }
1337  else
1338  NewFarFromParent(st);
1339  DeleteChart(&mTmp);
1340  }
1341  else
1342  {
1343  switch (chartCode)
1344  {
1345  case 1:
1346  case 2:
1347  NewNonRegularPoint(st);
1348  break;
1349  case 3:
1351  break;
1352  case 4:
1353  NewNotInManifold(st);
1354  break;
1355  default:
1356  Error("Unknown chart creation error code");
1357  }
1358  }
1359  }
1360  else
1361  NewLargeError(st);
1362 
1363  /* If not moved (i.e., we do not have a good point)
1364  for a reason different from a collision, try to
1365  adjust the avance step */
1366  if ((!moved)&&(!inCollision))
1367  {
1368  /* If we are not trying to jump over a singularity */
1369  if (currentDelta<=delta)
1370  {
1371  if (currentDelta>epsilon)
1372  {
1373  /* We are trying to generate the first point in
1374  a difficult area (singular or with very high
1375  curvature). Try to reduce the advance step with
1376  the purpose of finding a point just outside this
1377  problematic area. Note that the center of the
1378  current chart is outside this area and, thus
1379  we try to approach it.
1380  */
1381  currentDelta*=0.5;
1382  canInitChart=TRUE;
1383  smallError=TRUE;
1384  closeEnough=TRUE;
1385  }
1386  else
1387  {
1388  if (!canInitChart) /* assume charCode==1 */
1389  {
1390  /* We are in a singular area and the current
1391  chart is just at the border of this singular
1392  area (we can not create any other chart closer
1393  to the singular area). In this case we try
1394  to jump over the singular area with a large
1395  jump. Note that this can produce some
1396  collisions that are not detected. This large
1397  jump is only tried once. If it does not work
1398  the extension is declared a failure and a warning
1399  is issued.
1400 
1401  In theory, singularities are zero volum areas but
1402  in practice they have some thickness that is given
1403  by the used numerical accuracy (epsilon)
1404  */
1405  currentDelta=5*delta;
1406  canInitChart=TRUE;
1407  smallError=TRUE;
1408  closeEnough=TRUE;
1409  }
1410  }
1411  }
1412  }
1413 
1414  } while((smallError)&&(canInitChart)&&(closeEnough)&&(!inCollision));
1415 
1416  if (!moved)
1417  {
1418  /* Could not extend at all */
1419  if (!inCollision)
1420  {
1421  if ((currentDelta>delta)||(!canInitChart)||(SingularChart(a->charts[parentID])))
1422  {
1424  printf(" Could not jump over a singularity (decrease epsilon?)");
1425  }
1426  else
1427  {
1428  /* !smallError or !closeEnough */
1429  NewImpossible(st);
1430  Error(" The impossible happened (II)");
1431  }
1432  }
1433  }
1434  else
1435  {
1436  /* Generate the new chart. In the case where extending the atlas in parallel,
1437  this part has to be executed sequentially. */
1438  if (a->currentChart==a->maxCharts)
1439  MEM_DUP(a->charts,a->maxCharts,Tchart *);
1440 
1441  NEW(a->charts[a->currentChart],1,Tchart);
1442 
1443  if (InitChart(pr,a->simpleChart,a->ambient,a->tp,
1444  a->m,a->k,ptGood,a->e,a->ce, a->r,
1445  &(a->J),a->w,a->charts[a->currentChart])!=0)
1446  Error("Can not create a chart already created just above?");
1447 
1448  #if (ATLAS_VERBOSE)
1449  printf(" New Chart %u\n",a->currentChart);
1450  #endif
1451 
1452  a->currentChart++;
1453  PostProcessNewCharts(pr,TRUE,parentID,st,a);
1454  }
1455 
1456  free(pt);
1457  free(ptGood);
1458  free(tp);
1459 
1460  return(moved);
1461 }
1462 
1463 void ReconstructAtlasPath(Tparameters *pr,unsigned int *pred,
1464  unsigned int mID,double *goal,unsigned int nv,
1465  boolean *systemVars,
1466  double *pl,unsigned int *ns,double ***path,Tatlas *a)
1467 {
1468  unsigned int nvs,i,k;
1469  unsigned int ms;
1470  unsigned int *chartID;
1471  signed int s;
1472  double *t,*o;
1473  Tchart *cp,*c;
1474 
1475  *pl=0;
1476 
1477  NEW(t,a->k,double);
1478 
1479  nvs=0;
1480  for(i=0;i<nv;i++)
1481  {
1482  if (systemVars[i])
1483  nvs++;
1484  }
1485 
1486  InitSamples(&ms,ns,path);
1487 
1488  /* Count the number of charts to be visited along the path */
1489  i=mID;
1490  k=0;
1491  while (i!=NO_UINT)
1492  {
1493  k++;
1494  i=pred[i];
1495  }
1496 
1497  /* Store the charts to be visited along the path (in the correct
1498  order) */
1499  NEW(chartID,k,unsigned int);
1500  s=k-1;
1501  i=mID;
1502  while (i!=NO_UINT)
1503  {
1504  chartID[s]=i;
1505  s--;
1506  i=pred[i];
1507  }
1508 
1509  /* Reconstruct the path in each chart (from the center of the
1510  chart to the projection of the center of next chart) */
1511  cp=a->charts[chartID[0]];
1512  for(i=1;i<k;i++)
1513  {
1514  c=a->charts[chartID[i]];
1515  Manifold2Chart(GetChartCenter(c),a->tp,t,cp);
1516  #if (_DEBUG>2)
1517  printf(" Step to %u %f\n",chartID[i],Norm(a->k,t));
1518  #endif
1519  if (!PathInChart(pr,t,a->tp,&(a->J),nvs,systemVars,&ms,pl,ns,path,cp))
1520  {
1521  if (ATLAS_VERBOSE)
1522  Warning("Collision when reconstructing path in atlas");
1523  }
1524  cp=c;
1525  }
1526 
1527  /* And now the path on last chart to the goal */
1528  Manifold2Chart(goal,a->tp,t,cp);
1529  #if (_DEBUG>2)
1530  printf(" Last step %f\n",Norm(a->k,t));
1531  #endif
1532  if (!PathInChart(pr,t,a->tp,&(a->J),nvs,systemVars,&ms,pl,ns,path,cp))
1533  {
1534  if (ATLAS_VERBOSE)
1535  Warning("Collision when reconstructing path in atlas");
1536  }
1537 
1538  /* and add the goal */
1539  CS_WD_REGENERATE_ORIGINAL_POINT(pr,goal,&o,c->w);
1540  AddSample2Samples(nv,o,nvs,systemVars,&ms,ns,path);
1541  free(o);
1542 
1543  free(chartID);
1544  free(t);
1545 }
1546 
1547 boolean DetermineChartNeighbours(Tparameters *pr,boolean bif,
1548  unsigned int cmID,unsigned int parentID,
1549  Tatlas *a)
1550 {
1551  unsigned int i;
1552  unsigned int db;
1553  boolean singular;
1554 
1555  singular=FALSE;
1556 
1557  db=(unsigned int)GetParameter(CT_DETECT_BIFURCATIONS,pr);
1558 
1559  if ((a->n==0)||(db==0))
1560  /* Overide the caller setting if we do not want to detect bifurcations */
1561  bif=FALSE;
1562 
1563  if (ChartNumNeighbours(a->charts[cmID])>0)
1564  Error("DetermineChartNeighbours must be used for charts without any neighbour.");
1565 
1566  #if (USE_ATLAS_TREE)
1567  unsigned int nn=0,id;
1568  unsigned int *n=NULL;
1569  boolean intersectWithParent;
1570 
1571  SearchInBtree(a->charts[cmID],&nn,&n,&(a->tree));
1572  intersectWithParent=FALSE;
1573  for(i=0;i<nn;i++)
1574  {
1575  id=n[i];
1576  if (id==cmID)
1577  Error("The chart was not supposed to be in the tree");
1578 
1579  if (IntersectCharts(pr,a->tp,a->ambient,
1580  id,a->charts[id],cmID,a->charts[cmID]))
1581  {
1582  #if (ATLAS_VERBOSE)
1583  fprintf(stderr," Chart %u intersects with chart %u\n",cmID,id);
1584  #endif
1585  if ((bif)&&((db>1)||(parentID==NO_UINT)||(id==parentID)))
1586  singular|=(!DetectBifurcation(pr,cmID,id,a)); /* id=parent*/
1587 
1588  if (id==parentID)
1589  intersectWithParent=TRUE;
1590  }
1591  }
1592 
1593  if ((parentID!=NO_UINT)&&(!intersectWithParent))
1594  Error("A chart that does not intersect with its parent");
1595  if (nn>0)
1596  free(n);
1597 
1598  /* We add the chart to the tree at the end to avoid self-intersection. */
1599  AddChart2Btree(cmID,a->charts[cmID],&(a->tree));
1600  #else
1601  for(i=0;i<a->currentChart;i++)
1602  {
1603  if (i!=cmID)
1604  {
1605  if (IntersectCharts(pr,a->tp,a->ambient,
1606  i,a->charts[i],cmID,a->charts[cmID]))
1607  {
1608 
1609  #if (ATLAS_VERBOSE)
1610  fprintf(stderr," Chart %u intersects with chart %u\n",cmID,id);
1611  #endif
1612  if ((bif)&&((db>1)||(parentID==NO_UINT)||(i==parentID)))
1613  singular|=(!DetectBifurcation(pr,cmID,i,a));
1614  }
1615  else
1616  {
1617  if (i==parentID)
1618  Error("A chart that does not intersect with its parent");
1619  }
1620  }
1621  }
1622  #endif
1623 
1624  return(!singular);
1625 }
1626 
1627 double GeodesicDistance(Tparameters *pr,unsigned int parentID,unsigned int childID,
1628  Tatlas *a)
1629 {
1630  double d;
1631 
1632  if (a->n==0)
1633  d=DistanceTopology(a->m,a->tp,
1634  GetChartCenter(a->charts[parentID]),
1635  GetChartCenter(a->charts[childID]));
1636  else
1637  {
1638  double *v,*pt,*ptPrev;
1639  Tchart *c;
1640  double *start,*goal;
1641  double dStep;
1642  double delta;
1643  boolean projectionOk,inCollision,reached;
1644  unsigned int step;
1645  #if (PROJECT_WITH_PLANE)
1646  double *ptp;
1647  #endif
1648 
1649  NEW(v,a->m,double);
1650  NEW(pt,a->m,double);
1651  NEW(ptPrev,a->m,double);
1652  #if (PROJECT_WITH_PLANE)
1653  NEW(ptp,a->m,double);
1654  #endif
1655 
1656  c=a->charts[parentID];
1657  start=GetChartCenter(c);
1658  goal=GetChartCenter(a->charts[childID]);
1659 
1660  DifferenceVectorTopology(a->m,a->tp,goal,start,v);
1661 
1662  delta=GetParameter(CT_DELTA,pr);
1663  d=0.0;
1664  step=1;
1665  memcpy(ptPrev,start,a->m*sizeof(double));
1666 
1667  projectionOk=TRUE;
1668  inCollision=FALSE;
1669  reached=FALSE;
1670 
1671  while((projectionOk)&&(!inCollision)&&(!reached)&&(d<INF))
1672  {
1673  SumVectorScale(a->m,start,(double)step*delta,v,pt);
1674 
1675  #if (PROJECT_WITH_PLANE)
1676  memcpy(ptp,pt,a->m*sizeof(double));
1677  projectionOk=Newton2ManifoldPlane(pr,ptp,v,ptPrev,pt,a);
1678  #else
1679  projectionOk=(CS_WD_NEWTON_IN_SIMP(pr,pt,a->w)!=DIVERGED);
1680  #endif
1681 
1682  if (projectionOk)
1683  {
1684  CS_WD_IN_COLLISION(inCollision,pr,pt,ptPrev,a->w);
1685 
1686  if (!inCollision)
1687  {
1688  dStep=DistanceTopology(a->m,a->tp,ptPrev,pt);
1689  if (dStep<(delta/100.0))
1690  d=INF; /* The advance is stalled-> declare impossible path */
1691  else
1692  {
1693  d+=dStep;
1694  memcpy(ptPrev,pt,a->m*sizeof(double));
1695  reached=(DistanceTopology(a->m,a->tp,pt,goal)<delta);
1696  }
1697  }
1698  else
1699  {
1700  d=INF;
1701  //printf("d[%u,%u]=INF due to collision (%u)\n",parentID,childID,step);
1702  }
1703  }
1704  else
1705  {
1706  /* This should never happen. We print a message to warn */
1707  d=INF;
1708  //printf("d[%u,%u]=INF due to not convergence (%u)\n",parentID,childID,step);
1709  }
1710 
1711  step++;
1712  }
1713 
1714  //if (d<INF)
1715  // printf("d[%u,%u]=%g\n",parentID,childID,d);
1716 
1717  free(v);
1718  free(pt);
1719  free(ptPrev);
1720  #if (PROJECT_WITH_PLANE)
1721  free(ptp);
1722  #endif
1723  }
1724  return(d);
1725 }
1726 
1727 /******************************************************************/
1728 /******************************************************************/
1729 /******************************************************************/
1730 
1731 boolean DetectBifurcation(Tparameters *pr,unsigned int mID1,unsigned int mID2,Tatlas *a)
1732 {
1733  double *T;
1734  Tchart *mp1,*mp2;
1735  unsigned int d1,d2;
1736  boolean singular,singular1,singular2;
1737 
1738  singular=FALSE;
1739 
1740  mp1=a->charts[mID1];
1741  mp2=a->charts[mID2];
1742 
1743  if ((!SingularChart(mp1))&&(!SingularChart(mp2)))
1744  {
1745  T=GetChartTangentSpace(mp1);
1746  d1=GetChartDegree(pr,T,&(a->J),&singular1,mp1);
1747  d2=GetChartDegree(pr,T,&(a->J),&singular2,mp2);
1748 
1749  singular=((singular1)||(singular2));
1750 
1751  #if (_DEBUG>2)
1752  printf(" *Degree of chart %u -> %u [%u]\n",mID1,d1,singular1);
1753  printf(" -Degree of chart %u -> %u [%u]\n",mID2,d2,singular2);
1754  #endif
1755 
1756  /* When very close to a singularity, the chart might be declared
1757  non singular in creation but be singular in practice when
1758  computing it degree. */
1759  if ((!singular1)&&(!singular2)&&(d1!=d2))
1760  {
1761  if (a->nBifurcations==a->mBifurcations)
1763 
1765  a->bifurcation[a->nBifurcations]->mID1=mID1;
1766  a->bifurcation[a->nBifurcations]->d1=d1;
1767  a->bifurcation[a->nBifurcations]->mID2=mID2;
1768  a->bifurcation[a->nBifurcations]->d2=d2;
1769  a->bifurcation[a->nBifurcations]->p=NULL;
1770  a->nBifurcations++;
1771  }
1772  }
1773  return(!singular);
1774 }
1775 
1776 boolean FindSingularPoint(Tparameters *pr,unsigned int bID,Tatlas *a)
1777 {
1778  /* Detect the singularity point */
1779  unsigned int degreeLow,degreeUp,degree;
1780  double *d,*tg1,*tg2,*p,*T;
1781  boolean done,error;
1782  Tchart tmpM,*m1,*m2;
1783  double epsilon;
1784  unsigned int nm;
1785  double t,tLow,tUp;
1786  double c1,c2;
1787  boolean singular;
1788  double *p1,*p2,*tg;
1789 
1790  epsilon=GetParameter(CT_EPSILON,pr);
1791 
1792  degreeLow=a->bifurcation[bID]->d1;
1793  degreeUp =a->bifurcation[bID]->d2;
1794 
1795  if (degreeLow==degreeUp)
1796  Error("Degrees must be different at FindSingularPoint");
1797 
1798  m1=a->charts[a->bifurcation[bID]->mID1];
1799  m2=a->charts[a->bifurcation[bID]->mID2];
1800 
1801  NEW(tg1,a->k,double);
1802  NEW(tg2,a->k,double);
1803 
1804  NEW(p1,a->m,double);
1805  memcpy(p1,GetChartCenter(m1),a->m*sizeof(double));
1806  Manifold2Chart(p1,a->tp,tg1,m1); /*tg1 is zero*/
1807 
1808  NEW(p2,a->m,double);
1809  memcpy(p2,GetChartCenter(m2),a->m*sizeof(double));
1810  Manifold2Chart(p2,a->tp,tg2,m1);
1811 
1812  T=GetChartTangentSpace(m1);
1813 
1814  NEW(d,a->k,double);
1815  NEW(tg,a->k,double);
1816  NEW(p,a->m,double);
1817  memcpy(p,p2,a->m*sizeof(double));
1818 
1819  done=FALSE;
1820  error=FALSE;
1821  if (CompareTangentSpaces(m1,m2))
1822  error=FALSE;
1823  else
1824  {
1825  printf(" Incompatible initial charts in FindSingularPoint\n");
1826  error=TRUE;
1827  }
1828 
1829  DifferenceVector(a->k,tg2,tg1,d);
1830  tLow=0.0;
1831  tUp=1.0;
1832 
1833  while((!done)&&(!error))
1834  {
1835  t=(tLow+tUp)/2.0;
1836 
1837  SumVectorScale(a->k,tg1,t,d,tg);
1838 
1839  if (Chart2Manifold(pr,&(a->J),tg,NULL,p,p,m1)>a->e)
1840  error=TRUE;
1841 
1842  if ((!done)&&(!error))
1843  {
1844  /* Some of the chart generated in the search might be almost singular. We
1845  do not trigger an error if they are singular but we do not force the
1846  chart to be singular anyway. Just use the information from the numerical
1847  procedure without pre-defining if the point is regular or not. */
1849  a->m,a->k,p,a->e,a->ce,a->r,&(a->J),a->w,&tmpM);
1850 
1851  if (nm<2) /* 0: no error 1: singular chart */
1852  {
1853  if (SingularChart(&tmpM))
1854  done=TRUE;
1855  else
1856  {
1857  c1=MinCosinusBetweenCharts(m1,&tmpM);
1858  c2=MinCosinusBetweenCharts(&tmpM,m2);
1859 
1860  if ((c1<(1-a->ce))||(c2<(1-a->ce)))
1861  {
1862  /* This is typically the case where, accidentally, we ended up
1863  in the other branch */
1864  printf(" Could not find singular point. Large tangent error %f (%f %f)\n",tUp-tLow,c1,c2);
1865  error=TRUE;
1866  }
1867  else
1868  {
1869  degree=GetChartDegree(pr,T,&(a->J),&singular,&tmpM);
1870 
1871  if (singular)
1872  done=TRUE;
1873  else
1874  {
1875  if (degree==degreeLow)
1876  {
1877  tLow=t;
1878  memcpy(p1,p,a->m*sizeof(double));
1879  }
1880  else
1881  {
1882  if (degree==degreeUp)
1883  {
1884  tUp=t;
1885  memcpy(p2,p,a->m*sizeof(double));
1886  }
1887  else
1888  Error("Incoherent degree change");
1889  }
1890 
1891  done=((tUp-tLow)<100*epsilon);
1892  }
1893  }
1894  }
1895  DeleteChart(&tmpM);
1896  }
1897  else
1898  Error("Error initializing a new chart in FindSingularPoint");
1899  }
1900  }
1901  if (!error)
1902  {
1903  NEW(a->bifurcation[bID]->p,a->m,double);
1904  memcpy(a->bifurcation[bID]->p,p,a->m*sizeof(double));
1905 
1906  /* Try to improve the singular point estimation */
1907  //RefineSingularPoint(pr,bID,a);
1908  }
1909 
1910  free(tg);
1911  free(p1);
1912  free(p2);
1913  free(tg1);
1914  free(tg2);
1915  free(p);
1916  free(d);
1917 
1918  return(!error);
1919 }
1920 
1921 boolean RefineSingularPoint(Tparameters *pr,unsigned int bID,Tatlas *a)
1922 {
1923  double epsilon,nullSingularValue;
1924  unsigned int maxIterations;
1925  unsigned int i,j,k;
1926  double *y,*x,*lambda;
1927  unsigned int s,c,r;
1928  Tchart *c1;
1929  double *p1;
1930  double *phi;
1931  unsigned int it;
1932  boolean converged;
1933  double dif,d1,d2,d3;
1934 
1935  TNewton newton;
1936  double *J;
1937  double *bData;
1938  double *aData;
1939  double *ptr; /* used to access bData */
1940 
1941  int err;
1942 
1943  double ***h;
1944 
1945  /* This routine requires the Hessian, compute it if no
1946  already computed */
1947  if (a->H==NULL)
1948  {
1949  NEW(a->H,1,THessian);
1950  InitHessian(&(a->J),a->H);
1951  }
1952 
1953  epsilon=GetParameter(CT_EPSILON,pr);
1954  maxIterations=(unsigned int)GetParameter(CT_MAX_NEWTON_ITERATIONS,pr);
1955  nullSingularValue=epsilon/100;
1956 
1957  c1=a->charts[a->bifurcation[bID]->mID1];
1958  p1=GetChartCenter(c1);
1959  phi=GetChartTangentSpace(c1); /*This is m x k = ncJ x k*/
1960 
1961  /* As an improvement we could use an interpolation between the
1962  tangent spaces for c1 and c2 */
1963 
1964  /* Number of variables/columns of the system adjusted via Newton*/
1965  c=a->ncJ+a->ncJ; /* The original variables plus lambda */
1966  /* Number of equations/rows of the system adjusted via Newton */
1967  r=(a->nrJ+a->nrJ+a->k+1); /*F + J*lambda + phi*lambda + 1*/
1968 
1969  /* Space for the current estimation */
1970  NEW(y,c,double);
1971  /* Direct pointers to the two components of 'y' */
1972  x=y;
1973  lambda=&(y[a->ncJ]);
1974 
1975  /* Set up the initial value for 'y' */
1976 
1977  /* Initialize x to the current estimation of the singular point */
1978  if (a->bifurcation[bID]->p!=NULL)
1979  {
1980  /* We have an estimation of the singular point and want to
1981  refine it*/
1982  memcpy(x,a->bifurcation[bID]->p,sizeof(double)*a->ncJ);
1983  }
1984  else
1985  {
1986  /* Search the bifurcation from scratch. Depart from the
1987  center of the first chart */
1988  memcpy(x,p1,sizeof(double)*a->ncJ);
1989  }
1990 
1991  /* Space for the Jacobian evaluation */
1992  NEW(J,a->nrJ*a->ncJ,double); /* ncJ==m */
1993 
1994  #if (0)
1995  if (a->bifurcation[bID]->p!=NULL)
1996  {
1997  /* If we have an inintial estimation of the singular point, initialize lambda
1998  with the eigenvector for the smaller non-null eigenvalue.
1999  For this vector J*lambda is close to zero. */
2000 
2001  double *K;
2002 
2003  NEW(K,a->ncJ*(a->k+1),double);
2004 
2005  /* Re-use vector 'J' to store J^t */
2006  EvaluateTransposedJacobianInVector(a->bifurcation[bID]->p,a->ncJ,a->nrJ,J,&(a->J));
2007 
2008  FindKernel(a->nrJ,a->ncJ,J,a->k+1,FALSE,epsilon,&K);
2009 
2010  /* The kernel is returned from largest eigen value to smaller */
2011  GetColumn(0,a->ncJ,a->k+1,K,lambda);
2012 
2013  free(K);
2014  }
2015  else
2016  #else
2017  {
2018  lambda[0]=1;
2019  for(i=1;i<a->ncJ;i++)
2020  lambda[i]=0;
2021  }
2022  #endif
2023 
2024  /* Allocate space for the matrices to be used at each Newton step */
2025  InitNewton(r,c,&newton);
2026  aData=GetNewtonMatrixBuffer(&newton);
2027  /* set all entries to zero (many blocks remain zero all along the process) */
2028  s=r*c;
2029  for(i=0;i<s;i++)
2030  aData[i]=0.0;
2031 
2032  bData=GetNewtonRHBuffer(&newton); /* r entries */
2033 
2035 
2036  it=0;
2037  converged=FALSE;
2038  while((!converged)&&(it<maxIterations))
2039  {
2040  /* Set up the matrix */
2041 
2042  /* Get the Jacobian, we will use it in different steps below */
2043  EvaluateJacobianInVector(x,a->nrJ,a->ncJ,J,&(a->J));
2044 
2045  /* We first set up part of the matrix and then the residual since the
2046  residual evaluation needs the Jacobian, included in the matrix.*/
2047 
2048  /* The first block of the matrix comes from
2049  rows of the Jacobian (and a block of zeros at the end of each row) */
2050  SubMatrixFromMatrix(a->nrJ,a->ncJ,J,0,0,r,c,aData);
2051 
2052  /* Set up part of the residual (the one for 'x'). */
2053  /*F(x)=0*/
2054  CS_WD_EVALUATE_SIMP_EQUATIONS(pr,x,bData,a->w);
2055 
2056  /* Set up the rest of the residual (the one for 'lambda' that uses
2057  J just stored in aData) */
2058  /* J*lambda=0 */
2059  ptr=&(bData[a->nrJ]);
2060  MatrixVectorProduct(a->nrJ,a->ncJ,J,lambda,ptr);
2061 
2062  /* Now force lambda to be different from the vectors in the known
2063  tangent space (approximatted by the tangent space at the initial
2064  point, p1)
2065  phi' * lambda = 0 */
2066  TMatrixVectorProduct(a->m,a->k,phi,lambda,&(bData[a->nrJ+a->nrJ]));
2067 
2068  /* last element in the residual is lambda' lambda -1 =0 */
2069  bData[r-1]=GeneralDotProduct(a->ncJ,lambda,lambda)-1.0;
2070 
2071  d1=Norm(a->nrJ,bData);
2072  d2=Norm(a->nrJ,&(bData[a->nrJ]));
2073  d3=Norm(a->k,&(bData[a->nrJ+a->nrJ]));
2074  //d4=fabs(bData[r-1]);
2075  //if ((d1<epsilon)&&(d2<epsilon)&&(d3<epsilon)&&(d4<epsilon))
2076  if ((d1<10*epsilon)&&(d2<10*epsilon)&&(d3<10*epsilon))
2077  converged=TRUE;
2078  else
2079  {
2080  /* The Hessian part*/
2081  EvaluateHessian(x,h,a->H);
2082 
2083  /* The second block of the matrix comes from the Hessian */
2084  for(i=0;i<a->nrJ;i++)
2085  {
2086  for(j=0;j<a->ncJ;j++)
2087  {
2088  aData[RC2INDEX(a->nrJ+i,j,r,c)]=0.0;
2089  for(k=0;k<a->ncJ;k++)
2090  aData[RC2INDEX(a->nrJ+i,j,r,c)]+=(h[i][k][j]*lambda[k]);
2091  }
2092  }
2093 
2094  /* now the Jacobian part (take the already computed one) */
2095  SubMatrixFromMatrix(a->nrJ,a->ncJ,J,a->nrJ,a->ncJ,r,c,aData);
2096 
2097  /* The known tangent space part (transposed tangent) */
2098  SubMatrixFromTMatrix(a->m,a->k,phi,a->nrJ+a->nrJ,a->ncJ,r,c,aData);
2099 
2100  /* The last row of the matrix only inclues a block of zeros and 2*lambda*/
2101  for(i=0;i<a->ncJ;i++)
2102  aData[RC2INDEX(r-1,a->ncJ+i,r,c)]=(2.0*lambda[i]);
2103 
2104  /* Improve the solution */
2105  err=NewtonStep(nullSingularValue,y,&dif,&newton);
2106 
2107  if (err)
2108  it=maxIterations;
2109  else
2110  it++;
2111  }
2112  }
2113 
2114  if (converged)
2115  {
2116  if (a->tp!=NULL)
2117  ArrayPi2Pi(a->m,a->tp,x);
2118 
2119  /* If we do not have an estimation for the singular point we
2120  initialize it, oherwise we improve the estimation. */
2121  if (a->bifurcation[bID]->p==NULL)
2122  NEW(a->bifurcation[bID]->p,a->m,double);
2123 
2124  /* Singular point found. Update the information about the bifurcation */
2125  memcpy(a->bifurcation[bID]->p,x,a->m*sizeof(double));
2126  }
2127 
2128  /* release used memory */
2129  DeleteNewton(&newton);
2130  FreeHessianEvaluation(h,a->H);
2131  free(J);
2132  free(y);
2133 
2134  return(it<maxIterations);
2135 }
2136 
2137 unsigned int FindRightNullVector(Tparameters *pr,unsigned int bID,
2138  double **phi,Tatlas *a)
2139 {
2140  double *JTData;
2141  double *K=NULL;
2142  double s,sMin,*p;
2143  unsigned int it,itMin,ck;
2144  unsigned int out;
2145  double *T;
2146  double eps;
2147 
2148  //eps=sqrt(GetParameter(CT_EPSILON,pr)); /* typically 1e-3 */
2149  /* We use a large threshold just to avoid errors. This basically gets
2150  the k+1 vectors with smaller eigenvalues, irrespectively of the
2151  value of these eigenvalues. */
2152  eps=0.01;
2153 
2154  /* Number of columns of the matrix K defined below */
2155  ck=a->k+1;
2156 
2157  /*Use the tangent space at mp1 as an approximation of the tangent space at the
2158  bifurcation*/
2159  T=GetChartTangentSpace(a->charts[a->bifurcation[bID]->mID1]);
2160 
2161  if (a->bifurcation[bID]->p==NULL)
2162  Error("FindRightNullVector needs a singular point");
2163 
2164  /* The (almost) singular point */
2165  p=a->bifurcation[bID]->p;
2166 
2167  /* Space for the Jacobian */
2168  NEW(JTData,a->ncJ*a->nrJ,double);
2169  EvaluateTransposedJacobianInVector(p,a->ncJ,a->nrJ,JTData,&(a->J));
2170  #if (_DEBUG>1)
2171  PrintTMatrix(stdout,"J",a->ncJ,a->nrJ,JTData);
2172  #endif
2173 
2174  /* Now we retrive the k+1 vectors defining the kernel at the singularity.
2175  This is the same to that of \ref InitChart where we compute the
2176  kernel at a non-singular point. The difference is that here we
2177  have k+1 vector (instead of k) and that we have to be more generous with the
2178  criteria to consider eigen value as zero (the input point might not
2179  be exactly singular). In the extreme we can set the 'check' parameter
2180  to FALSE and then we just get the k+1 vectors for the smaller eigenvalues,
2181  irrespectively of their actual value. */
2182  out=FindKernel(a->nrJ,a->ncJ,JTData,ck,TRUE,eps,&K);
2183 
2184  #if (_DEBUG>1)
2185  PrintTMatrix(stdout,"T",a->m,a->k,T);
2186  PrintTMatrix(stdout,"K",a->m,ck,K);
2187  #endif
2188 
2189  /* Look for the vector more different from those in T.
2190  Note that we just get the vector that is more different
2191  for those in T, without any minimal dissimilarity.
2192  We could define a threshold and return only a valid
2193  vector it is different 'enough' from those in T */
2194 
2195  /* Space for the output vector (not used if out!=0) */
2196 
2197  if (out==0)
2198  {
2199  double *Proj;
2200 
2201  NEW((*phi),a->m,double);
2202  NEW(Proj,a->k*ck,double);
2203 
2204  TMatrixMatrixProduct(a->m,a->k,T,ck,K,Proj);
2205 
2206  #if (_DEBUG>1)
2207  PrintMatrix(stdout,"Proj",a->k,ck,Proj);
2208  #endif
2209 
2210  #if (_DEBUG>0)
2211  printf(" Proj(T):[ ");
2212  #endif
2213 
2214  /* Compute the norm of the columns of Proj */
2215  sMin=INF;
2216  itMin=0; /* dummy value */
2217  for(it=0;it<=a->k;it++)
2218  {
2219  s=ColumnSquaredNorm(it,a->k,ck,Proj);
2220  #if (_DEBUG>0)
2221  printf("%g ",s);
2222  #endif
2223  if (s<sMin)
2224  {
2225  sMin=s;
2226  itMin=it;
2227  }
2228  }
2229  #if (_DEBUG>0)
2230  printf("]\n");
2231  #endif
2232  free(Proj);
2233 
2234  /* Get the column of K corresponding to the smaller
2235  projection on T */
2236  GetColumn(itMin,a->m,ck,K,(*phi));
2237  }
2238  else
2239  *phi=NULL;
2240 
2241  /* Release allocated space */
2242  if (K!=NULL)
2243  free(K);
2244 
2245  free(JTData);
2246 
2247  return(out);
2248 }
2249 
2250 boolean Newton2ManifoldPlane(Tparameters *pr,double *point,double *vector,
2251  double *pInit,double *p,Tatlas *a)
2252 {
2253  if (a->n==0)
2254  {
2255  memcpy(p,point,sizeof(double)*a->m);
2256  return(TRUE);
2257  }
2258  else
2259  {
2260  double epsilon,nullSingularValue;
2261  unsigned int j,it,maxIterations;
2262  boolean converged;
2263 
2264  TNewton newton;
2265  double *bData;
2266  double *aData;
2267  double *ptr;
2268 
2269  double errorVal;
2270  int err;
2271 
2272  epsilon=GetParameter(CT_EPSILON,pr);
2273  maxIterations=(unsigned int)GetParameter(CT_MAX_NEWTON_ITERATIONS,pr);
2274  nullSingularValue=epsilon/100;
2275 
2276  if (maxIterations==0)
2277  Error("MAX_NEWTON_ITERATIONS must be larger than 0 to use Newton2ManifoldPlane");
2278 
2279  InitNewton(a->nrJ+1,a->ncJ,&newton);
2280  aData=GetNewtonMatrixBuffer(&newton);
2281  bData=GetNewtonRHBuffer(&newton);
2282 
2283  if (pInit==NULL)
2284  memcpy(p,point,sizeof(double)*a->m);
2285  else
2286  memcpy(p,pInit,sizeof(double)*a->m);
2287 
2288  /* Iterate from this point to a point on the manifold */
2289  it=0;
2290  converged=FALSE;
2291  while((!converged)&&(it<maxIterations))
2292  {
2293  /* Define the residual (right-had side of the system) */
2294  CS_WD_EVALUATE_SIMP_EQUATIONS(pr,p,bData,a->w);
2295 
2296  /* Complete the residual with the equation defining the
2297  plane that might intersect with the other branch */
2298  ptr=&(bData[a->nrJ]);
2299  *ptr=0;
2300  for(j=0;j<a->ncJ;j++) /* ncJ=m */
2301  (*ptr)+=(vector[j]*(p[j]-point[j]));
2302 
2303  errorVal=Norm(a->nrJ+1,bData);
2304 
2305  if (errorVal<epsilon)
2306  converged=TRUE;
2307  else
2308  {
2309  /* Fill in the part of the 'A' corresponding to the Jacobian */
2310  EvaluateJacobianInVector(p,a->nrJ+1,a->ncJ,aData,&(a->J));
2311 
2312  /* Now the part of the 'A' matrix corresponding to the plane
2313  that might intersect with the manifold. */
2314  SetRow(vector,a->nrJ,a->nrJ+1,a->ncJ,aData); /*ncJ==m*/
2315 
2316  /* Define the residual (right-had side of the system) */
2317  CS_WD_EVALUATE_SIMP_EQUATIONS(pr,p,bData,a->w);
2318 
2319  /* Complete the residual with the equation defining the
2320  plane that might intersect with the other branch */
2321  ptr=&(bData[a->nrJ]);
2322  *ptr=0;
2323  for(j=0;j<a->ncJ;j++) /* ncJ=m */
2324  (*ptr)+=(vector[j]*(p[j]-point[j]));
2325 
2326  err=NewtonStep(nullSingularValue,p,&errorVal,&newton);
2327 
2328  if (err)
2329  it=maxIterations;
2330  else
2331  {
2332  if(errorVal<epsilon)
2333  converged=TRUE;
2334  it++;
2335  }
2336  }
2337  }
2338 
2339  if ((converged)&&(a->tp!=NULL))
2340  ArrayPi2Pi(a->m,a->tp,p);
2341 
2342  /* release used memory */
2343  DeleteNewton(&newton);
2344 
2345  return(it<maxIterations);
2346  }
2347 }
2348 
2349 boolean FindPointInOtherBranch(Tparameters *pr,unsigned int bID,
2350  double *phi,double **p,Tatlas *a)
2351 {
2352  double d;
2353  double *p0;
2354  boolean converged;
2355 
2356  if (a->bifurcation[bID]->p==NULL)
2357  Error("FindPointInOtherBranch needs a singular point");
2358 
2359  /* Displace a bit along phi to get a point outside the manifold */
2360  NEW(p0,a->m,double);
2361  SumVectorScale(a->m,a->bifurcation[bID]->p,0.01*a->r,phi,p0);
2362 
2363  /* Search for the intersection of a plane defined by
2364  the new vector of the kernel at the bifurcation found using
2365  \ref FindRightNullVector passing by a point just out
2366  of the variety. This point is also determined using
2367  the new vector of the kernel. */
2368 
2369  NEW((*p),a->m,double);
2370  converged=Newton2ManifoldPlane(pr,p0,phi,NULL,*p,a);
2371 
2372  if (converged)
2373  {
2374  d=DistanceTopology(a->m,a->tp,a->bifurcation[bID]->p,*p);
2375  if (d>a->r)
2376  {
2377  converged=FALSE;
2378  printf(" Converged too far from singularity\n");
2379  }
2380  }
2381  else
2382  {
2383  printf(" Could not jump to the other branch\n");
2384  free(*p);
2385  }
2386 
2387  free(p0);
2388 
2389  return(converged);
2390 }
2391 
2392 void DefineChartsAtBifurcation(Tparameters *pr,unsigned int bID,
2393  double *v,TAtlasStatistics *ast,Tatlas *a)
2394 {
2395  double c;
2396 
2397  if (a->bifurcation[bID]->p==NULL)
2398  Error("DefineChartsAtBifurcation needs a singular point");
2399 
2400  /* 3.1.- We define a new chart on the singularity */
2401  if (a->currentChart==a->maxCharts)
2402  MEM_DUP(a->charts,a->maxCharts,Tchart *);
2403 
2404  NEW(a->charts[a->currentChart],1,Tchart);
2405 
2406  if (InitChartWithTangent(pr,FALSE,a->ambient,a->tp,a->m,a->k,
2407  a->bifurcation[bID]->p,
2409  a->e,a->ce, a->r,
2410  &(a->J),a->w,a->charts[a->currentChart])>1)
2411  Warning("Can not create a chart on the singular point");
2412  else
2413  {
2414  a->currentChart++;
2416 
2417  /* 3.2.- Define a new chart in the other branch */
2418  if (a->currentChart==a->maxCharts)
2419  MEM_DUP(a->charts,a->maxCharts,Tchart *);
2420 
2421  NEW(a->charts[a->currentChart],1,Tchart);
2422 
2423  if (InitSingularChart(pr,FALSE,a->ambient,a->tp,a->m,a->k,v,a->e,a->ce,a->r,
2424  &(a->J),a->w,a->charts[a->currentChart])>1)
2425  Warning("Can not create a chart on the other branch");
2426  else
2427  {
2429  if (c>(1-a->ce))
2431 
2432  printf(" New Bifurcation Chart %u (%f)\n",a->currentChart,c);
2433 
2434  a->currentChart++;
2436 
2437  /* 3.3.- Link the two charts together */
2439  a->currentChart-1,a->charts[a->currentChart-1]);
2440  }
2441  }
2442 }
2443 
2444 void ProcessBifurcation(Tparameters *pr,unsigned int bID,TAtlasStatistics *ast,Tatlas *a)
2445 {
2446  if ((bID>=a->npBifurcations)&&(bID<a->nBifurcations))
2447  {
2448  NewBifurcation(ast);
2449  /*
2450  Now we have to detect a point in the "other" branch of the manifold,
2451  start a chart there (IntChart) and search for neighbours
2452  (DetectChartNeighbours).
2453  */
2454  double *phi,*v;
2455 
2456  printf(" Searching for bifurcation\n");
2457 
2458  /* 1.- Determine the bifurcation point. This is an approximation since
2459  all our processes are epsilon accurate. The result is that the
2460  singular point is actually close to singular but not singular */
2461 
2462  if (FindSingularPoint(pr,bID,a))
2463  {
2464  /* 2.- Find the right null vector (the vector for the smallest
2465  eigenvalue (it sould be zero but is not due to numerical
2466  problems) */
2467  if (FindRightNullVector(pr,bID,&phi,a)==0)
2468  {
2469  /* 3.- Find a point in the other branch */
2470  if (FindPointInOtherBranch(pr,bID,phi,&v,a))
2471  {
2472  /* Define on chart at the current branch of the singularity,
2473  another at the new branch and link then.*/
2474  DefineChartsAtBifurcation(pr,bID,v,ast,a);
2475 
2476  /* Release intermediate variables */
2477  free(v);
2478  }
2479  else
2480  NewNoJumpBranch(ast);
2481 
2482  /*Release other intermediate variables*/
2483  free(phi);
2484  }
2485  else
2486  NewNoSingularEnough(ast);
2487  }
2488  else
2490  }
2491 }
2492 
2493 void LoadBifurcations(FILE *f,Tatlas *a)
2494 {
2495  unsigned int i,j,p;
2496 
2497  fscanf(f,"%u",&(a->mBifurcations));
2498  fscanf(f,"%u",&(a->nBifurcations));
2499  fscanf(f,"%u",&(a->npBifurcations));
2500 
2502 
2503 
2504  for(i=0;i<a->nBifurcations;i++)
2505  {
2506  NEW(a->bifurcation[i],1,Tbifurcation);
2507  fscanf(f,"%u",&(a->bifurcation[i]->mID1));
2508  fscanf(f,"%u",&(a->bifurcation[i]->d1));
2509  fscanf(f,"%u",&(a->bifurcation[i]->mID2));
2510  fscanf(f,"%u",&(a->bifurcation[i]->d2));
2511  fscanf(f,"%u",&p);
2512  if (p!=0)
2513  {
2514  NEW(a->bifurcation[i]->p,a->m,double);
2515  for(j=0;j<a->m;j++)
2516  fscanf(f,"%lf",&(a->bifurcation[i]->p[j]));
2517  }
2518  else
2519  a->bifurcation[i]->p=NULL;
2520  }
2521 }
2522 
2523 void SaveBifurcations(FILE *f,Tatlas *a)
2524 {
2525  unsigned int i,j;
2526 
2527  fprintf(f,"%u\n",a->mBifurcations);
2528  fprintf(f,"%u\n",a->nBifurcations);
2529  fprintf(f,"%u\n",a->npBifurcations);
2530 
2531  for(i=0;i<a->nBifurcations;i++)
2532  {
2533  fprintf(f,"%u %u %u %u %u\n",
2534  a->bifurcation[i]->mID1,a->bifurcation[i]->d1,
2535  a->bifurcation[i]->mID2,a->bifurcation[i]->d2,
2536  (a->bifurcation[i]->p!=NULL));
2537  if (a->bifurcation[i]->p!=NULL)
2538  {
2539  for(j=0;j<a->m;j++)
2540  fprintf(f,"%.12f ",a->bifurcation[i]->p[j]);
2541  fprintf(f,"\n");
2542  }
2543  }
2544 }
2545 
2547  unsigned int xID,unsigned int yID,unsigned int zID,Tatlas *a)
2548 {
2549  unsigned int i;
2550  double *p;
2551  double x[2],y[2],z[2];
2552  double *o;
2553  Tchart *m;
2554  Tcolor color;
2555 
2556  NewColor(1,0,0,&color); /* red */
2557  StartNew3dObject(&color,p3d);
2558 
2559  for(i=0;i<a->nBifurcations;i++)
2560  {
2561  m=a->charts[a->bifurcation[i]->mID1];
2562  p=GetChartCenter(m);
2563  CS_WD_REGENERATE_ORIGINAL_POINT(pr,p,&o,a->w);
2564  x[0]=o[xID];
2565  y[0]=o[yID];
2566  z[0]=o[zID];
2567  free(o);
2568 
2569  m=a->charts[a->bifurcation[i]->mID2];
2570  p=GetChartCenter(m);
2571  CS_WD_REGENERATE_ORIGINAL_POINT(pr,p,&o,a->w);
2572  x[1]=o[xID];
2573  y[1]=o[yID];
2574  z[1]=o[zID];
2575  free(o);
2576 
2577  PlotVect3d(2,x,y,z,p3d);
2578  }
2579  Close3dObject(p3d);
2580  DeleteColor(&color);
2581 }
2582 
2584 {
2585  unsigned int i;
2586 
2587  for(i=0;i<a->nBifurcations;i++)
2588  {
2589  if (a->bifurcation[i]->p!=NULL)
2590  free(a->bifurcation[i]->p);
2591  free(a->bifurcation[i]);
2592  }
2593  free(a->bifurcation);
2594 
2595  a->mBifurcations=0;
2596  a->nBifurcations=0;
2597  a->npBifurcations=0;
2598 }
2599 
2600 void InitAtlasHeapElement(unsigned int mID,double c,double beta,TAtlasHeapElement *he)
2601 {
2602  he->chartID=mID;
2603  he->cost=c;
2604  if (beta<1)
2605  Error("The heap element penalty factor must be >1");
2606  he->beta=beta;
2607  he->nPenalized=1;
2608 }
2609 
2610 void CopyAtlasHeapElement(void *he1,void *he2)
2611 {
2612  ((TAtlasHeapElement *)he1)->chartID=((TAtlasHeapElement *)he2)->chartID;
2613  ((TAtlasHeapElement *)he1)->cost=((TAtlasHeapElement *)he2)->cost;
2614  ((TAtlasHeapElement *)he1)->beta=((TAtlasHeapElement *)he2)->beta;
2615  ((TAtlasHeapElement *)he1)->nPenalized=((TAtlasHeapElement *)he2)->nPenalized;
2616 }
2617 
2619 {
2620  return(he->chartID);
2621 }
2622 
2624 {
2625  return(he->cost);
2626 }
2627 
2628 boolean LessThanAtlasHeapElement(void *he1,void *he2,void *userData)
2629 {
2630  double t,b1,b2,c1,c2;
2631 
2632  t=((TAtlasHeapElement *)he1)->nPenalized;
2633  b1=((TAtlasHeapElement *)he1)->beta;
2634  c1=pow(b1,t-1)*((TAtlasHeapElement *)he1)->cost;
2635 
2636  t=((TAtlasHeapElement *)he2)->nPenalized;
2637  b2=((TAtlasHeapElement *)he2)->beta;
2638  c2=pow(b2,t-1)*((TAtlasHeapElement *)he2)->cost;
2639 
2640  return(c1<=c2);
2641 }
2642 
2644 {
2645  he->nPenalized++;
2646 }
2647 
2649 {
2650 }
2651 
2653 {
2654  boolean hasS;
2655  unsigned int i;
2656 
2657  if (CS_WD_GET_SIMP_TOPOLOGY(pr,&(a->tp),a->w)!=a->m)
2658  Error("Missmatch number of variables in SetAtlasTopology");
2659 
2660  /* Search for a non-real variable */
2661  hasS=FALSE;
2662  i=0;
2663  while((i<a->m)&&(!hasS))
2664  {
2665  hasS=(a->tp[i]==TOPOLOGY_S);
2666  i++;
2667  }
2668  if (!hasS)
2669  {
2670  /* if all variables are real no need to consider topology */
2671  free(a->tp);
2672  a->tp=NULL;
2673  }
2674 }
2675 
2676 void InitAtlas(Tparameters *pr,boolean parallel,boolean simpleChart,
2677  unsigned int k,double e,double ce, double r,TAtlasBase *w,
2678  Tatlas *a)
2679 {
2680  a->w=w;
2681 
2683  a->currentChart=0;
2684  a->npCharts=0;
2685 
2686  NEW(a->charts,a->maxCharts,Tchart *);
2687 
2688  NEW(a->ambient,1,Tbox);
2689 
2690  /* Since atlas are defined on the simplified system we get the
2691  corresponding Jacobian. */
2692  CS_WD_GET_SIMP_JACOBIAN(pr,&(a->J),a->w);
2693  GetJacobianSize(&(a->nrJ),&(a->ncJ),&(a->J));
2695 
2696  /* differ the Hessian computation */
2697  a->H=NULL;
2698 
2699  a->k=k;
2700  a->m=a->ncJ;
2701  a->n=a->m-a->k;
2702  a->r=r;
2703  a->e=e;
2704  a->ce=ce;
2705 
2707  a->nBifurcations=0;
2708  a->npBifurcations=0;
2710 
2711  a->simpleChart=simpleChart;
2712 
2713  SetAtlasTopology(pr,a);
2714 
2715  /* The openMP parallel execution is only possible if OpenMP is active and
2716  it is only worth if the problem is large (in number of variables or
2717  dimension of the solution set). Moreover, collision detection
2718  is typically not re-entrant. Do not use parallel execution in
2719  this case (if operating on a world instead than on a cuik file). */
2720 
2721  a->parallel=FALSE; /* The default is not to execute in parallel */
2722 
2723  #ifdef _OPENMP
2724  if (parallel)
2725  {
2726  a->nCores=omp_get_max_threads();
2727  /* even if having many cores ans OpenMP we only execute in parallel
2728  large problems. */
2729  a->parallel=((a->nCores>1)&&((a->m>25)||(a->k>2)));
2730  }
2731  #endif
2732  //a->parallel=FALSE;
2733  if (!a->parallel)
2734  a->nCores=1;
2735 
2736  fprintf(stderr,"Number of computing cores (atlas) : %u\n",a->nCores);
2737 
2738  /* When using world, collisions are considered (if defined) */
2739  CS_WD_INIT_CD(pr,a->nCores,a->w);
2740 }
2741 
2742 boolean InitAtlasFromPoint(Tparameters *pr,boolean parallel,boolean simpleChart,double *p,
2743  TAtlasBase *w,Tatlas *a)
2744 {
2745  unsigned int chartCode;
2746  boolean initOK;
2747  double *ps,*pWithDummies;
2748  unsigned int k;
2749  double e,ce,r;
2750 
2751  k=(unsigned int)GetParameter(CT_N_DOF,pr);
2752  r=GetParameter(CT_R,pr);
2753  e=GetParameter(CT_E,pr);
2754  ce=GetParameter(CT_CE,pr);
2755 
2756  InitAtlas(pr,parallel,simpleChart,k,e,ce,r,w,a);
2757 
2758  /* We have to recover the full solution point from the values of the system
2759  variables in sample 'p' and then define the a point in the simplified system
2760  that is where the atlas is defined.
2761  Note that the actual dimension of the ambient space is that of the number
2762  of variables in the simplified system. Moreover, note that both the simplified
2763  and the original system describe the same manifold (k is the same is the to of
2764  them)
2765  */
2766  CS_WD_REGENERATE_SOLUTION_POINT(pr,p,&pWithDummies,a->w);
2767 
2768  if (CS_WD_ORIGINAL_IN_COLLISION(pr,pWithDummies,NULL,a->w))
2769  Error("Starting point for the atlas is in collision");
2770 
2771  a->m=CS_WD_GENERATE_SIMPLIFIED_POINT(pr,pWithDummies,&ps,a->w);
2772  free(pWithDummies);
2773 
2774  if (a->k==0)
2775  {
2776  double epsilon,*JT;
2777 
2778  /* We have to determine the dof assuming that the given point is regular */
2779  Warning("N_DOF parameter set to 0. Assuming that the initial point is regular");
2780 
2781  epsilon=GetParameter(CT_EPSILON,pr);
2782  NEW(JT,a->ncJ*a->nrJ,double);
2783 
2784  EvaluateTransposedJacobianInVector(ps,a->ncJ,a->nrJ,JT,&(a->J));
2785 
2786  a->k=a->ncJ-FindRank(epsilon,a->nrJ,a->ncJ,JT);
2787 
2788  free(JT);
2789  fprintf(stderr,"Setting N_DOF=%u\n\n",a->k);
2790 
2791  /* Change the parameter !! */
2792  ChangeParameter(CT_N_DOF,(double)a->k,pr);
2793  }
2794 
2795  NEW(a->charts[0],1,Tchart);
2796  chartCode=InitChart(pr,a->simpleChart,a->ambient,a->tp,a->m,a->k,ps,a->e,a->ce,a->r,
2797  &(a->J),a->w,a->charts[0]);
2798 
2799  switch (chartCode)
2800  {
2801  case 1:
2802  Error("The expected mobility is too low (increase N_DOF)");
2803  break;
2804  case 2:
2805  Error("The expected mobility is too high (decrease N_DOF)");
2806  break;
2807  case 3:
2808  Error("There is a numerical error when computing the tangent space");
2809  break;
2810  case 4:
2811  Error("The initial point is not on the manifold");
2812  break;
2813  }
2814 
2815  initOK=(chartCode==0);
2816 
2817  free(ps);
2818 
2819  if (initOK)
2820  {
2821  if (FrontierChart(a->charts[0]))
2822  Error("The initial chart is out of the ambient space domain");
2823 
2824  a->currentChart=1;
2825  a->npCharts=1; /* No need to post-process the first chart. */
2826  #if (USE_ATLAS_TREE)
2827  InitBTree(0,a->charts[0],a->ambient,a->tp,&(a->tree));
2828  #endif
2829  }
2830  else
2831  free(a->charts[0]);
2832 
2833  return(initOK);
2834 }
2835 
2836 unsigned int AddChart2Atlas(Tparameters *pr,double *ps,unsigned int parentID,boolean *singular,Tatlas *a)
2837 {
2838  boolean initOK;
2839  unsigned int mID;
2840 
2841  *singular=FALSE;
2842 
2843  /* Generate the new chart */
2844  if (a->currentChart==a->maxCharts)
2845  MEM_DUP(a->charts,a->maxCharts,Tchart *);
2846 
2847  NEW(a->charts[a->currentChart],1,Tchart);
2848 
2849  initOK=(InitChart(pr,a->simpleChart,a->ambient,a->tp,a->m,a->k,ps,a->e,a->ce, a->r,
2850  &(a->J),a->w,a->charts[a->currentChart])==0);
2851  if (initOK)
2852  {
2853  #if (ATLAS_VERBOSE)
2854  printf(" New Chart %u\n",a->currentChart);
2855  #endif
2856 
2857  mID=a->currentChart;
2858  a->currentChart++;
2859  PostProcessNewCharts(pr,TRUE,parentID,NULL,a);
2860  }
2861  else
2862  {
2863  mID=NO_UINT;
2864  free(a->charts[a->currentChart]);
2865  }
2866 
2867  return(mID);
2868 }
2869 
2870 unsigned int AddTrustedChart2Atlas(Tparameters *pr,double *ps,unsigned int parentID,boolean *singular,Tatlas *a)
2871 {
2872  boolean initOK;
2873  unsigned int mID;
2874  unsigned int db;
2875 
2876  *singular=FALSE;
2877 
2878  /* Generate the new chart */
2879  if (a->currentChart==a->maxCharts)
2880  MEM_DUP(a->charts,a->maxCharts,Tchart *);
2881 
2882  NEW(a->charts[a->currentChart],1,Tchart);
2883 
2884  initOK=(InitTrustedChart(pr,a->simpleChart,a->ambient,a->tp,a->m,a->k,ps,a->e,a->ce, a->r,
2885  &(a->J),a->w,a->charts[a->currentChart])==0);
2886 
2887  if (initOK)
2888  {
2889  #if (ATLAS_VERBOSE)
2890  printf(" New Chart %u (%p)\n",a->currentChart,a->charts[a->currentChart]);
2891  #endif
2892 
2893  mID=a->currentChart;
2894  a->currentChart++;
2895 
2896  if (a->n>0)
2897  {
2898  /* and now detect (and process) bifurcation from parent to child, even
2899  if they are not neighbours yet. */
2900  db=(unsigned int)GetParameter(CT_DETECT_BIFURCATIONS,pr);
2901 
2902  if ((db>0)&&(parentID!=NO_UINT))
2903  *singular=DetectBifurcation(pr,parentID,mID,a);
2904  }
2905  /* detect neighbours and deal with the bifurcations if any */
2906  /* Intersect with the rest of charts (but without concern about singularities
2907  and without enforcing intersection with parent). */
2908  PostProcessNewCharts(pr,FALSE,NO_UINT,NULL,a);
2909  }
2910  else
2911  {
2912  mID=NO_UINT;
2913  free(a->charts[a->currentChart]);
2914  }
2915 
2916  return(mID);
2917 }
2918 
2919 void BuildAtlasFromPoint(Tparameters *pr,double *p,boolean simpleChart,
2920  TAtlasBase *w,Tatlas *a)
2921 {
2922  Theap h;
2923  TAtlasHeapElement he,he2;
2924  unsigned int mID;
2925  double *t;
2926  TAtlasStatistics *st;
2927  unsigned int cm,cmPrev;
2928  double d;
2929  unsigned int nv,k;
2930  double beta;
2931  unsigned int maxCharts;
2932  /* just in case parallel=TRUE */
2933  unsigned int i,*cornerID,*chartID,maxInProcess,ncInProcess;
2934  double **tv;
2935  Tchart **newCharts;
2936  TAtlasHeapElement *heInProcess;
2937 
2938  /* Init the atlas trying to exploit parallelism, if available and worth */
2939  if (!InitAtlasFromPoint(pr,TRUE,simpleChart,p,w,a))
2940  Error("Can not start atlas from the given point (BuildAtlasFromPoint)");
2941 
2942  k=(unsigned int)GetParameter(CT_N_DOF,pr);
2943 
2944  maxCharts=(unsigned int)GetParameter(CT_MAX_CHARTS,pr);
2945 
2946  InitHeap(sizeof(TAtlasHeapElement),
2951 
2952  beta=GetParameter(CT_ATLASGBF_BETA,pr);
2953  /* one-dim solution sets (k==1) -> process charts in sequence */
2954  InitAtlasHeapElement(0,(k==1?1:0),beta,&he);
2955  AddElement2Heap(NO_UINT,(void *)(&he),&h);
2956 
2957  if (a->parallel)
2958  {
2959  fprintf(stderr,"Executing in %u parallel threads\n",a->nCores);
2960  /* some charts are difficult to process it's better to have more
2961  charts in queue... let the other threads to process the simple
2962  ones */
2963  maxInProcess=(unsigned int)(1.5*a->nCores);
2964  NEW(chartID,maxInProcess,unsigned int);
2965  NEW(cornerID,maxInProcess,unsigned int);
2966  NEW(tv,maxInProcess,double *);
2967  for(i=0;i<maxInProcess;i++)
2968  NEW(tv[i],a->k,double);
2969  NEW(heInProcess,maxInProcess,TAtlasHeapElement);
2970  NEW(newCharts,maxInProcess,Tchart*);
2971  st=NULL;
2972  }
2973  else
2974  {
2975  NEW(t,a->k,double);
2976  NEW(st,1,TAtlasStatistics);
2977  InitAtlasStatistics(st);
2978  }
2979 
2980  while((!HeapEmpty(&h))&&(a->currentChart<maxCharts))
2981  {
2982  cmPrev=a->currentChart;
2983 
2984  if (!a->parallel)
2985  {
2986  ExtractMinElement((void *)(&he),&h);
2987  mID=GetAtlasHeapElementID(&he);
2988 
2989  //if (ExpandibleChart(a->charts[mID]))
2990  if (OpenChart(a->charts[mID]))
2991  {
2992  printf("Extending chart %u\n",mID);
2993 
2994  NewBoundaryAttempt(st);
2995 
2996  /* Treat one external corner at a time */
2998  {
2999  /* This generates a new chart on the direction of 't', if possible. */
3000  ExtendAtlasFromPoint(pr,mID,t,st,a);
3001 
3002  /* Just in case the selected vertex is not actually used, we eliminate it
3003  from the list of expandible vetexes. In general this has no effect since
3004  the extension already eliminated the vertex (and created new vertexes) */
3005  WrongCorner(nv,a->charts[mID]);
3006  }
3007  else
3008  NewNotInBoundary(st);
3009 
3010  /* Just in case the chart still has external corners (still open) */
3011  AddElement2Heap(NO_UINT,(void *)(&he),&h);
3012  }
3013  }
3014  else
3015  {
3016  /* Select several open charts, and a corner of each chart */
3017  ncInProcess=0;
3018  while((!HeapEmpty(&h))&&(ncInProcess<maxInProcess))
3019  {
3020  ExtractMinElement((void *)(&(heInProcess[ncInProcess])),&h);
3021  chartID[ncInProcess]=GetAtlasHeapElementID(&(heInProcess[ncInProcess]));
3022  if (OpenChart(a->charts[chartID[ncInProcess]]))
3023  ncInProcess++;
3024  }
3025 
3026  #pragma omp parallel for private(i) schedule(dynamic)
3027  for(i=0;i<ncInProcess;i++)
3028  {
3029  if (BoundaryPointFromExternalCorner(RANDOMNESS,&(cornerID[i]),
3030  tv[i],a->charts[chartID[i]]))
3031  {
3032  printf("Extending chart %u (%u)\n",chartID[i],i);
3033  newCharts[i]=NULL;
3034  NewChartFromPoint(pr,chartID[i],tv[i],&(newCharts[i]),a);
3035  }
3036  /* We selected ncInProcess *different* charts, we can do the
3037  'WrongCorner' in parallel too */
3038  WrongCorner(cornerID[i],a->charts[chartID[i]]);
3039  }
3040 
3041  /* The post process of the generated charts is serialized */
3042  /* Add the charts to the atlas one at a time. */
3043  for(i=0;i<ncInProcess;i++)
3044  {
3045  if (newCharts[i]!=NULL)
3046  {
3047  if (a->currentChart==a->maxCharts)
3048  MEM_DUP(a->charts,a->maxCharts,Tchart *);
3049 
3050  /* We directly re-use the charts to safe one copy. */
3051  a->charts[a->currentChart]=newCharts[i];
3052  a->currentChart++;
3053 
3054  /* Now detect neighbours and the possible bifurcations */
3055  PostProcessNewCharts(pr,TRUE,chartID[i],st,a);
3056  }
3057  }
3058 
3059  /* Add the charts just processed to the heap, just in case they are still open */
3060  for(i=0;i<ncInProcess;i++)
3061  AddElement2Heap(NO_UINT,(void *)(&(heInProcess[i])),&h);
3062  }
3063 
3064  /* The above can generate several charts (when not using OpenMP or due to bifurcations) */
3065  /* Now we add them to the heap */
3066  for(cm=cmPrev;cm<a->currentChart;cm++)
3067  {
3068  /* Now add the new chart to the heap */
3069  if (k==1) /* one-dim solution sets -> process charts in sequence */
3070  d=1/(double)(cm+1);
3071  else
3072  {
3073  /* when executing in parallel we assign the expansion priority at random
3074  to minimize the prob. of expanding close charts in paralle. This produces
3075  more charts than those really necessary. */
3076  if (a->parallel)
3077  d=randomDouble();
3078  else
3079  d=DistanceTopology(a->m,a->tp,p,GetChartCenter(a->charts[cm]));
3080  }
3081  InitAtlasHeapElement(cm,d,beta,&he2);
3082  AddElement2Heap(NO_UINT,(void *)(&he2),&h);
3083  }
3084  }
3085 
3086  if (a->parallel)
3087  {
3088  free(chartID);
3089  free(cornerID);
3090  for(i=0;i<a->nCores;i++)
3091  free(tv[i]);
3092  free(tv);
3093  free(newCharts);
3094  free(heInProcess);
3095  }
3096  else
3097  {
3098  PrintAtlasStatistics(pr,st);
3099  free(st);
3100  free(t);
3101  }
3102 
3103  DeleteHeap(&h);
3104 }
3105 
3106 boolean MinimizeOnAtlas(Tparameters *pr,char *fname,double *p,TAtlasBase *w,
3107  double (*costF)(Tparameters*,boolean,double*,void*),
3108  void *costData,
3109  Tatlas *a)
3110 {
3111  unsigned int i,j,k,l,nv,nvs,nt,mt,pnc;
3112  TMinTrace **t;
3113  boolean *systemVars,done;
3114  double *o,*currentPoint;
3115  double cost,cost1;
3116  double *g,*newPoint,*d,ng;
3117  double delta,epsilon;
3118  Tchart *currentChart;
3119  unsigned int db;
3120  boolean sing,ok;
3121 
3122  db=(unsigned int)GetParameter(CT_DETECT_BIFURCATIONS,pr);
3123 
3124  if (db>1)
3126 
3127  delta=GetParameter(CT_DELTA,pr);
3128  epsilon=GetParameter(CT_EPSILON,pr);
3129 
3130  /* Init the atlas */
3131  if (!InitAtlasFromPoint(pr,FALSE,FALSE,p,w,a))
3132  Error("Can not start atlas from the given point (MinimizeOnAtlas)");
3133 
3134  k=(unsigned int)GetParameter(CT_N_DOF,pr);
3135 
3136  /* Get the system varibles */
3137  nv=CS_WD_GET_SYSTEM_VARS(&systemVars,a->w);
3138  nvs=0;
3139  for(i=0;i<nv;i++)
3140  {
3141  if (systemVars[i])
3142  nvs++;
3143  }
3144 
3145  /* Init the set of traces */
3146  mt=5; /* In general only one trace will be followed */
3147  NEW(t,mt,TMinTrace*);
3148  nt=1;
3149  /* Init the first trace */
3150  NEW(t[0],1,TMinTrace);
3151  t[0]->st=0;
3152  t[0]->nc=0; /* Start the minimization from the first chart. */
3153  InitSamples(&(t[0]->ms),&(t[0]->ns),&(t[0]->path));
3154 
3155  NEW(g,k,double); /* gradient (in tangent space) */
3156  NEW(d,k,double); /* displacement */
3157  NEW(newPoint,a->m,double); /* new temptative point */
3158 
3159  /* Start by tracing the path from the given point */
3160  l=0;
3161 
3162  /* Add the first point to the path */
3163  currentPoint=GetChartCenter(a->charts[t[l]->nc]);
3164  CS_WD_REGENERATE_ORIGINAL_POINT(pr,currentPoint,&o,a->w);
3165  AddSample2Samples(nv,o,nvs,systemVars,&(t[l]->ms),&(t[l]->ns),&(t[l]->path));
3166  free(o);
3167 
3168  /* Compute the initial cost (debug purposes only) */
3169  cost=costF(pr,TRUE,currentPoint,costData);
3170  fprintf(stderr," Initial cost: %g\n",cost);
3171 
3172  ok=TRUE;
3173 
3174  while(l<nt)
3175  {
3176  done=FALSE;
3177 
3178  while (!done)
3179  {
3180  /* Point from where to continue the minimization */
3181  currentChart=a->charts[t[l]->nc];
3182  currentPoint=GetChartCenter(currentChart);
3183 
3184  /* Numerical evaluation of the gradient */
3185  cost=costF(pr,TRUE,currentPoint,costData);
3186 
3187  for(i=0;i<k;i++)
3188  d[i]=0;
3189 
3190  for(i=0;i<k;i++)
3191  {
3192  d[i]=100*epsilon;
3193  if (Chart2Manifold(pr,&(a->J),d,NULL,currentPoint,newPoint,currentChart)<INF)
3194  {
3195  cost1=costF(pr,TRUE,newPoint,costData);
3196  g[i]=-(cost1-cost)/(100*epsilon);
3197  }
3198  else
3199  Error("Can not converge to the manifold in MinimizeOnAtlas");
3200  d[i]=0.0;
3201  }
3202 
3203  ng=Norm(k,g);
3204 
3205  fprintf(stderr," Branch %u step %u: point: [%g %g ...]\n",l,t[l]->st,currentPoint[0],currentPoint[1]);
3206  fprintf(stderr," cost: %g\n",cost);
3207  fprintf(stderr," norm gradient: %g\n",ng);
3208 
3209  if (t[l]->st>100) // (((l==0)&&(t[l]->st==48))||((l==1)&&(t[l]->st==96)))
3210  done=TRUE;
3211  else
3212  {
3213  if (ng>delta)
3214  ScaleVector(delta/ng,k,g);
3215 
3216  fprintf(stderr," norm disp.: %g\n",Norm(k,g));
3217 
3218  if (Chart2Manifold(pr,&(a->J),g,NULL,currentPoint,newPoint,currentChart)==INF)
3219  {
3220  fprintf(stderr," Error in convergence\n");
3221  done=TRUE;
3222  }
3223  else
3224  {
3225  pnc=a->currentChart;
3226  AddChart2Atlas(pr,newPoint,t[l]->nc,&sing,a);
3227 
3228  ok&=(!sing);
3229 
3230  if (a->currentChart>pnc+1)
3231  {
3232  fprintf(stderr," ******* BIFURCATION *******\n");
3233  /* We stepped over a singularity -> bifurcate the path */
3234  /* duplicate the path */
3235  if (nt==mt)
3236  { MEM_DUP(t,mt,TMinTrace*); }
3237 
3238  NEW(t[nt],1,TMinTrace);
3239 
3240  InitSamples(&(t[nt]->ms),&(t[nt]->ns),&(t[nt]->path));
3241  for(j=0;j<t[l]->ns;j++)
3242  AddSample2Samples(nvs,t[l]->path[j],nvs,NULL,
3243  &(t[nt]->ms),&(t[nt]->ns),&(t[nt]->path));
3244  t[nt]->st=t[l]->st;
3245 
3246  /* Now extend the current path */
3247  currentPoint=GetChartCenter(a->charts[pnc+1]);
3248  CS_WD_REGENERATE_ORIGINAL_POINT(pr,currentPoint,&o,a->w);
3249  AddSample2Samples(nv,o,nvs,systemVars,&(t[l]->ms),&(t[l]->ns),&(t[l]->path));
3250  free(o);
3251  currentPoint=GetChartCenter(a->charts[pnc+0]);
3252  CS_WD_REGENERATE_ORIGINAL_POINT(pr,currentPoint,&o,a->w);
3253  AddSample2Samples(nv,o,nvs,systemVars,&(t[l]->ms),&(t[l]->ns),&(t[l]->path));
3254  free(o);
3255  t[l]->nc=pnc+0;
3256 
3257  /* And extend the new path */
3258  currentPoint=GetChartCenter(a->charts[pnc+1]);
3259  CS_WD_REGENERATE_ORIGINAL_POINT(pr,currentPoint,&o,a->w);
3260  AddSample2Samples(nv,o,nvs,systemVars,&(t[nt]->ms),&(t[nt]->ns),&(t[nt]->path));
3261  free(o);
3262  currentPoint=GetChartCenter(a->charts[pnc+2]);
3263  CS_WD_REGENERATE_ORIGINAL_POINT(pr,currentPoint,&o,a->w);
3264  AddSample2Samples(nv,o,nvs,systemVars,&(t[nt]->ms),&(t[nt]->ns),&(t[nt]->path));
3265  free(o);
3266  t[nt]->nc=pnc+2;
3267 
3268  /* We have a new path already stareted */
3269  nt++;
3270  }
3271  else
3272  {
3273  /* Add the first point to the path */
3274  currentPoint=GetChartCenter(a->charts[pnc]);
3275  CS_WD_REGENERATE_ORIGINAL_POINT(pr,currentPoint,&o,a->w);
3276  AddSample2Samples(nv,o,nvs,systemVars,&(t[l]->ms),&(t[l]->ns),&(t[l]->path));
3277  free(o);
3278 
3279  t[l]->nc=pnc;
3280  }
3281  }
3282  }
3283  t[l]->st++;
3284  }
3285 
3286  /* Continue next pending minimization path */
3287  l++;
3288  }
3289 
3290  free(d);
3291  free(g);
3292  free(newPoint);
3293 
3294  if (!ok)
3295  Warning("A singularity was detected during the minimization but it could not be determined if it was a bifurcation. Try a smaller epsilon or a larger delta?");
3296 
3297  /* Save the stored paths */
3298  if (nt==1)
3299  SaveSamples(fname,FALSE,nvs,t[0]->ns,t[0]->path);
3300  else
3301  {
3302  for(l=0;l<nt;l++)
3303  SaveSamplesN(fname,FALSE,l,nvs,t[l]->ns,t[l]->path);
3304  }
3305 
3306  free(systemVars);
3307 
3308  return(ok);
3309 }
3310 
3312 {
3313  return(a->r);
3314 }
3315 
3317 {
3318  return(a->e);
3319 }
3320 
3322 {
3323  return(a->ce);
3324 }
3325 
3327 {
3328  return(a->w);
3329 }
3330 
3331 unsigned int GetAtlasAmbientDim(Tatlas *a)
3332 {
3333  return(a->m);
3334 }
3335 
3336 unsigned int GetAtlasManifoldDim(Tatlas *a)
3337 {
3338  return(a->k);
3339 }
3340 
3341 boolean AtlasAStar(Tparameters *pr,double *p,double *time,
3342  double *pl,unsigned int *ns,double ***path,Tatlas *a)
3343 {
3344  Theap h;
3345  unsigned int i;
3346  TAtlasHeapElement he,he2,*hePtr;
3347  unsigned int *chartID;
3348  unsigned int mID;
3349  TAStarInfo *info,*infoID,*infoParent;
3350  /* The 'pred' must be stored apart to re-use the path reconstruction function */
3351  unsigned int *pred;
3352  boolean found;
3353  double *t;
3354  double epsilon;
3355  unsigned int nn,id;
3356  double c,dst;
3357  double *pID,*pmID;
3358  double *ps,*pWithDummies;
3359  double er;
3360  unsigned int nv;
3361  boolean *systemVars;
3362  unsigned int cm,cmPrev,mmPrev;
3363  TAtlasStatistics *st;
3364  unsigned int nc;
3365  unsigned int it;
3366  Tstatistics stime;
3367  double beta;
3368  boolean collision=FALSE;
3369  double maxTime;
3370  unsigned int maxCharts;
3371  unsigned int nce;
3372  unsigned int *vs; /* set of vertex indices (only used in parallel execution). */
3373  double **ts; /* set of vertex coordinates (only used in parallel execution). */
3374  Tchart **newCharts; /* set of generated charts (only used in parallel execution). */
3375 
3376  if (a->currentChart!=1)
3377  Error("AtlasAStar assumes an initial atlas with only one local chart");
3378 
3379  epsilon=GetParameter(CT_EPSILON,pr);
3380  beta=GetParameter(CT_ATLASGBF_BETA,pr);
3381  maxTime=GetParameter(CT_MAX_PLANNING_TIME,pr);
3382  maxCharts=(unsigned int)GetParameter(CT_MAX_CHARTS,pr);
3383 
3384  nv=CS_WD_GET_SYSTEM_VARS(&systemVars,a->w);
3385  CS_WD_REGENERATE_SOLUTION_POINT(pr,p,&pWithDummies,a->w);
3386  if (CS_WD_GENERATE_SIMPLIFIED_POINT(pr,pWithDummies,&ps,a->w)!=a->m)
3387  Error("Dimension missmatch in AtlasAStar");
3388  free(pWithDummies);
3389  if (a->n==0)
3390  er=0.0;
3391  else
3392  er=CS_WD_ERROR_IN_SIMP_EQUATIONS(pr,ps,a->w);
3393  if (er>epsilon)
3394  Error("Target point for the AtlasAStar is not on the manifold");
3395 
3396  collision=CS_WD_ORIGINAL_IN_COLLISION(pr,pWithDummies,NULL,a->w);
3397  if (collision)
3398  Warning("Target point for the AtlasAStar is in collision");
3399 
3400  InitHeap(sizeof(TAtlasHeapElement),
3405 
3406  NEW(t,a->k,double);
3407 
3408  NEW(info,a->maxCharts,TAStarInfo);
3409  NEW(pred,a->maxCharts,unsigned int);
3410 
3411  info[0].cost=0;
3412  info[0].heuristic=DistanceTopology(a->m,a->tp,ps,GetChartCenter(a->charts[0]));
3413  info[0].status=1; /*open*/
3414  pred[0]=NO_UINT;
3415 
3416  if (a->parallel)
3417  {
3418  st=NULL;
3419  NEW(chartID,a->nCores,unsigned int);
3420  NEW(newCharts,a->nCores,Tchart *);
3421  NEW(vs,a->nCores,unsigned int);
3422  NEW(ts,a->nCores,double*);
3423  for(i=0;i<a->nCores;i++)
3424  NEW(ts[i],a->k,double);
3425  }
3426  else
3427  {
3428  NEW(st,1,TAtlasStatistics);
3429  InitAtlasStatistics(st);
3430  }
3431 
3432  InitAtlasHeapElement(0,info[0].cost+info[0].heuristic,beta,&he);
3433  AddElement2Heap(NO_UINT,(void *)(&he),&h);
3434 
3435  found=FALSE;
3436 
3437  it=0;
3438 
3439  InitStatistics(a->nCores,0,&stime);
3440  *time=0.0;
3441 
3442  while ((!found)&&(!HeapEmpty(&h))&&(*time<maxTime)&&(a->currentChart<maxCharts))
3443  {
3444  if ((ATLAS_VERBOSE)||((it%1000)==0))
3445  {
3446  printf("Iteration %u (c:%u t:%g)\n",it,a->currentChart,*time);
3447  fflush(stdout);
3448  }
3449 
3450  ExtractMinElement((void *)(&he),&h);
3451  mID=GetAtlasHeapElementID(&he);
3452  infoParent=&(info[mID]);
3453 
3454  /* If the current chart already includes the goal we are done */
3455  if ((PointOnChart(pr,&(a->J),ps,a->tp,t,a->charts[mID]))&&
3456  (DistanceOnChart(pr,t,a->tp,&(a->J),a->charts[mID])<INF))
3457  found=TRUE;
3458  else
3459  {
3460  /* already closed element? The heap can hold alternative paths to
3461  the same node that have been improved over time. Instead of
3462  removing them from the heap as better paths are found we leave
3463  them as just ignore them when extracted.
3464  Moreover, we do not expand nodes whose cost is INF
3465  */
3466  if ((infoParent->status!=2)&&(infoParent->cost<INF))
3467  {
3468  cmPrev=a->currentChart;
3469  mmPrev=a->maxCharts;
3470 
3471  if (a->parallel)
3472  {
3473  while(ExpandibleChart(a->charts[mID]))
3474  {
3475  /* We have to genere new neighbors for chart 'mID'.
3476  Select up to 'nCores' other expandible charts and generate neighbours
3477  in parallel with the aim of saving time in future interations. */
3478  chartID[0]=mID;
3479  nce=1;
3480  i=0;
3481  while((i<HeapSize(&h))&&(nce<a->nCores))
3482  {
3483  hePtr=(TAtlasHeapElement*)GetHeapElement(i,&h); /* does not remove from heap */
3484 
3485  chartID[nce]=GetAtlasHeapElementID(hePtr);
3486  if (ExpandibleChart(a->charts[chartID[nce]]))
3487  nce++;
3488  i++;
3489  }
3490  #pragma omp parallel for private(i) schedule(static)
3491  for(i=0;i<nce;i++)
3492  {
3493  newCharts[i]=NULL;
3494  if (BoundaryPointFromExternalCorner(FALSE,&(vs[i]),ts[i],a->charts[chartID[i]]))
3495  {
3496  NewChartFromPoint(pr,chartID[i],ts[i],&(newCharts[i]),a);
3497 
3498  /* ensure that the selected corner is maked as "already used" */
3499  WrongCorner(vs[i],a->charts[chartID[i]]);
3500  }
3501  }
3502 
3503  /* Add the new charts to the atlas */
3504  for(i=0;i<nce;i++)
3505  {
3506  if (newCharts[i]!=NULL)
3507  {
3508  if (a->currentChart==a->maxCharts)
3509  MEM_DUP(a->charts,a->maxCharts,Tchart *);
3510 
3511  /* We directly re-use the charts to safe one copy. */
3512  a->charts[a->currentChart]=newCharts[i];
3513  a->currentChart++;
3514 
3515  /* Now detect neighbours and the possible bifurcations */
3516  PostProcessNewCharts(pr,TRUE,chartID[i],st,a);
3517  }
3518  }
3519  }
3520  }
3521  else
3522  {
3523  /* Generating all neighbours for this chart: one for each external vertex */
3524  while(ExpandibleChart(a->charts[mID]))
3525  {
3526  NewBoundaryAttempt(st);
3527  if (!BoundaryPointFromExternalCorner(FALSE,&nc,t,a->charts[mID]))
3528  {
3529  NewNotInBoundary(st);
3530  Error("Can not generate neighbouring charts");
3531  }
3532  else
3533  {
3534  ExtendAtlasFromPoint(pr,mID,t,st,a);
3535 
3536  /* ensure that the selected corner is maked as "already used" */
3537  WrongCorner(nc,a->charts[mID]);
3538  }
3539  } /* end of generate all neighbours */
3540  }
3541 
3542  /* set the A*-related information for the new charts */
3543  if (mmPrev<a->maxCharts)
3544  {
3545  MEM_EXPAND(info,a->maxCharts,TAStarInfo);
3546  MEM_EXPAND(pred,a->maxCharts,unsigned int);
3547  }
3548 
3549  for(cm=cmPrev;cm<a->currentChart;cm++)
3550  {
3551  /*Mark the new charts as un-visited*/
3552  info[cm].status=0;/* not open nor closed*/
3553  info[cm].heuristic=0;
3554  info[cm].cost=0;
3555  pred[cm]=NO_UINT;
3556  }
3557 
3558  /* Now that we have all the neighbours explicited proceed with
3559  the A* */
3560  pmID=GetChartCenter(a->charts[mID]);
3561 
3562  nn=ChartNumNeighbours(a->charts[mID]);
3563  for(i=0;i<nn;i++)
3564  {
3565  id=ChartNeighbourID(i,a->charts[mID]);
3566  if (id!=NO_UINT)
3567  {
3568  infoID=&(info[id]);
3569 
3570  #if (_DEBUG>1)
3571  printf(" N[%u->%u][%u] : ",mID,id,infoID->status);
3572  #endif
3573 
3574  if (infoID->status!=2) /*not closed (closed can not be improved)*/
3575  {
3576  pID=GetChartCenter(a->charts[id]);
3577 
3578  /* Geodesic distance is more accurate than euclidean and
3579  includes the presence of obstacles, if any. If obstacles
3580  are for sure not present, we just use the Euclidean
3581  distance.
3582 
3583  Caution: The GeodesicDistance function is not always
3584  able to find the path when it exists. This can induce
3585  sub-optimatility in the search. Moreover, the returned
3586  path is not the true geodesic, but at least is a path
3587  on the manifold. Use with caution.
3588  */
3589  if (ON_CUIKSYSTEM(a->w))
3590  dst=DistanceTopology(a->m,a->tp,pmID,pID);
3591  else
3592  dst=GeodesicDistance(pr,mID,id,a); /* This might be parallelized */
3593 
3594  c=infoParent->cost+dst;
3595 
3596  if ((infoID->status==0)|| /* 1st time we see this node */
3597  (c<infoID->cost)) /* status must be 1 (open) */
3598  {
3599  #if (_DEBUG>1)
3600  if (infoID->status==0)
3601  printf("new %g -> %g\n",dst,c);
3602  else
3603  printf("cheaper %g -> %g<%g\n",dst,c,infoID->cost);
3604  #endif
3605  /*not open not closed (1st time we see this node) */
3606  pred[id]=mID;
3607  infoID->cost=c;
3608  infoID->heuristic=DistanceTopology(a->m,a->tp,pID,ps);
3609 
3610  /* if open we are re-adding it to the heap. The cheapest
3611  path will have higher priority in the heap. */
3612  InitAtlasHeapElement(id,infoID->cost+infoID->heuristic,beta,
3613  &he2);
3614  AddElement2Heap(NO_UINT,(void *)(&he2),&h);
3615 
3616  infoID->status=1; /*open*/
3617  }
3618  #if (_DEBUG>1)
3619  else
3620  printf("%g > %g\n",c,infoID->cost);
3621  #endif
3622  }
3623  #if (_DEBUG>1)
3624  else
3625  printf("closed (%g)\n",infoID->cost);
3626  #endif
3627  }
3628  }
3629 
3630  infoParent->status=2; /*we close the current node node (all neighbors already explored) */
3631 
3632  } /*alrady closed element*/
3633  } /*if objective found*/
3634 
3635  it++;
3636  *time=GetElapsedTime(&stime);
3637  } /*loop until objective found*/
3638 
3639  DeleteStatistics(&stime);
3640 
3641  /* Use the pred to reconstruct the path */
3642  if (found)
3643  ReconstructAtlasPath(pr,pred,mID,ps,nv,systemVars,pl,ns,path,a);
3644  else
3645  {
3646  *ns=0;
3647  path=NULL;
3648  }
3649 
3650  if (a->parallel)
3651  {
3652  free(chartID);
3653  free(newCharts);
3654  free(vs);
3655  for(i=0;i<a->nCores;i++)
3656  free(ts[i]);
3657  free(ts);
3658  }
3659 
3660  if (st!=NULL)
3661  {
3662  PrintAtlasStatistics(pr,st);
3663  free(st);
3664  }
3665 
3666  free(info);
3667  free(pred);
3668 
3669  free(t);
3670  free(ps);
3671  DeleteHeap(&h);
3672  free(systemVars);
3673 
3674  return(found);
3675 }
3676 
3677 boolean AtlasGBF(Tparameters *pr,double *p,double *time,
3678  double *pl,unsigned int *ns,double ***path,Tatlas *a)
3679 {
3680  Theap h;
3681  TAtlasHeapElement he,he2;
3682  unsigned int mID;
3683  double heuristic;
3684  unsigned int *pred;
3685  boolean found;
3686  double *t;
3687  double epsilon;
3688  double *ps,*pWithDummies;
3689  double er;
3690  unsigned int nv;
3691  boolean *systemVars;
3692  unsigned int cm,cmPrev,mmPrev;
3693  TAtlasStatistics st;
3694  unsigned int it;
3695  Tstatistics stime;
3696  double beta;
3697  boolean collision=FALSE;
3698  double maxTime;
3699  unsigned int maxCharts;
3700 
3701  if (a->currentChart!=1)
3702  Error("Connect2Atlas assumes an initial atlas with only one local chart");
3703 
3704  epsilon=GetParameter(CT_EPSILON,pr);
3705  beta=GetParameter(CT_ATLASGBF_BETA,pr);
3706  maxTime=GetParameter(CT_MAX_PLANNING_TIME,pr);
3707  maxCharts=(unsigned int)GetParameter(CT_MAX_CHARTS,pr);
3708 
3709  nv=CS_WD_GET_SYSTEM_VARS(&systemVars,a->w);
3710 
3711  CS_WD_REGENERATE_SOLUTION_POINT(pr,p,&pWithDummies,a->w);
3712  if (CS_WD_GENERATE_SIMPLIFIED_POINT(pr,pWithDummies,&ps,a->w)!=a->m)
3713  Error("Dimension missmatch in AtlasGBF");
3714  if (a->n==0)
3715  er=0.0;
3716  else
3717  er=CS_WD_ERROR_IN_SIMP_EQUATIONS(pr,ps,a->w);
3718  if (er>epsilon)
3719  Error("Target point for the AtlasGBF is not on the manifold");
3720 
3721  collision=CS_WD_ORIGINAL_IN_COLLISION(pr,pWithDummies,NULL,a->w);
3722  if (collision)
3723  Warning("Target point for the AtlasGBF is in collision");
3724  free(pWithDummies);
3725 
3726  InitHeap(sizeof(TAtlasHeapElement),
3731 
3732  NEW(t,a->k,double);
3733 
3734  NEW(pred,a->maxCharts,unsigned int);
3735 
3736  heuristic=DistanceTopology(a->m,a->tp,GetChartCenter(a->charts[0]),ps);
3737  pred[0]=NO_UINT;
3738 
3739  InitAtlasStatistics(&st);
3740 
3741  InitAtlasHeapElement(0,heuristic,beta,&he);
3742  AddElement2Heap(NO_UINT,(void *)(&he),&h);
3743 
3744  found=FALSE;
3745 
3746  it=0;
3747  InitStatistics(a->nCores,0,&stime);
3748  *time=0.0;
3749 
3750  while ((!found)&&(!HeapEmpty(&h))&&(*time<maxTime)&&(a->currentChart<maxCharts))
3751  {
3752  ExtractMinElement((void *)(&he),&h);
3753  mID=GetAtlasHeapElementID(&he);
3754 
3755  if ((ATLAS_VERBOSE)||((it%1000)==0))
3756  {
3757  printf("Iteration %u (c:%u t:%g)\n",it,a->currentChart,*time);
3758  fflush(stdout);
3759  }
3760 
3761  if ((PointOnChart(pr,&(a->J),ps,a->tp,t,a->charts[mID]))&&
3762  (DistanceOnChart(pr,t,a->tp,&(a->J),a->charts[mID])<INF))
3763  found=TRUE;
3764  else
3765  {
3766  if (ExpandibleChart(a->charts[mID]))
3767  {
3768  NewBoundaryAttempt(&st);
3769 
3770  if (!RandomPointOnBoundary(t,a->charts[mID]))
3771  {
3772  NewNotInBoundary(&st);
3774  }
3775  else
3776  {
3777  /*printf(" New random point: ");PrintVector(stdout,a->k,t);*/
3778 
3779  cmPrev=a->currentChart;
3780  mmPrev=a->maxCharts;
3781  if (ExtendAtlasTowardPoint(pr,mID,t,TRUE,&st,a))
3782  {
3783  /* If we extended the room for charts, we have to
3784  extend the associated information accordingly*/
3785  if (mmPrev<a->maxCharts)
3786  MEM_EXPAND(pred,a->maxCharts,unsigned int);
3787 
3788  for(cm=cmPrev;cm<a->currentChart;cm++)
3789  {
3790  pred[cm]=mID;
3791  heuristic=DistanceTopology(a->m,a->tp,
3792  GetChartCenter(a->charts[cm]),
3793  ps);
3794  InitAtlasHeapElement(cm,heuristic,beta,&he2);
3795  AddElement2Heap(NO_UINT,(void *)(&he2),&h);
3796  }
3797  }
3798  else
3800  }
3801 
3802  AddElement2Heap(NO_UINT,(void *)(&he),&h);
3803  } /* if ExpandibleChart() = chart that can be expanded*/
3804  } /*if objective found*/
3805 
3806  it++;
3807  *time=GetElapsedTime(&stime);
3808  } /*loop until objective found*/
3809  DeleteStatistics(&stime);
3810 
3811  /* Use the pred to reconstruct the path */
3812  if (found)
3813  ReconstructAtlasPath(pr,pred,mID,ps,nv,systemVars,pl,ns,path,a);
3814  else
3815  {
3816  *ns=0;
3817  path=NULL;
3818  }
3819 
3820  PrintAtlasStatistics(pr,&st);
3821 
3822  free(pred);
3823  free(t);
3824  free(ps);
3825  DeleteHeap(&h);
3826  free(systemVars);
3827 
3828  return(found);
3829 }
3830 
3831 unsigned int AtlasMemSize(Tatlas *a)
3832 {
3833  unsigned int b,i;
3834 
3835  b=0;
3836  for(i=0;i<a->currentChart;i++)
3837  b+=ChartMemSize(a->charts[i]); /* charts[][] */
3838 
3839  return(b);
3840 }
3841 
3843 {
3844  FILE *f;
3845  unsigned int i;
3846 
3847  f=fopen(GetFileFullName(fname),"w");
3848  if (!f)
3849  Error("Could not open fiel to store atlas");
3850 
3851  fprintf(f,"%u\n",a->m);
3852  fprintf(f,"%u\n",a->k);
3853  fprintf(f,"%u\n",a->n);
3854  fprintf(f,"%.12f\n",a->e);
3855  fprintf(f,"%.12f\n",a->ce);
3856  fprintf(f,"%.12f\n",a->r);
3857  fprintf(f,"%u\n",a->simpleChart);
3858 
3859  fprintf(f,"%u\n",a->maxCharts);
3860  fprintf(f,"%u\n",a->currentChart);
3861  for(i=0;i<a->currentChart;i++)
3862  SaveChart(f,a->charts[i]);
3863 
3864  SaveBifurcations(f,a);
3865 
3866  fclose(f);
3867 }
3868 
3870 {
3871  FILE *f;
3872  unsigned int i;
3873 
3874  f=fopen(GetFileFullName(fname),"r");
3875  if (!f)
3876  Error("Could not open file to read atlas");
3877 
3878  fscanf(f,"%u",&(a->m));
3879  fscanf(f,"%u",&(a->k));
3880  fscanf(f,"%u",&(a->n));
3881  fscanf(f,"%lf",&(a->e));
3882  fscanf(f,"%lf",&(a->ce));
3883  fscanf(f,"%lf",&(a->r));
3884  fscanf(f,"%u",&(a->simpleChart));
3885 
3886  a->w=w;
3887  SetAtlasTopology(pr,a);
3888 
3889  NEW(a->ambient,1,Tbox);
3891 
3892  fscanf(f,"%u",&(a->maxCharts));
3893  fscanf(f,"%u",&(a->currentChart));
3894  NEW(a->charts,a->maxCharts,Tchart *);
3895  for(i=0;i<a->currentChart;i++)
3896  {
3897  NEW(a->charts[i],1,Tchart);
3898  LoadChart(f,a->w,a->charts[i]);
3899 
3900  #if (USE_ATLAS_TREE)
3901  if (i==0)
3902  InitBTree(i,a->charts[i],a->ambient,a->tp,&(a->tree));
3903  else
3904  AddChart2Btree(i,a->charts[i],&(a->tree));
3905  #endif
3906  }
3907 
3908  LoadBifurcations(f,a);
3909 
3910  fclose(f);
3911 
3912  /* The Jacobian is not saved but re-computed */
3913  CS_WD_GET_SIMP_JACOBIAN(pr,&(a->J),a->w);
3914  GetJacobianSize(&(a->nrJ),&(a->ncJ),&(a->J));
3915 
3916  /* delay the Hessian computation */
3917  a->H=NULL;
3918 
3919  /* The parallelism information is not stored! */
3920  #ifdef _OPENMP
3921  a->nCores=omp_get_max_threads();
3922  a->parallel=((a->nCores>1)&&((a->m>25)||(a->k>2)));
3923  #else
3924  a->parallel=FALSE;
3925  #endif
3926 
3927  if (!a->parallel)
3928  a->nCores=1;
3929 }
3930 
3931 unsigned int GetAtlasNumCharts(Tatlas *a)
3932 {
3933  return(a->currentChart);
3934 }
3935 
3936 Tchart *GetAtlasChart(unsigned int id,Tatlas *a)
3937 {
3938  if (id<a->currentChart)
3939  return(a->charts[id]);
3940  else
3941  return(NULL);
3942 }
3943 
3944 boolean RandomPointInAtlas(Tparameters *pr,double scale,double *w,
3945  unsigned int *nm,
3946  double *t,double *p,Tatlas *a)
3947 {
3948  boolean havePoint;
3949 
3950  if (w==NULL)
3951  {
3952  /* Uniform distribution on charts*/
3953  *nm=randomMax(a->currentChart-1);
3954  }
3955  else
3956  {
3957  /* Select the charts from the given distribution */
3959  }
3960  /* Get a point from the selected chart */
3961  havePoint=RandomPointInChart(pr,scale,a->tp,t,p,a->charts[*nm]);
3962 
3963  return(havePoint);
3964 }
3965 
3966 double AtlasVolume(Tparameters *pr,boolean collisionFree,Tatlas *a)
3967 {
3968  unsigned int i;
3969  double v,vc;
3970 
3971  v=0.0;
3972  for(i=0;i<a->currentChart;i++)
3973  {
3974  if (!FrontierChart(a->charts[i]))
3975  {
3976  vc=ChartVolume(pr,collisionFree,a->tp,&(a->J),a->charts[i]);
3977  #if (ATLAS_VERBOSE)
3978  printf(" Volume of chart %u: %g\n",i,vc);
3979  #endif
3980  v+=vc;
3981  }
3982  }
3983 
3984  return(v);
3985 }
3986 
3987 void SaveChartCenters(Tparameters *pr,char *fname,boolean inside,
3988  boolean saveWithDummies,boolean middlePoint,Tatlas *a)
3989 {
3990  double *o;
3991  unsigned int i,j,nv,nvs;
3992  boolean *systemVars;
3993  double *c;
3994  FILE *fo;
3995  Tfilename fsol;
3996  double *t,*p;
3997 
3998  if (saveWithDummies)
3999  CreateFileName(NULL,fname,"_center",SOL_WITH_DUMMIES_EXT,&fsol);
4000  else
4001  CreateFileName(NULL,fname,"_center",SOL_EXT,&fsol);
4002  fprintf(stderr,"Writing boxes to : %s\n",GetFileFullName(&fsol));
4003  fo=fopen(GetFileFullName(&fsol),"w");
4004  if (!fo)
4005  Error("Could not open the file to store the boxes in GetChartCenters");
4006 
4007  nv=CS_WD_GET_SYSTEM_VARS(&systemVars,a->w);
4008  nvs=0;
4009  for(j=0;j<nv;j++)
4010  {
4011  if (systemVars[j])
4012  nvs++;
4013  }
4014 
4015  if (middlePoint)
4016  {
4017  NEW(t,a->k,double);
4018  NEW(p,a->m,double);
4019  }
4020 
4021  for(i=0;i<a->currentChart;i++)
4022  {
4023  //if (SingularChart(a->charts[i]))
4024  if ((!inside)||(!FrontierChart(a->charts[i])))
4025  {
4026  c=GetChartCenter(a->charts[i]);
4027 
4028  CS_WD_REGENERATE_ORIGINAL_POINT(pr,c,&o,a->w);
4029 
4030  if (saveWithDummies)
4031  fprintf(fo,"%u { %u ",i,nv);
4032  else
4033  fprintf(fo,"%u { %u ",i,nvs);
4034  for(j=0;j<nv;j++)
4035  {
4036  if ((saveWithDummies)||(systemVars[j]))
4037  fprintf(fo,"[%.12g,%.12g] ",o[j],o[j]);
4038  }
4039  fprintf(fo,"}\n");
4040 
4041  free(o);
4042 
4043  if (middlePoint)
4044  {
4045  unsigned int nn,nk,k;
4046 
4047  nn=ChartNumNeighbours(a->charts[i]);
4048 
4049  fprintf(stderr,"Chart %u/%u (%u)\n",i,a->currentChart,nn);
4050  for(k=0;k<nn;k++)
4051  {
4052  nk=ChartNeighbourID(k,a->charts[i]);
4053  if ((nk!=NO_UINT)&&(nk>i))
4054  {
4056  t,a->charts[i]);
4057  ScaleVector(0.5,a->k,t);
4058  if (Chart2Manifold(pr,&(a->J),t,a->tp,NULL,p,a->charts[i])<INF)
4059  {
4060  CS_WD_REGENERATE_ORIGINAL_POINT(pr,p,&o,a->w);
4061 
4062  if (saveWithDummies)
4063  fprintf(fo,"%u { %u ",i,nv);
4064  else
4065  fprintf(fo,"%u { %u ",i,nvs);
4066  for(j=0;j<nv;j++)
4067  {
4068  if ((saveWithDummies)||(systemVars[j]))
4069  fprintf(fo,"[%.12g,%.12g] ",o[j],o[j]);
4070  }
4071  fprintf(fo,"}\n");
4072 
4073  free(o);
4074  }
4075  else
4076  fprintf(stderr,"Error generating intermediate point %u %u\n",i,nk);
4077  }
4078  }
4079  }
4080  }
4081  }
4082 
4083  if (middlePoint)
4084  {
4085  free(t);
4086  free(p);
4087  }
4088  fclose(fo);
4089 
4090  free(systemVars);
4091 
4092  DeleteFileName(&fsol);
4093 }
4094 
4095 void SaveSingularCharts(Tparameters *pr,char *fname,
4096  boolean saveWithDummies,Tatlas *a)
4097 {
4098  double *o;
4099  unsigned int i,j,nv,nvs;
4100  boolean *systemVars;
4101  double *c;
4102  FILE *fo;
4103  Tfilename fsol;
4104 
4105  if (saveWithDummies)
4106  CreateFileName(NULL,fname,"_singular",SOL_WITH_DUMMIES_EXT,&fsol);
4107  else
4108  CreateFileName(NULL,fname,"_singular",SOL_EXT,&fsol);
4109  fprintf(stderr,"Writing boxes to : %s\n",GetFileFullName(&fsol));
4110  fo=fopen(GetFileFullName(&fsol),"w");
4111  if (!fo)
4112  Error("Could not open the file to store the boxes in GetChartCenters");
4113 
4114  nv=CS_WD_GET_SYSTEM_VARS(&systemVars,a->w);
4115  nvs=0;
4116  for(j=0;j<nv;j++)
4117  {
4118  if (systemVars[j])
4119  nvs++;
4120  }
4121 
4122  for(i=0;i<a->currentChart;i++)
4123  {
4124  if (SingularChart(a->charts[i]))
4125  {
4126  c=GetChartCenter(a->charts[i]);
4127 
4128  CS_WD_REGENERATE_ORIGINAL_POINT(pr,c,&o,a->w);
4129 
4130  if (saveWithDummies)
4131  fprintf(fo,"%u { %u ",i,nv);
4132  else
4133  fprintf(fo,"%u { %u ",i,nvs);
4134  for(j=0;j<nv;j++)
4135  {
4136  if ((saveWithDummies)||(systemVars[j]))
4137  fprintf(fo,"[%.12g,%.12g] ",o[j],o[j]);
4138  }
4139  fprintf(fo,"}\n");
4140 
4141  free(o);
4142  }
4143  }
4144  fclose(fo);
4145 
4146  free(systemVars);
4147 
4148  DeleteFileName(&fsol);
4149 }
4150 
4151 void PlotAtlas(char *fname,int argc,char **arg,Tparameters *pr,FILE *fcost,
4152  unsigned int xID,unsigned int yID,unsigned int zID,Tatlas *a)
4153 {
4154  Tplot3d p3d;
4155  unsigned int i;
4156  Tcolor color;
4157  unsigned int obj,np;
4158 
4159  InitPlot3d(fname,FALSE,argc,arg,&p3d);
4160 
4161  /* When plotting as polytopes all charts are plotted in blue and not
4162  bifurcation info is plotted */
4163 
4164  /* Normal charts in blue */
4165  NewColor(0.5,0.5,1,&color); /*blue*/
4166  obj=StartNew3dObject(&color,&p3d);
4167  np=0;
4168  for(i=0;i<a->currentChart;i++)
4169  {
4170  #if (PLOT_ATLAS_IN_COLORS)
4171  if ((fcost!=NULL)||(a->simpleChart)||
4172  ((!ExpandibleChart(a->charts[i]))&&
4173  (!SingularChart(a->charts[i]))&&
4174  (!FrontierChart(a->charts[i]))))
4175  #endif
4176  {
4177  np++;
4178  PlotChart(pr,fcost,&(a->J),xID,yID,zID,&p3d,a->charts[i]);
4179  }
4180  }
4181  if ((PLOT_AS_POLYGONS)&&(a->k==2)&&(fcost!=NULL))
4182  Close3dObjectNoColor(&p3d); /* the cost already gave the color when plotting */
4183  else
4184  Close3dObject(&p3d);
4185  DeleteColor(&color);
4186  if (np==0)
4187  Delete3dObject(obj,&p3d);
4188 
4189  if ((PLOT_ATLAS_IN_COLORS)&&(fcost==NULL)&&(!a->simpleChart))
4190  {
4191  /* Singular charts in green */
4192  NewColor(0,1,0,&color); /*green*/
4193  obj=StartNew3dObject(&color,&p3d);
4194  np=0;
4195  for(i=0;i<a->currentChart;i++)
4196  {
4197  if ((!ExpandibleChart(a->charts[i]))&&(SingularChart(a->charts[i])&&(!FrontierChart(a->charts[i]))))
4198  {
4199  np++;
4200  PlotChart(pr,NULL,&(a->J),xID,yID,zID,&p3d,a->charts[i]);
4201  }
4202  }
4203 
4204  Close3dObject(&p3d);
4205  DeleteColor(&color);
4206  if (np==0)
4207  Delete3dObject(obj,&p3d);
4208 
4209  /* Open charts if red (Open = expansion is still possible) */
4210  NewColor(1,0.5,0.5,&color); /*red*/
4211  obj=StartNew3dObject(&color,&p3d);
4212  np=0;
4213  for(i=0;i<a->currentChart;i++)
4214  {
4215  if ((ExpandibleChart(a->charts[i]))&&(!SingularChart(a->charts[i])&&(!FrontierChart(a->charts[i]))))
4216  {
4217  np++;
4218  PlotChart(pr,NULL,&(a->J),xID,yID,zID,&p3d,a->charts[i]);
4219  }
4220  }
4221 
4222  Close3dObject(&p3d);
4223  DeleteColor(&color);
4224  if (np==0)
4225  Delete3dObject(obj,&p3d);
4226 
4227  /* Expandible singular charts in yellow */
4228  NewColor(1,1,0,&color); /*yellow*/
4229  obj=StartNew3dObject(&color,&p3d);
4230  np=0;
4231  for(i=0;i<a->currentChart;i++)
4232  {
4233  if ((ExpandibleChart(a->charts[i]))&&(SingularChart(a->charts[i])&&(!FrontierChart(a->charts[i]))))
4234  {
4235  np++;
4236  PlotChart(pr,NULL,&(a->J),xID,yID,zID,&p3d,a->charts[i]);
4237  }
4238  }
4239 
4240  Close3dObject(&p3d);
4241  DeleteColor(&color);
4242  if (np==0)
4243  Delete3dObject(obj,&p3d);
4244 
4245  /* Frontier charts in dark red */
4246  NewColor(0.25,0,0,&color); /* */
4247  obj=StartNew3dObject(&color,&p3d);
4248  np=0;
4249  for(i=0;i<a->currentChart;i++)
4250  {
4251  //if ((!ExpandibleChart(a->charts[i]))&&(!SingularChart(a->charts[i])&&(FrontierChart(a->charts[i]))))
4252  if (FrontierChart(a->charts[i]))
4253  {
4254  np++;
4255  PlotChart(pr,NULL,&(a->J),xID,yID,zID,&p3d,a->charts[i]);
4256  }
4257  }
4258 
4259  Close3dObject(&p3d);
4260  DeleteColor(&color);
4261  if (np==0)
4262  Delete3dObject(obj,&p3d);
4263 
4264  /* Now plot a line connecting chart at the two sides of a singularity */
4265  //PlotBifurcations(pr,&p3d,xID,yID,zID,a);
4266  }
4267 
4268  /*line for the neighbouring relations*/
4269 #if (0)
4270  {
4271  unsigned int j;
4272  double *pi,*pj;
4273  double x[2],y[2],z[2];
4274  unsigned int nn,nj;
4275  double *o;
4276 
4277  NewColor(1,1,0,&color);
4278  StartNew3dObject(&color,&p3d);
4279  for(i=0;i<a->currentChart;i++)
4280  {
4281  pi=GetChartCenter(a->charts[i]);
4282  CS_WD_REGENERATE_ORIGINAL_POINT(pr,pi,&o,a->w);
4283  x[0]=o[xID];
4284  y[0]=o[yID];
4285  z[0]=o[zID];
4286  free(o);
4287 
4288  nn=ChartNumNeighbours(a->charts[i]);
4289  if (nn==0)
4290  fprintf(stderr,"Chart %u has no neighbours",i);
4291  for(j=0;j<nn;j++)
4292  {
4293  nj=ChartNeighbourID(j,a->charts[i]);
4294  if ((nj!=NO_UINT)&&(nj>i))
4295  {
4296  pj=GetChartCenter(a->charts[nj]);
4297  CS_WD_REGENERATE_ORIGINAL_POINT(pr,pj,&o,a->w);
4298  x[1]=o[xID];
4299  y[1]=o[yID];
4300  z[1]=o[zID];
4301  free(o);
4302  PlotVect3d(2,x,y,z,&p3d);
4303  }
4304  }
4305  }
4306  Close3dObject(&p3d);
4307  DeleteColor(&color);
4308  }
4309 #endif
4310 
4311  ClosePlot3d(FALSE,0,0,0,&p3d);
4312 }
4313 
4314 void TriangulateAtlas(char *fname,int argc,char **arg,Tparameters *pr,FILE *fcost,
4315  unsigned int xID,unsigned int yID,unsigned int zID,Tatlas *a)
4316 {
4317  Tplot3d p3d;
4318  unsigned int i,j,k;
4319  Tcolor color;
4320  double *p,*o;
4321  double cost;
4322  double **v; /* Vertices */
4323  Tcolor *c; /* One color per vertex (might not be used) */
4324  unsigned int mf,nf; /* Max faces (space allocated for faces) and current number
4325  of faces */
4326  unsigned int *nvf,**fv; /* Vertex per face, and vertices in each face. */
4327  unsigned int nTmp;
4328  double v1[3],v2[3],cosAngle;
4329  boolean *corrected,*used;
4330  double **normal;
4331  unsigned int nc;
4332  boolean correctionDone;
4333  unsigned int nn,*nID1,*nID2;
4334  boolean found;
4335  unsigned int *tp;
4336  unsigned int rep;
4337  double cx,cy,cz;
4338 
4339  if (a->k!=2)
4340  Error("TriangulateAtlas only operates on surfaces (manifold dim=2)");
4341 
4342  NEW(tp,3,unsigned int);
4343  tp[0]=CS_WD_GET_VAR_TOPOLOGY(xID,a->w);
4344  tp[1]=CS_WD_GET_VAR_TOPOLOGY(yID,a->w);
4345  tp[2]=CS_WD_GET_VAR_TOPOLOGY(zID,a->w);
4346 
4347  if ((tp[0]==TOPOLOGY_R)&&(tp[1]==TOPOLOGY_R)&&(tp[2]==TOPOLOGY_R))
4348  {
4349  free(tp);
4350  tp=NULL;
4351  }
4352 
4353  InitPlot3d(fname,FALSE,argc,arg,&p3d);
4354 
4355  /* Now store the vertices, one per chart (i.e., the center), possibly
4356  with associated colors */
4357  NEW(v,a->currentChart,double*);
4358  if (fcost!=NULL)
4359  NEW(c,a->currentChart,Tcolor);
4360 
4361  cx=GetParameter(CT_CUT_X,pr);
4362  cy=GetParameter(CT_CUT_Y,pr);
4363  cz=GetParameter(CT_CUT_Z,pr);
4364  rep=(unsigned int)(GetParameter(CT_REPRESENTATION,pr));
4365 
4366  for(i=0;i<a->currentChart;i++)
4367  {
4368  NEW(v[i],3,double);
4369  p=GetChartCenter(a->charts[i]);
4370  CS_WD_REGENERATE_ORIGINAL_POINT(pr,p,&o,a->w);
4371  v[i][0]=o[xID];
4372  v[i][1]=o[yID];
4373  v[i][2]=o[zID];
4374  if (rep==REP_JOINTS)
4375  {
4376  if ((cx<0)&&(v[i][0]<cx))
4377  v[i][0]+=M_2PI;
4378  if ((cx>0)&&(v[i][0]>cx))
4379  v[i][0]-=M_2PI;
4380  if ((cy<0)&&(v[i][1]<cy))
4381  v[i][1]+=M_2PI;
4382  if ((cy>0)&&(v[i][1]>cy))
4383  v[i][1]-=M_2PI;
4384  if ((cz<0)&&(v[i][2]<cz))
4385  v[i][2]+=M_2PI;
4386  if ((cz>0)&&(v[i][2]>cz))
4387  v[i][2]-=M_2PI;
4388  }
4389  free(o);
4390  if (fcost!=NULL)
4391  {
4392  /* Set up the color for this vertex */
4393  if (fscanf(fcost,"%lf",&cost)!=1)
4394  Error("No enough data in the cost file");
4395 
4396  CostColor(cost,1e-1,&(c[i]));
4397  }
4398  }
4399 
4400  /* Now set up the faces */
4401  mf=a->currentChart;
4402  nf=0;
4403  NEW(fv,mf,unsigned int*);
4404  for(i=0;i<a->currentChart;i++)
4405  {
4406  GetChartNeighboursFromVertices(pr,&nn,&nID1,&nID2,a->charts[i]);
4407  for(j=0;j<nn;j++)
4408  {
4409  /* Vertices corresponding to the border of the atlas still
4410  have the default faces with NO_UINT as ID -> not use these
4411  vertices*/
4412  if ((nID1[j]!=NO_UINT)&&(nID2[j]!=NO_UINT))
4413  {
4414  if (nf==mf)
4415  MEM_DUP(fv,mf,unsigned int*);
4416  NEW(fv[nf],3,unsigned int);
4417 
4418  fv[nf][0]=i;
4419  fv[nf][1]=nID1[j];
4420  fv[nf][2]=nID2[j];
4421 
4422  /* Triangles that cross the borders imposed by the topology
4423  should not be considered. */
4424  if (tp==NULL)
4425  found=FALSE;
4426  else
4427  {
4428  /*
4429  found=((CrossTopologyBorder(a->m,a->tp,
4430  GetChartCenter(a->charts[i]),
4431  GetChartCenter(a->charts[nID1[j]])))||
4432  (CrossTopologyBorder(a->m,a->tp,
4433  GetChartCenter(a->charts[i]),
4434  GetChartCenter(a->charts[nID2[j]])))||
4435  (CrossTopologyBorder(a->m,a->tp,
4436  GetChartCenter(a->charts[nID1[j]]),
4437  GetChartCenter(a->charts[nID1[j]]))));
4438  */
4439  found=((CrossTopologyBorder(3,tp,
4440  v[i],
4441  v[nID1[j]]))||
4442  (CrossTopologyBorder(3,tp,
4443  v[i],
4444  v[nID2[j]]))||
4445  (CrossTopologyBorder(3,tp,
4446  v[nID1[j]],
4447  v[nID2[j]])));
4448  }
4449 
4450  k=0;
4451  while ((!found)&&(k<nf))
4452  {
4453  found=SameTriangle(fv[nf],fv[k]);
4454  k++;
4455  }
4456  if (!found)
4457  nf++;
4458  }
4459  }
4460  free(nID1);
4461  free(nID2);
4462  }
4463  if (tp!=NULL)
4464  free(tp);
4465 
4466  /* All faces have 3 vertices */
4467  NEW(nvf,nf,unsigned int);
4468  for(i=0;i<nf;i++)
4469  nvf[i]=3;
4470  /* Fix the orientation for the triangles */
4471  NEW(used,nf,boolean);
4472  NEW(corrected,nf,boolean);
4473  NEW(normal,nf,double*);
4474  for(i=0;i<nf;i++)
4475  {
4476  used[i]=FALSE;
4477  corrected[i]=FALSE;
4478  NEW(normal[i],3,double);
4479  }
4480  /* Start from the first triangle */
4481  corrected[0]=TRUE;
4482  DifferenceVector(3,v[fv[0][1]],v[fv[0][0]],v1);
4483  DifferenceVector(3,v[fv[0][2]],v[fv[0][0]],v2);
4484  CrossProduct(v1,v2,normal[0]);
4485  nc=1;
4486  correctionDone=FALSE;
4487  while((!correctionDone)&&(nc<nf))
4488  {
4489  /* Search for a corrected no used face */
4490  i=0;
4491  while ((i<nf)&&((used[i])||(!corrected[i])))
4492  i++;
4493  if (i==nf)
4494  correctionDone=TRUE;
4495 
4496  if (!correctionDone)
4497  {
4498  /* Align all neighbours with the normal at this face */
4499  j=0;
4500  while(j<nf)
4501  {
4502  if (!corrected[j])
4503  {
4504  if (NeighbouringTriangles(fv[i],fv[j]))
4505  {
4506  DifferenceVector(3,v[fv[j][1]],v[fv[j][0]],v1);
4507  DifferenceVector(3,v[fv[j][2]],v[fv[j][0]],v2);
4508  CrossProduct(v1,v2,normal[j]);
4509 
4510  cosAngle=DotProduct(normal[i],normal[j]);
4511  if (cosAngle<0)
4512  {
4513  /* Swap the orientation of face j */
4514  nTmp=fv[j][1];
4515  fv[j][1]=fv[j][2];
4516  fv[j][2]=nTmp;
4517  ScaleVector(-1.0,3,normal[j]);
4518  }
4519  corrected[j]=TRUE;
4520  nc++;
4521  }
4522  }
4523  j++;
4524  }
4525  used[i]=TRUE;
4526  }
4527  }
4528  free(used);
4529  free(corrected);
4530  for(i=0;i<nf;i++)
4531  free(normal[i]);
4532  free(normal);
4533 
4534  /* Define the object */
4535  /* Normal charts in blue */
4536  NewColor(-1,-1,-1,&color); /*blue*/
4537  StartNew3dObject(&color,&p3d);
4538 
4539  if (fcost==NULL)
4540  Plot3dObject(a->currentChart,nf,1,v,nvf,fv,&p3d);
4541  else
4542  Plot3dObjectWithColors(a->currentChart,nf,1,v,c,nvf,fv,&p3d);
4543 
4544  Close3dObject(&p3d);
4545  ClosePlot3d(FALSE,0,0,0,&p3d);
4546 
4547  /* Release memory */
4548  for(i=0;i<a->currentChart;i++)
4549  free(v[i]);
4550  free(v);
4551 
4552  if (fcost!=NULL)
4553  free(c);
4554 
4555  for(i=0;i<nf;i++)
4556  free(fv[i]);
4557  free(fv);
4558  free(nvf);
4559 }
4560 
4562 {
4563  unsigned int i;
4564 
4565  DeleteJacobian(&(a->J));
4566 
4567  if (a->H!=NULL)
4568  {
4569  DeleteHessian(a->H);
4570  free(a->H);
4571  }
4572 
4573  for(i=0;i<a->currentChart;i++)
4574  {
4575  DeleteChart(a->charts[i]);
4576  free(a->charts[i]);
4577  }
4578 
4579  free(a->charts);
4580 
4581  if (a->ambient!=NULL)
4582  {
4583  DeleteBox(a->ambient);
4584  free(a->ambient);
4585  }
4586 
4587  if (a->tp!=NULL)
4588  free(a->tp);
4589 
4590  DeleteBifurcations(a);
4591 
4592  #if (USE_ATLAS_TREE)
4593  if (a->currentChart>0)
4594  DeleteBTree(&(a->tree));
4595  #endif
4596 }
#define CT_R
Ball radius in atlas.
Definition: parameters.h:257
void NewSingularImpossible(TAtlasStatistics *ast)
New time we could not extend a singular chart.
Definition: atlas.c:785
boolean AtlasAStar(Tparameters *pr, double *p, double *time, double *pl, unsigned int *ns, double ***path, Tatlas *a)
Expands the atlas to reach a given point.
Definition: atlas.c:3341
void NewBifurcation(TAtlasStatistics *ast)
New processed bifurcation.
Definition: atlas.c:791
unsigned int nImpossible
Definition: atlas.h:118
boolean ExtendAtlasFromPoint(Tparameters *pr, unsigned int parentID, double *t, TAtlasStatistics *st, Tatlas *a)
Tries to expand the atlas from a chart from a given point.
Definition: atlas.c:1015
void PlotVect3d(unsigned int n, double *x, double *y, double *z, Tplot3d *p)
Adds a polyline to the current object.
Definition: plot3d.c:447
CBLAS_INLINE void ScaleVector(double f, unsigned int s, double *v)
Scales a vector.
Definition: basic_algebra.c:30
boolean PointOnChart(Tparameters *pr, TJacobian *sJ, double *p, unsigned int *tp, double *t, Tchart *c)
Identify points on a chart.
Definition: chart.c:1602
void SaveChart(FILE *f, Tchart *c)
Stores the chart information on a file.
Definition: chart.c:1877
unsigned int d2
Definition: atlas.h:163
void AddChart2Btree(unsigned int id, Tchart *mp, TBTree *t)
Adds a chart to the tree.
Definition: btree.c:75
unsigned int ns
Definition: atlas.c:36
unsigned int ChartMemSize(Tchart *c)
Memory used by a given chart.
Definition: chart.c:1862
void LoadAtlas(Tparameters *pr, Tfilename *fname, TAtlasBase *w, Tatlas *a)
Defines an atlas from the information on a file.
Definition: atlas.c:3869
boolean FindPointInOtherBranch(Tparameters *pr, unsigned int bID, double *phi, double **p, Tatlas *a)
Searches for a point in the other manifold branch.
Definition: atlas.c:2349
unsigned int d1
Definition: atlas.h:161
double ce
Definition: atlas.h:296
#define REP_JOINTS
One of the possible values of the REPRESENTATION parameter.
Definition: parameters.h:60
unsigned int nLargeError
Definition: atlas.h:121
unsigned int st
Definition: atlas.c:33
#define CS_WD_ERROR_IN_SIMP_EQUATIONS(pr, p, wcs)
Computes the error in the simplified system for a given point.
Definition: wcs.h:446
#define MIN_SAMPLING_RADIUS
Relative minimum sampling radius.
Definition: chart.h:59
#define CT_EPSILON
Numerical tolerance.
Definition: parameters.h:194
#define FALSE
FALSE.
Definition: boolean.h:30
unsigned int nSmallAngle
Definition: atlas.h:136
boolean CompareTangentSpaces(Tchart *c1, Tchart *c2)
Checks if the tangent spaces are similar.
Definition: chart.c:901
#define CS_WD_GENERATE_SIMPLIFIED_POINT(pr, p, r, wcs)
Generates a simplified point from an original one.
Definition: wcs.h:432
CBLAS_INLINE void SetRow(double *v, unsigned int k, unsigned int r, unsigned int c, double *m)
Sets a row of a matrix.
unsigned int FindKernel(unsigned int nr, unsigned int nc, double *mT, unsigned int dof, boolean check, double epsilon, double **T)
Computes the kernel of a matrix.
Definition: algebra.c:1098
unsigned int GetAtlasManifoldDim(Tatlas *a)
Manifold dimensionality.
Definition: atlas.c:3336
#define INIT_NUM_CHARTS_IN_ATLAS_HEAP
Initial number of elements in the heap of local charts.
Definition: atlas.h:102
double DistanceTopology(unsigned int s, unsigned int *tp, double *v1, double *v2)
Computes the distance of two points.
TJacobian J
Definition: atlas.h:315
unsigned int m
Definition: atlas.h:292
void DeleteHessian(THessian *h)
Destructor.
Definition: hessian.c:77
#define NEW(_var, _n, _type)
Allocates memory space.
Definition: defines.h:385
void SearchInBtree(Tchart *mp, unsigned int *nn, unsigned int **n, TBTree *t)
Search for neighbouring charts.
Definition: btree.c:113
#define CS_WD_GET_VAR_TOPOLOGY(varID, wcs)
Gets the variable topology.
Definition: wcs.h:263
void ComputeAtlasHessian(Tatlas *a)
Computes the Hessian from the Jacobian.
void EvaluateTransposedJacobianInVector(double *v, unsigned int nr, unsigned int nc, double *m, TJacobian *j)
Evaluates the transposed Jacobian.
Definition: jacobian.c:137
Data structure to hold the information about the name of a file.
Definition: filename.h:248
#define RC2INDEX(i, j, nr, nc)
Index in a vector of a matrix element.
Definition: basic_algebra.h:81
void ArrayPi2Pi(unsigned int n, unsigned int *t, double *a)
Applies PI2PI to an array.
Tbox * ambient
Definition: atlas.h:320
unsigned int status
Definition: atlas.c:53
boolean RandomPointInAtlas(Tparameters *pr, double scale, double *w, unsigned int *nm, double *t, double *p, Tatlas *a)
Samples a random point on the atlas.
Definition: atlas.c:3944
boolean BoundaryPointFromExternalCorner(boolean rand, unsigned int *nv, double *t, Tchart *c)
Random point on the chart boundary from the polytope vetices.
Definition: chart.c:1340
Structure used for the elements of the heap of charts.
Definition: atlas.h:176
void AllocateHessianEvaluation(double ****m, THessian *h)
Allocate space for the Hessian evaluation.
Definition: hessian.c:33
void EvaluateHessian(double *v, double ***m, THessian *h)
Evaluates the Hessian.
Definition: hessian.c:46
double GetAtlasError(Tatlas *a)
Maximum error for all the charts.
Definition: atlas.c:3316
unsigned int chartID
Definition: atlas.h:177
unsigned int randomMax(unsigned int m)
Returns a random integer in the range [0,m].
Definition: random.c:77
void ProcessBifurcation(Tparameters *pr, unsigned int bID, TAtlasStatistics *ast, Tatlas *a)
Processes the bifurcation points not yet processed.
Definition: atlas.c:2444
CBLAS_INLINE void TMatrixMatrixProduct(unsigned int ra, unsigned int ca, double *A, unsigned int cb, double *B, double *C)
C = A^t * B.
void InitStatistics(unsigned int np, double v, Tstatistics *t)
Constructor.
Definition: statistics.c:21
CBLAS_INLINE double Norm(unsigned int s, double *v)
Computes the norm of a vector.
void LinkCharts(unsigned int id1, Tchart *c1, unsigned int id2, Tchart *c2)
Connect charts at singularities.
Definition: chart.c:1669
unsigned int npCharts
Definition: atlas.h:308
unsigned int * tp
Definition: atlas.h:304
unsigned int FindRightNullVector(Tparameters *pr, unsigned int bID, double **phi, Tatlas *a)
Finds the right null vector that does not belong to the tangent space.
Definition: atlas.c:2137
void DeleteJacobian(TJacobian *j)
Destructor.
Definition: jacobian.c:249
#define CT_MAX_PLANNING_TIME
Maximum time for path planning.
Definition: parameters.h:475
void DifferenceVectorTopology(unsigned int s, unsigned int *tp, double *v1, double *v2, double *v)
Substracts two vectors.
void DeleteBTree(TBTree *t)
Chart tree destructor.
Definition: btree.c:155
#define PLOT_ATLAS_IN_COLORS
Activate/deactivate the colors in the atlas plot.
Definition: atlas.h:39
unsigned int nc
Definition: atlas.c:34
double GetAtlasRadius(Tatlas *a)
Radius used in the charts.
Definition: atlas.c:3311
void NewSingularPointMissed(TAtlasStatistics *ast)
New missed singular point.
Definition: atlas.c:803
unsigned int randomWithDistribution(unsigned int m, double s, double *d)
Random number with a given discrete distribution.
Definition: random.c:86
void PenalizeAtlasHeapElement(TAtlasHeapElement *he)
Penalized the cost stored in a atlas heap element.
Definition: atlas.c:2643
void NewBoundaryAttempt(TAtlasStatistics *ast)
New attempt to generate a point on the boundary.
Definition: atlas.c:719
void InitPlot3d(char *name, boolean axes, int argc, char **arg, Tplot3d *p)
Constructor.
Definition: plot3d.c:41
#define TRUE
TRUE.
Definition: boolean.h:21
double * GetNewtonRHBuffer(TNewton *n)
Buffer to store the Newton right hand.
Definition: algebra.c:1131
double MinCosinusBetweenCharts(Tchart *c1, Tchart *c2)
Computes the angle between the tangent spaces in the charts.
Definition: chart.c:920
double r
Definition: atlas.h:297
double Chart2Manifold(Tparameters *pr, TJacobian *sJ, double *t, unsigned int *tp, double *pInit, double *p, Tchart *c)
Returns the point in the manifold for a given set of parameteres.
Definition: chart.c:1066
void DeleteAtlas(Tatlas *a)
Destructor.
Definition: atlas.c:4561
void Error(const char *s)
General error function.
Definition: error.c:80
#define TOPOLOGY_R
One of the possible topologies.
Definition: defines.h:122
A color.
Definition: color.h:23
boolean MinimizeOnAtlas(Tparameters *pr, char *fname, double *p, TAtlasBase *w, double(*costF)(Tparameters *, boolean, double *, void *), void *costData, Tatlas *a)
Gradient minimization on an manifold.
Definition: atlas.c:3106
void GetJacobianSize(unsigned int *nr, unsigned int *nc, TJacobian *j)
Returns the size of the Jacobian.
Definition: jacobian.c:43
#define ON_CUIKSYSTEM(wcs)
TRUE if the atlas is defined on a cuiksystem.
Definition: wcs.h:139
unsigned int nInCollision
Definition: atlas.h:130
Representation of a bifurcation.
Definition: atlas.h:159
unsigned int mBifurcations
Definition: atlas.h:324
void Delete3dObject(unsigned int nobj, Tplot3d *p)
Deletes a previously created geometric object.
Definition: plot3d.c:152
boolean simpleChart
Definition: atlas.h:298
boolean NeighbouringTriangles(unsigned int *v1, unsigned int *v2)
Determines if two sets of vertices define a neighbouring triangle.
Definition: geom.c:648
#define CT_ATLASGBF_BETA
Cost penalty factor for atlasGBF.
Definition: parameters.h:289
A chart on a manifold.
Definition: chart.h:70
unsigned int GetAtlasAmbientDim(Tatlas *a)
Ambient dimensionality.
Definition: atlas.c:3331
unsigned int nQRSVDError
Definition: atlas.h:127
void DeleteAtlasHeapElement(void *he)
Atlas heap element destructor.
Definition: atlas.c:2648
unsigned int nrJ
Definition: atlas.h:313
double randomDouble()
Returns a random double in the [0,1] interval.
Definition: random.c:33
void AddElement2Heap(unsigned int id, void *e, Theap *heap)
Adds an element to the heap.
Definition: heap.c:294
void InitAtlasHeapElement(unsigned int mID, double c, double beta, TAtlasHeapElement *he)
Constructor of TAtlasHeapElement.
Definition: atlas.c:2600
void NewGoodExtension(TAtlasStatistics *ast)
New time we actually succeeded in creating a new chart.
Definition: atlas.c:773
unsigned int GetAtlasNumCharts(Tatlas *a)
Number of charts in the atlas.
Definition: atlas.c:3931
int NewtonStep(double nullSingularValue, double *x, double *dif, TNewton *n)
One step in a Newton iteration.
boolean DetectBifurcation(Tparameters *pr, unsigned int mID1, unsigned int mID2, Tatlas *a)
Determines if there is a bifurcation between the center of two charts.
Definition: atlas.c:1731
unsigned int nNonRegularPoint
Definition: atlas.h:123
Error and warning functions.
unsigned int nFarFromParent
Definition: atlas.h:129
void DeleteFileName(Tfilename *fn)
Destructor.
Definition: filename.c:205
#define CT_MAX_CHARTS
Maximum number of charts in an atlas.
Definition: parameters.h:490
unsigned int maxCharts
Definition: atlas.h:306
#define PLOT_AS_POLYGONS
Set to 1 to get a nicer plot for 2D manifolds.
Definition: chart.h:50
A 3D plot.
Definition: plot3d.h:54
unsigned int FindRank(double epsilon, unsigned int nr, unsigned int nc, double *mT)
Determines the row-rank of a matrix.
Definition: algebra.c:1084
unsigned int n
Definition: atlas.h:294
double GetChartRadius(Tchart *c)
Returns de range of the chart.
Definition: chart.c:938
#define CT_CUT_X
Limit of domain of the X dimension of 3d plots.
Definition: parameters.h:420
void ReconstructAtlasPath(Tparameters *pr, unsigned int *pred, unsigned int mID, double *goal, unsigned int nv, boolean *systemVars, double *pl, unsigned int *ns, double ***path, Tatlas *a)
Reconstructs the path between the stat/goal configurations.
Definition: atlas.c:1463
double e
Definition: atlas.h:295
unsigned int k
Definition: atlas.h:293
void AddSample2Samples(unsigned int nv, double *sample, unsigned int nvs, boolean *systemVars, unsigned int *ms, unsigned int *ns, double ***path)
Adds a sample to a set of samples.
Definition: samples.c:150
double DotProduct(double *v1, double *v2)
Computes the dot product of two 3d vectors.
Definition: geom.c:643
double GeodesicDistance(Tparameters *pr, unsigned int parentID, unsigned int childID, Tatlas *a)
Approximates the geodesic distance between the centers of two charts.
Definition: atlas.c:1627
void NewFarFromParent(TAtlasStatistics *ast)
New time the point was too far from parent.
Definition: atlas.c:755
void InitBTree(unsigned int id, Tchart *mp, Tbox *ambient, unsigned int *topology, TBTree *t)
Initializes a binary tree of charts.
Definition: btree.c:19
unsigned int InitChart(Tparameters *pr, boolean simple, Tbox *domain, unsigned int *tp, unsigned int m, unsigned int k, double *p, double e, double eCurv, double r, TJacobian *sJ, TAtlasBase *w, Tchart *c)
Constructor.
Definition: chart.c:792
Tbifurcation ** bifurcation
Definition: atlas.h:329
void EvaluateJacobianInVector(double *v, unsigned int nr, unsigned int nc, double *m, TJacobian *j)
Evaluates the Jacobian.
Definition: jacobian.c:97
void AddBorderConstraint(Tparameters *pr, double *t, unsigned int *tp, Tbox *ambient, Tchart *c)
Crops the domain for a given chart.
Definition: chart.c:229
void * GetHeapElement(unsigned int i, Theap *heap)
Returns a pointer to a heap element.
Definition: heap.c:331
CBLAS_INLINE double GeneralDotProduct(unsigned int s, double *v1, double *v2)
Computes the dot product of two general vectors.
Definition: basic_algebra.c:15
CBLAS_INLINE void MatrixVectorProduct(unsigned int r, unsigned int c, double *A, double *b, double *o)
Product of a matrix and a vector.
unsigned int HeapSize(Theap *heap)
Gets the number of elements in a heap.
Definition: heap.c:284
boolean parallel
Definition: atlas.h:301
#define CT_CUT_Z
Limit of domain of the Z dimension of 3d plots.
Definition: parameters.h:444
#define CS_WD_SIMP_INEQUALITIES_HOLD(pr, p, wcs)
Cheks if all inequalities hold.
Definition: wcs.h:207
void NewImpossible(TAtlasStatistics *ast)
New Error when extending from/toward a point.
Definition: atlas.c:779
boolean RandomPointInChart(Tparameters *pr, double scale, unsigned int *tp, double *t, double *p, Tchart *c)
Samples a random point in the area covered by the chart.
Definition: chart.c:1364
void Close3dObjectNoColor(Tplot3d *p)
Closes a composed object without assigning any color.
Definition: plot3d.c:184
boolean LessThanAtlasHeapElement(void *he1, void *he2, void *userData)
Comparison between atlas heap elements.
Definition: atlas.c:2628
unsigned int nSingImpossible
Definition: atlas.h:119
Definitions of constants and macros used in several parts of the cuik library.
Tchart ** charts
Definition: atlas.h:311
void NewChartFromPoint(Tparameters *pr, unsigned int parentID, double *t, Tchart **newChart, Tatlas *a)
Generates a chart from a vertex taken from a parent chart.
Definition: atlas.c:919
void NewRadiousChange(TAtlasStatistics *ast)
New time we had to change the sampling radious to get a new chart.
Definition: atlas.c:767
boolean CollisionChart(Tchart *c)
Identifies collision charts.
Definition: chart.c:1277
boolean RefineSingularPoint(Tparameters *pr, unsigned int bID, Tatlas *a)
Improves the locatin f a singular point.
Definition: atlas.c:1921
void DifferenceVector(unsigned int s, double *v1, double *v2, double *v)
Substracts two vectors.
#define CS_WD_NEWTON_IN_SIMP(pr, p, wcs)
Applies a Newton procedure to move a point towads the manifold.
Definition: wcs.h:488
double cost
Definition: atlas.c:51
unsigned int nBoundaryAttempts
Definition: atlas.h:112
void NewSmallAngleAtBifurcation(TAtlasStatistics *ast)
Small angle between the charts at a bifurcation.
Definition: atlas.c:797
boolean CrossTopologyBorder(unsigned int s, unsigned int *tp, double *v1, double *v2)
Determines if the line between two points crosses the topology boder.
unsigned int nNoSingularEnough
Definition: atlas.h:139
Statistics associated with a solving process.
Definition: statistics.h:28
void SaveSingularCharts(Tparameters *pr, char *fname, boolean saveWithDummies, Tatlas *a)
Stores the centers of the singular charts.
Definition: atlas.c:4095
void NewNoJumpBranch(TAtlasStatistics *ast)
The jump to the other branch failed.
Definition: atlas.c:815
THessian * H
Definition: atlas.h:318
double * GetChartTangentSpace(Tchart *c)
Gets the chart tangent space.
Definition: chart.c:970
double ** path
Definition: atlas.c:38
unsigned int nExtensions
Definition: atlas.h:116
unsigned int nBifurcations
Definition: atlas.h:325
double DistanceOnChart(Tparameters *pr, double *t, unsigned int *tp, TJacobian *sJ, Tchart *c)
Distance between the center of a chart and a point on this chart.
Definition: chart.c:1546
void DeleteAtlasHessian(Tatlas *a)
Removes the Hessian data.
boolean HeapEmpty(Theap *heap)
Checks if a heap is empty.
Definition: heap.c:289
double ChartVolume(Tparameters *pr, boolean collisionFree, unsigned int *tp, TJacobian *sJ, Tchart *c)
Estimate the volume of a chart.
Definition: chart.c:1406
void PostProcessNewCharts(Tparameters *pr, boolean bif, unsigned int parentID, TAtlasStatistics *st, Tatlas *a)
Post-processes the charts added since the last call to this function.
Definition: atlas.c:893
boolean Newton2ManifoldPlane(Tparameters *pr, double *point, double *vector, double *pInit, double *p, Tatlas *a)
Finds a point in the intersection of the manifold and a plane.
Definition: atlas.c:2250
Information of each node (chart) being visited in the A* search.
Definition: atlas.c:50
void DeleteHeap(Theap *heap)
Destructor.
Definition: heap.c:388
void Warning(const char *s)
General warning function.
Definition: error.c:116
A table of parameters.
void DeleteNewton(TNewton *n)
Releases a Newton structure.
double GetAtlasHeapElementCost(TAtlasHeapElement *he)
Gets the cost.
Definition: atlas.c:2623
void CreateFileName(char *path, char *name, char *suffix, char *ext, Tfilename *fn)
Constructor.
Definition: filename.c:22
void GetChartNeighboursFromVertices(Tparameters *pr, unsigned int *nn, unsigned int **cID1, unsigned int **cID2, Tchart *c)
Returns the identifier of neighbouring charts coincident at a vertex.
Definition: chart.c:1704
unsigned int nCores
Definition: atlas.h:300
boolean DetermineChartNeighbours(Tparameters *pr, boolean bif, unsigned int cmID, unsigned int parentID, Tatlas *a)
Determines the neighbours of a chart.
Definition: atlas.c:1547
#define CS_WD_GET_SIMP_JACOBIAN(pr, J, wcs)
Computes the Jacobian of the simplified system.
Definition: wcs.h:474
void NewNoSingularEnough(TAtlasStatistics *ast)
New not singular engoug point.
Definition: atlas.c:809
#define SAMPLING_RADIUS_REDUCTION_FACTOR
Ratio at which the sampling radius is reduced.
Definition: atlas.h:85
boolean FrontierChart(Tchart *c)
Identifies frontier charts.
Definition: chart.c:1282
void SaveChartCenters(Tparameters *pr, char *fname, boolean inside, boolean saveWithDummies, boolean middlePoint, Tatlas *a)
Stores the centers of the charts.
Definition: atlas.c:3987
void DeleteChart(Tchart *c)
Destructor.
Definition: chart.c:2011
Type defining the equations on which the atlas is defined.
Definition: wcs.h:30
boolean FindSingularPoint(Tparameters *pr, unsigned int bID, Tatlas *a)
Searches for a singular point.
Definition: atlas.c:1776
Definition of an atlas on a manifold.
void NewNonRegularPoint(TAtlasStatistics *ast)
New time we could not initialize a new chart.
Definition: atlas.c:737
#define CS_WD_GET_SYSTEM_VARS(sv, wcs)
Gets the system variables.
Definition: wcs.h:238
TAtlasBase * w
Definition: chart.h:72
char * GetFileFullName(Tfilename *fn)
Gets the file full name (paht+name+extension).
Definition: filename.c:151
boolean IntersectCharts(Tparameters *pr, unsigned int *tp, Tbox *ambient, unsigned int id1, Tchart *c1, unsigned int id2, Tchart *c2)
Intersects two local charts.
Definition: chart.c:1270
#define M_2PI
2*Pi.
Definition: defines.h:100
#define SOL_EXT
File extension for solution files.
Definition: filename.h:137
boolean AtlasGBF(Tparameters *pr, double *p, double *time, double *pl, unsigned int *ns, double ***path, Tatlas *a)
Expands the atlas to reach a given point.
Definition: atlas.c:3677
#define CT_REPRESENTATION
Representation.
Definition: parameters.h:215
unsigned int mID2
Definition: atlas.h:162
void NewLargeError(TAtlasStatistics *ast)
New time the point in the tangent space was too far form the manifold.
Definition: atlas.c:731
void SetAtlasTopology(Tparameters *pr, Tatlas *a)
Initializes the topology array in the atlas.
Definition: atlas.c:2652
CBLAS_INLINE void TMatrixVectorProduct(unsigned int r, unsigned int c, double *A, double *b, double *o)
Product of a transposed matrix and a vector.
unsigned int InitTrustedChart(Tparameters *pr, boolean simple, Tbox *domain, unsigned int *tp, unsigned int m, unsigned int k, double *p, double e, double eCurv, double r, TJacobian *sJ, TAtlasBase *w, Tchart *c)
Constructor.
Definition: chart.c:816
#define CS_WD_REGENERATE_ORIGINAL_POINT(pr, p, o, wcs)
Completes an original point from a simplified one.
Definition: wcs.h:279
void NewDecompositionError(TAtlasStatistics *ast)
New time we could not initialize a new chart.
Definition: atlas.c:749
void InitHeap(unsigned int ele_size, void(*Copy)(void *, void *), void(*Delete)(void *), boolean(*LessThan)(void *, void *, void *), void *userData, boolean hasIDs, unsigned int max_ele, Theap *heap)
Constructor.
Definition: heap.c:237
boolean ExpandibleChart(Tchart *c)
Identifies boundary charts.
Definition: chart.c:1292
A atlas on a manifold.
Definition: atlas.h:289
unsigned int AtlasMemSize(Tatlas *a)
Memory used by a given atlas.
Definition: atlas.c:3831
void NewNotInBoundary(TAtlasStatistics *ast)
New time we failed to generate a point on the boundary.
Definition: atlas.c:725
A box.
Definition: box.h:83
void PrintAtlasStatistics(Tparameters *pr, TAtlasStatistics *ast)
Print the information stored in the statistics..
Definition: atlas.c:821
CBLAS_INLINE double ColumnSquaredNorm(unsigned int k, unsigned int r, unsigned int c, double *m)
Computes the squared norm of a column of a matrix.
unsigned int nPenalized
Definition: atlas.h:180
void ChartIsFrontier(Tchart *c)
Marks a chart as a frontier chart.
Definition: chart.c:1287
void InitHessian(TJacobian *j, THessian *h)
Constructor.
Definition: hessian.c:16
#define MEM_DUP(_var, _n, _type)
Duplicates a previously allocated memory space.
Definition: defines.h:414
#define NO_UINT
Used to denote an identifier that has not been initialized.
Definition: defines.h:435
CBLAS_INLINE void SumVectorScale(unsigned int s, double *v1, double w, double *v2, double *v)
Adds two vectors with a scale.
Definition: basic_algebra.c:86
double AtlasVolume(Tparameters *pr, boolean collisionFree, Tatlas *a)
Approximates the volume of the manifold.
Definition: atlas.c:3966
void InitSamples(unsigned int *ms, unsigned int *ns, double ***path)
Initializes a set of samples.
Definition: samples.c:143
void SaveBifurcations(FILE *f, Tatlas *a)
Saves the bifurcation information to a file.
Definition: atlas.c:2523
double cost
Definition: atlas.h:178
double * GetChartCenter(Tchart *c)
Returns the center of the chart.
Definition: chart.c:933
boolean RandomPointOnBoundary(double *t, Tchart *c)
Random point on the boundary of the chart.
Definition: chart.c:1356
Tchart * GetAtlasChart(unsigned int id, Tatlas *a)
Gets one of the charts of the chart.
Definition: atlas.c:3936
TAtlasBase * GetAtlasWorld(Tatlas *a)
Gets the world structure on which the atlas is defined.
Definition: atlas.c:3326
void NewNotInManifold(TAtlasStatistics *ast)
New time we could not initialize a new chart.
Definition: atlas.c:743
void SaveSamples(char *fname, boolean smooth, unsigned int nvs, unsigned int ns, double **path)
Saves a set of samples to a file.
Definition: samples.c:1318
#define CS_WD_EVALUATE_SIMP_EQUATIONS(pr, p, r, wcs)
Evaluates the simplified set of equations.
Definition: wcs.h:176
CBLAS_INLINE void SubMatrixFromMatrix(unsigned int nr1, unsigned int nc1, double *m1, unsigned int nri, unsigned int nci, unsigned int nr, unsigned int nc, double *m)
Defines a submatrix in a matrix.
unsigned int GetAtlasHeapElementID(TAtlasHeapElement *he)
Gets the chart identifier.
Definition: atlas.c:2618
void SaveAtlas(Tparameters *pr, Tfilename *fname, Tatlas *a)
Stores the atlas information on a file.
Definition: atlas.c:3842
void DeleteBox(void *b)
Destructor.
Definition: box.c:1259
unsigned int nRadiousChange
Definition: atlas.h:131
A minimization trace.
Definition: atlas.c:32
void InitAtlas(Tparameters *pr, boolean parallel, boolean simpleChart, unsigned int k, double e, double ce, double r, TAtlasBase *w, Tatlas *a)
Constructor.
Definition: atlas.c:2676
void InitAtlasStatistics(TAtlasStatistics *ast)
Init the atlas built statistics.
Definition: atlas.c:688
#define SOL_WITH_DUMMIES_EXT
File extension for solution files with dummies.
Definition: filename.h:143
boolean SameTriangle(unsigned int *v1, unsigned int *v2)
Identifies triangles formed by the same set of vertices.
Definition: geom.c:662
unsigned int AddTrustedChart2Atlas(Tparameters *pr, double *ps, unsigned int parentID, boolean *singular, Tatlas *a)
Defines a new chart and adds it to the atlas.
Definition: atlas.c:2870
boolean OpenChart(Tchart *c)
Identifies charts not fully sorrounded by other charts.
Definition: chart.c:1300
#define CT_MAX_NEWTON_ITERATIONS
Maximum number of iterations in the Newton-Raphson function.
Definition: parameters.h:311
#define CT_E
Chart error in atlas.
Definition: parameters.h:243
unsigned int ExtractMinElement(void *e, Theap *heap)
Extracts and removes the minimal element of a heap.
Definition: heap.c:356
Hessian of a set of equations.
Definition: hessian.h:24
boolean ExtendAtlasTowardPoint(Tparameters *pr, unsigned int parentID, double *t, boolean collisionStops, TAtlasStatistics *st, Tatlas *a)
Tries to expand the atlas from a chart toward a given point.
Definition: atlas.c:1246
double Manifold2Chart(double *p, unsigned int *tp, double *t, Tchart *c)
Returns the parametrization of a point.
Definition: chart.c:1036
#define MEM_EXPAND(_var, _n, _type)
Expands a previously allocated memory space.
Definition: defines.h:404
boolean CloseCharts(Tparameters *pr, unsigned int *tp, Tchart *c1, Tchart *c2)
Identifies close local charts.
Definition: chart.c:1264
double GetParameter(unsigned int n, Tparameters *p)
Gets the value for a particular parameter.
Definition: parameters.c:93
void DefineChartsAtBifurcation(Tparameters *pr, unsigned int bID, double *v, TAtlasStatistics *ast, Tatlas *a)
Defines two related charts on a bifurcation point.
Definition: atlas.c:2392
unsigned int currentChart
Definition: atlas.h:307
A generic binary heap.
Definition: heap.h:105
void WrongCorner(unsigned int nv, Tchart *c)
Mark a vertex as wrong.
Definition: chart.c:1305
#define CS_WD_REGENERATE_SOLUTION_POINT(pr, p, r, wcs)
Compleates a solution point with the dummy variables.
Definition: wcs.h:417
void NewAtlasExtension(TAtlasStatistics *ast)
New attempt to extend the atlas.
Definition: atlas.c:713
void NewInCollision(TAtlasStatistics *ast)
New time the point was in collision.
Definition: atlas.c:761
#define CT_CUT_Y
Limit of domain of the Y dimension of 3d plots.
Definition: parameters.h:432
unsigned int ChartNumNeighbours(Tchart *c)
Number of neighbours of the chart.
Definition: chart.c:1675
Data about the atlas construction.
Definition: atlas.h:111
unsigned int InitPossiblySingularChart(Tparameters *pr, boolean simple, Tbox *domain, unsigned int *tp, unsigned int m, unsigned int k, double *p, double e, double eCurv, double r, TJacobian *sJ, TAtlasBase *w, Tchart *c)
Constructor.
Definition: chart.c:800
unsigned int ncJ
Definition: atlas.h:314
void DeleteColor(Tcolor *c)
Destructor.
Definition: color.c:93
void Plot3dObjectWithColors(unsigned int nv, unsigned int nf, unsigned int ne, double **v, Tcolor *c, unsigned int *nvf, unsigned int **fv, Tplot3d *p)
Adds a colored polytope to the current object.
Definition: plot3d.c:334
double beta
Definition: atlas.h:179
#define ATLAS_VERBOSE
Vebosity of the atlas operations.
Definition: atlas.h:29
#define CS_WD_IN_COLLISION(f, pr, s, sPrev, wcs)
Checks if a configuration is in collision.
Definition: wcs.h:319
unsigned int InitChartWithTangent(Tparameters *pr, boolean simple, Tbox *domain, unsigned int *tp, unsigned int m, unsigned int k, double *p, double *T, double e, double eCurv, double r, TJacobian *sJ, TAtlasBase *w, Tchart *c)
Constructor.
Definition: chart.c:824
#define INF
Infinite.
Definition: defines.h:70
void PrintMatrix(FILE *f, char *label, unsigned int r, unsigned int c, double *m)
Prints a matrix.
CBLAS_INLINE void SubMatrixFromTMatrix(unsigned int nr1, unsigned int nc1, double *m1, unsigned int nri, unsigned int nci, unsigned int nr, unsigned int nc, double *m)
Defines a submatrix in a matrix.
#define RANDOMNESS
If 0 we avoid any randomness in the cuiksuite behavior.
Definition: defines.h:55
void LoadBifurcations(FILE *f, Tatlas *a)
Loads the bifurcation information from a file.
Definition: atlas.c:2493
#define CT_DELTA
Size of the steps in the path connecting two configurations.
Definition: parameters.h:282
unsigned int nGoodExtension
Definition: atlas.h:133
#define CT_N_DOF
Dimensionality of the solution space for the mechanism at hand.
Definition: parameters.h:318
Auxiliary functions to deal with sets of samples.
double * p
Definition: atlas.h:164
#define CT_DETECT_BIFURCATIONS
TRUE (or 1) if bifurcation must be detected.
Definition: parameters.h:468
unsigned int ChartNeighbourID(unsigned int n, Tchart *c)
Returns the identifier of one of the neighbours of a chart.
Definition: chart.c:1687
boolean InitAtlasFromPoint(Tparameters *pr, boolean parallel, boolean simpleChart, double *p, TAtlasBase *w, Tatlas *a)
Initializes an atlas from a given point.
Definition: atlas.c:2742
Definition of basic randomization functions.
#define CS_WD_INIT_CD(pr, mt, wcs)
Initializes the collision detector.
Definition: wcs.h:294
double GetElapsedTime(Tstatistics *t)
Elapsed time.
Definition: statistics.c:92
void NewColor(double r, double g, double b, Tcolor *c)
Constructor.
Definition: color.c:14
void PlotChart(Tparameters *pr, FILE *fcost, TJacobian *sJ, unsigned int xID, unsigned int yID, unsigned int zID, Tplot3d *p3d, Tchart *c)
Plots a 3d projection of a local chart.
Definition: chart.c:1726
#define INIT_NUM_BIFURCATIONS
Initial number of bifurcations of an atlas.
Definition: atlas.h:66
void SaveSamplesN(char *fname, boolean smooth, unsigned int n, unsigned int nvs, unsigned int ns, double **path)
Saves a set of samples to a file.
Definition: samples.c:1333
void Plot3dObject(unsigned int nv, unsigned int nf, unsigned int ne, double **v, unsigned int *nvf, unsigned int **fv, Tplot3d *p)
Adds a polytope to the current object.
Definition: plot3d.c:276
void TriangulateAtlas(char *fname, int argc, char **arg, Tparameters *pr, FILE *fcost, unsigned int xID, unsigned int yID, unsigned int zID, Tatlas *a)
Pots the triangular mesh defined by the an atlas.
Definition: atlas.c:4314
void LoadChart(FILE *f, TAtlasBase *w, Tchart *c)
Defines a chart from the information on a file.
Definition: chart.c:1932
#define CS_WD_GENERATE_SIMP_INITIAL_BOX(pr, b, wcs)
Computes the global box for the simplified system.
Definition: wcs.h:460
void CopyAtlasHeapElement(void *he1, void *he2)
Copy constructor.
Definition: atlas.c:2610
unsigned int ms
Definition: atlas.c:37
unsigned int GetChartDegree(Tparameters *pr, double *T, TJacobian *sJ, boolean *singular, Tchart *c)
Returns the chart degree.
Definition: chart.c:985
unsigned int AddChart2Atlas(Tparameters *pr, double *ps, unsigned int parentID, boolean *singular, Tatlas *a)
Defines a new chart and adds it to the atlas.
Definition: atlas.c:2836
void ChangeParameter(unsigned int n, double v, Tparameters *p)
Sets the value for a particular parameter.
Definition: parameters.c:164
TAtlasBase * w
Definition: atlas.h:290
void CrossProduct(double *v1, double *v2, double *v3)
Computes the cross product of two 3d vectors.
Definition: geom.c:630
unsigned int nNotInBoundary
Definition: atlas.h:114
unsigned int mID1
Definition: atlas.h:160
#define INIT_NUM_CHARTS
Initial number of charts of an atlas.
Definition: atlas.h:60
unsigned int nNotInManifold
Definition: atlas.h:125
unsigned int StartNew3dObject(Tcolor *c, Tplot3d *p)
Start a composed object.
Definition: plot3d.c:157
void PrintTMatrix(FILE *f, char *label, unsigned int r, unsigned int c, double *m)
Prints a transposed matrix.
void DeleteStatistics(Tstatistics *t)
Destructor.
Definition: statistics.c:274
boolean PathInChart(Tparameters *pr, double *t, unsigned int *tp, TJacobian *sJ, unsigned int nvs, boolean *systemVars, unsigned int *ms, double *pl, unsigned int *ns, double ***path, Tchart *c)
Defines the path to a point in the chart.
Definition: chart.c:1477
#define DIVERGED
One of the possible outputs of the Newton iteration.
Definition: cuiksystem.h:111
void CostColor(double cost, double minCost, Tcolor *c)
Definees a color in function of a cost.
Definition: color.c:40
void DeleteBifurcations(Tatlas *a)
Deletes the bifurcation information.
Definition: atlas.c:2583
void FreeHessianEvaluation(double ***m, THessian *h)
Release space for the Hessian evaluation.
Definition: hessian.c:64
#define CT_CE
Chart error in atlas.
Definition: parameters.h:250
boolean SingularChart(Tchart *c)
Identify charts defined on singularities.
Definition: chart.c:980
double * GetNewtonMatrixBuffer(TNewton *n)
Buffer to store the Newton matrix.
Definition: algebra.c:1126
double heuristic
Definition: atlas.c:52
#define CS_WD_GET_SIMP_TOPOLOGY(pr, tp, wcs)
Gets the simplified variable topology.
Definition: wcs.h:401
void PlotAtlas(char *fname, int argc, char **arg, Tparameters *pr, FILE *fcost, unsigned int xID, unsigned int yID, unsigned int zID, Tatlas *a)
Pots a projection of an atlas.
Definition: atlas.c:4151
void Close3dObject(Tplot3d *p)
Closes a composed object.
Definition: plot3d.c:171
void InitNewton(unsigned int nr, unsigned int nc, TNewton *n)
Defines a Newton structure.
void BuildAtlasFromPoint(Tparameters *pr, double *p, boolean simpleChart, TAtlasBase *w, Tatlas *a)
Defines an atlas from a given point.
Definition: atlas.c:2919
unsigned int npBifurcations
Definition: atlas.h:326
unsigned int nSPMissed
Definition: atlas.h:138
unsigned int InitSingularChart(Tparameters *pr, boolean simple, Tbox *domain, unsigned int *tp, unsigned int m, unsigned int k, double *p, double e, double eCurv, double r, TJacobian *sJ, TAtlasBase *w, Tchart *c)
Constructor.
Definition: chart.c:808
void ClosePlot3d(boolean quit, double average_x, double average_y, double average_z, Tplot3d *p)
Destructor.
Definition: plot3d.c:473
double GetAtlasErrorCurv(Tatlas *a)
Maximum curvature error for all the charts.
Definition: atlas.c:3321
unsigned int nBifurcations
Definition: atlas.h:135
#define TOPOLOGY_S
One of the possible topologies.
Definition: defines.h:139
boolean PointInBoxTopology(boolean *used, boolean update, unsigned int n, double *v, double tol, unsigned int *tp, Tbox *b)
Checks if a point is included in a(sub-) box.
Definition: box.c:350
void PlotBifurcations(Tparameters *pr, Tplot3d *p3d, unsigned int xID, unsigned int yID, unsigned int zID, Tatlas *a)
Plots the bifurcation information.
Definition: atlas.c:2546
CBLAS_INLINE void GetColumn(unsigned int k, unsigned int r, unsigned int c, double *m, double *v)
Gets a column from a matrix.
#define CS_WD_ORIGINAL_IN_COLLISION(pr, o, oPrev, wcs)
Checks if a configuration is in collision.
Definition: wcs.h:348
unsigned int nNoJumpBranch
Definition: atlas.h:140