Example #1
0
// A driver() function 
// driver() is required in all FEM programs
extern "C" void
driver(void)
{
  int nnodes,nelems,nelems2,ignored;
  int i, myId=FEM_My_partition();
  myGlobals g;
  FEM_Register(&g,(FEM_PupFn)pup_myGlobals);
  
  _registerFEMMeshModify();

  printf("partition %d is in driver\n", myId);

  int mesh=FEM_Mesh_default_read(); // Tell framework we are reading data from the mesh
  
  // Get node data
  nnodes=FEM_Mesh_get_length(mesh,FEM_NODE); // Get number of nodes
  g.nnodes=nnodes;
  g.coord=new vector3d[nnodes];
  // Get node positions
  FEM_Mesh_data(mesh, FEM_NODE, FEM_DATA+0, (double*)g.coord, 0, nnodes, FEM_DOUBLE, 3);

  // Get element data
  nelems=FEM_Mesh_get_length(mesh,FEM_ELEM+0); // Get number of elements
  g.nelems=nelems;
  g.conn=new connRec[nelems];
  // Get connectivity for elements
  FEM_Mesh_data(mesh, FEM_ELEM+0, FEM_CONN, (int *)g.conn, 0, nelems, FEM_INDEX_0, 4);


  double* tridata =new double[nelems];
  FEM_Mesh_data(mesh, FEM_ELEM+0, FEM_DATA, (int *)tridata, 0, nelems, FEM_DOUBLE, 1);  

  int nelemsghost=FEM_Mesh_get_length(mesh,FEM_ELEM+0+FEM_GHOST); 
  double* trighostdata =new double[nelemsghost];
  FEM_Mesh_data(mesh, FEM_ELEM+0+FEM_GHOST, FEM_DATA, (int *)trighostdata, 0, nelemsghost, FEM_DOUBLE, 1);
  int nnodesghost=FEM_Mesh_get_length(mesh,FEM_NODE+0+FEM_GHOST);
  double* nodeghostdata =new double[3*nnodesghost];
  FEM_Mesh_data(mesh, FEM_NODE+0+FEM_GHOST, FEM_DATA, (int *)nodeghostdata, 0, nnodesghost, FEM_DOUBLE, 3);


  {
    const int triangleFaces[12] = {0,1,2,1,2,3,2,3,0,0,3,1};
    FEM_Add_elem2face_tuples(mesh, 0, 3, 4, triangleFaces);
    FEM_Mesh_create_elem_elem_adjacency(mesh);
    FEM_Mesh_allocate_valid_attr(mesh, FEM_ELEM+0);
    FEM_Mesh_allocate_valid_attr(mesh, FEM_NODE);
    FEM_Mesh_create_node_elem_adjacency(mesh);
    FEM_Mesh_create_node_node_adjacency(mesh);
    
    int netIndex = 0;
    publish_data_netfem(netIndex,g); netIndex++;
#ifdef SUMMARY_ON
    FEM_Print_Mesh_Summary(mesh);
#endif
    int rank = 0;
    MPI_Comm comm = MPI_COMM_WORLD;
    MPI_Comm_rank(comm,&rank);
    
    MPI_Barrier(comm);
    FEM_REF_INIT(mesh);
    
    FEM_Mesh *meshP = FEM_Mesh_lookup(FEM_Mesh_default_read(),"driver");
    FEM_AdaptL *ada = meshP->getfmMM()->getfmAdaptL();
    int ret_op = -1;
    
    FEM_Adapt_Algs *adaptAlgs= meshP->getfmMM()->getfmAdaptAlgs();
    adaptAlgs->FEM_Adapt_Algs_Init(FEM_DATA+0,FEM_DATA+4);
    FEM_Interpolate *interp = meshP->getfmMM()->getfmInp();
    //interp->FEM_SetInterpolateNodeEdgeFnPtr(interpolate);
    
    MPI_Barrier(comm);
    
    //CkPrintf("Shadow arrays have been bound\n");
    /*
#ifdef SUMMARY_ON
    FEM_Print_Mesh_Summary(mesh);
#endif
    
    CkPrintf("Marking 5 nodes and one element as invalid\n");
    FEM_set_entity_invalid(mesh, FEM_NODE, 5);
    FEM_set_entity_invalid(mesh, FEM_NODE, 6);
    FEM_set_entity_invalid(mesh, FEM_NODE, 7);
    FEM_set_entity_invalid(mesh, FEM_NODE, 8);
    FEM_set_entity_invalid(mesh, FEM_NODE, 9);	
    FEM_set_entity_invalid(mesh, FEM_ELEM, 9);
    
#ifdef SUMMARY_ON
    FEM_Print_Mesh_Summary(mesh);
#endif
    
    CkPrintf("Marking 5 nodes and one element as valid again\n");
    FEM_set_entity_valid(mesh, FEM_NODE, 5);
    FEM_set_entity_valid(mesh, FEM_NODE, 6);
    FEM_set_entity_valid(mesh, FEM_NODE, 7);
    FEM_set_entity_valid(mesh, FEM_NODE, 8);
    FEM_set_entity_valid(mesh, FEM_NODE, 9);	
    FEM_set_entity_valid(mesh, FEM_ELEM, 9);
    */
#ifdef SUMMARY_ON
    FEM_Print_Mesh_Summary(mesh);
#endif
    
    int adjs[4];
    int elemid;
	if(rank == 0) {
	  adjs[0] = 0;
	  adjs[1] = 1;
	  adjs[2] = 2;
	  adjs[3] = 3;
	  elemid = 0;
	} else if(rank == 1) {
	  adjs[0] = 19;
	  adjs[1] = 5;
	  adjs[2] = 7;
	  adjs[3] = 21;
	  elemid = 21;
	} else if(rank == 2) {
	  adjs[0] = 8;
	  adjs[1] = 11;
	  adjs[2] = 6;
	  adjs[3] = 21;
	  elemid = 7;
	} else {
	  adjs[0] = 0;
	  adjs[1] = 1;
	  adjs[2] = 2;
	  adjs[3] = 3;
	  elemid = 0;
	}
	int newel1 = 0;
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
	FEM_Print_n2e(mesh,adjs[0]);
	FEM_Print_n2e(mesh,adjs[1]);
	FEM_Print_n2e(mesh,adjs[2]);
	FEM_Print_n2e(mesh,adjs[3]);
	FEM_Print_n2n(mesh,adjs[0]);
	FEM_Print_n2n(mesh,adjs[1]);
	FEM_Print_n2n(mesh,adjs[2]);
	FEM_Print_n2n(mesh,adjs[3]);
	FEM_Print_e2n(mesh,elemid);
	FEM_Print_e2e(mesh,elemid);
#endif

	//FEM_Modify_Lock(mesh, adjs, 3, adjs, 0);
	if(rank == 0) {
	  FEM_remove_element(mesh, elemid, 0, 1);
	}
	//FEM_Modify_Unlock(mesh);
	MPI_Barrier(comm);
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif

	//FEM_Modify_Lock(mesh, adjs, 3, adjs, 0);
	if(rank == 0) {
	  newel1 = FEM_add_element(mesh,adjs,4,0,0);
	  CkPrintf("New Element\n");
	}
	//FEM_Modify_Unlock(mesh);
	publish_data_netfem(netIndex,g); netIndex++;
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
	FEM_Print_n2e(mesh,adjs[0]);
	FEM_Print_n2e(mesh,adjs[1]);
	FEM_Print_n2e(mesh,adjs[2]);
	FEM_Print_n2e(mesh,adjs[3]);
	FEM_Print_n2n(mesh,adjs[0]);
	FEM_Print_n2n(mesh,adjs[1]);
	FEM_Print_n2n(mesh,adjs[2]);
	FEM_Print_n2n(mesh,adjs[3]);
	FEM_Print_e2n(mesh,newel1);
	FEM_Print_e2e(mesh,newel1);
#endif
	/*
	if(rank==0){
	  FEM_Print_Mesh_Summary(mesh);
	  CkPrintf("%d: Removing element \n", rank);
	  
	  int nelemsghost   =FEM_Mesh_get_length(mesh,FEM_ELEM+0+FEM_GHOST); 
	  int numvalidghost =FEM_count_valid(mesh,FEM_ELEM+0+FEM_GHOST);
	  CkPrintf("nelemsghost=%d numvalidghost=%d\n", nelemsghost, numvalidghost);
	
	  for(int i=1;i<20;i++){
		if(FEM_is_valid(mesh, FEM_ELEM+FEM_GHOST, i)){
		  double data[1];
		  FEM_Mesh_data(mesh, FEM_ELEM+FEM_GHOST, FEM_DATA, (int *)data, i, 1, FEM_DOUBLE, 1);  

		  CkPrintf("%d: Eating ghost element %d with value %f\n", rank, i, data[1]);
		  int conn[3];
		  
		  FEM_Mesh_data(mesh, FEM_ELEM+FEM_GHOST, FEM_CONN, (int *)conn, i, 1, FEM_INDEX_0, 3);
		  CkPrintf("conn for element is: %d %d %d\n", conn[0], conn[1], conn[2]);
		  FEM_Modify_Lock(mesh, conn, 3, conn, 0);
		  FEM_remove_element(mesh, FEM_From_ghost_index(i), 0, 1);
		  FEM_Modify_Unlock(mesh);

		  MPI_Barrier(comm);
		  FEM_Print_Mesh_Summary(mesh);

		  FEM_Modify_Lock(mesh, conn, 3, conn, 0);
		  FEM_add_element(mesh, conn, 3, 0, rank); // add locally
		  FEM_Modify_Unlock(mesh);
		  CkPrintf("New conn for element is: %d %d %d\n", conn[0], conn[1], conn[2]);
		  
		  publish_data_netfem(netIndex,g); netIndex++;
		  FEM_Print_Mesh_Summary(mesh);
		}
		else{
		  //  CkPrintf("invalid element %d\n", i);
		}
	  }
	}
	else {
	  CkPrintf("Rank %d\n", rank);
	  for(int i=1;i<20;i++){
	    MPI_Barrier(comm);
	    FEM_Print_Mesh_Summary(mesh);

	    publish_data_netfem(netIndex,g); netIndex++;
	    FEM_Print_Mesh_Summary(mesh);
	  }
	}
	
	publish_data_netfem(netIndex,g); netIndex++;
	*/	

	/*
	CkPrintf("Starting Local edge flips on individual chunks\n");
	int flip[4];
	if(rank == 0) {
	  flip[0] = 1;
	  flip[1] = 2;
	  flip[2] = 0;
	  flip[3] = 3;
	}
	else if(rank == 1) {
	  flip[0] = 1;
	  flip[1] = 2;
	  flip[2] = 0;
	  flip[3] = 4;
	}
	else if(rank == 2) {
	  flip[0] = 13;
	  flip[1] = 14;
	  flip[2] = 15;
	  flip[3] = 7;
	}
	else {
	  flip[0] = 0;
	  flip[1] = 1;
	  flip[2] = 2;
	  flip[3] = 3;
	}
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
	ret_op = ada->edge_flip(flip[0],flip[1]);
	publish_data_netfem(netIndex,g); netIndex++;
	ret_op = ada->edge_flip(flip[2],flip[3]);
	publish_data_netfem(netIndex,g); netIndex++;
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
	
	CkPrintf("Starting shared edge flips on individual chunks\n");
	int sflip[4];
	if(rank == 0) {
	  sflip[0] = 19;
	  sflip[1] = 18;
	  sflip[2] = 1;
	  sflip[3] = -4;
	}
	else if(rank == 1) {
	  sflip[0] = 5;
	  sflip[1] = 6;
	  sflip[2] = 7;
	  sflip[3] = -5;
	}
	else if(rank == 2) {
	  sflip[0] = 11;
	  sflip[1] = 2;
	  sflip[2] = 0;
	  sflip[3] = -2;
	}
	else {
	  sflip[0] = 0;
	  sflip[1] = 1;
	  sflip[2] = 2;
	  sflip[3] = 3;
	}
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
	ret_op = ada->edge_flip(sflip[0],sflip[1]);
	publish_data_netfem(netIndex,g); netIndex++;
	if(ret_op > 0) {
	  if(sflip[2]<0) sflip[2] = ret_op;
	  else if(sflip[3]<0) sflip[3] = ret_op;
	}
	ret_op = ada->edge_flip(sflip[2],sflip[3]);
	publish_data_netfem(netIndex,g); netIndex++;
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
	
	CkPrintf("Starting Local edge bisect on individual chunks\n");
	int bisect[2];
	if(rank == 0) {
	  bisect[0] = 16;
	  bisect[1] = 21;
	}
	else if(rank == 1) {
	  bisect[0] = 5;
	  bisect[1] = 6;
	}
	else if(rank == 2) {
	  bisect[0] = 8;
	  bisect[1] = 11;
	}
	else {
	  bisect[0] = 0;
	  bisect[1] = 1;
	}
	if(rank==2) ret_op = ada->edge_bisect(bisect[0],bisect[1]);
	publish_data_netfem(netIndex,g); netIndex++;
	adaptAlgs->tests();
	MPI_Barrier(comm);
	
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
	
	CkPrintf("Starting Local vertex remove on individual chunks\n");
	int vr[2];
	if(rank == 0) {
	  vr[0] = ret_op;
	  vr[1] = 6;
	}
	else if(rank == 1) {
	  vr[0] = ret_op;
	  vr[1] = 13;
	}
	else if(rank == 2) {
	  vr[0] = ret_op;
	  vr[1] = 21;
	}
	else {
	  vr[0] = ret_op;
	  vr[1] = 1;
	}
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
	ret_op = ada->vertex_remove(vr[0],vr[1]);
	publish_data_netfem(netIndex,g); netIndex++;
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
	
	
	CkPrintf("Starting shared edge bisect on individual chunks\n");
	int sbisect[2];
	if(rank == 0) {
	  sbisect[0] = 1;//4;//21;
	  sbisect[1] = 19;//20;
	}
	else if(rank == 1) {
	  sbisect[0] = 0;
	  sbisect[1] = 21;
	}
	else if(rank == 2) {
	  sbisect[0] = 20;//9;//3;
	  sbisect[1] = 8;//2;//19;
	}
	else {
	  sbisect[0] = 0;
	  sbisect[1] = 1;
	}
	
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
	ret_op = ada->edge_bisect(sbisect[0],sbisect[1]);
	publish_data_netfem(netIndex,g); netIndex++;
	CkPrintf("Starting shared vertex remove on individual chunks\n");

	int svr[2];
	if(rank == 0) {
	  svr[0] = ret_op;
	  svr[1] = 19;
	}
	else if(rank == 1) {
	  svr[0] = ret_op;
	  svr[1] = 21;
	}
	else if(rank == 2) {
	  svr[0] = ret_op;
	  svr[1] = 20;
	}
	else {
	  svr[0] = ret_op;
	  svr[1] = 1;
	}
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
	ret_op = ada->vertex_remove(svr[0],svr[1]);
	publish_data_netfem(netIndex,g); netIndex++;
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif

	CkPrintf("Starting Local edge contract on individual chunks\n");
	int contract[2];
	if(rank == 0) {
	  contract[1] = 16;
	  contract[0] = 21;
	}
	else if(rank == 1) {
	  contract[0] = 5;
	  contract[1] = 6;
	}
	else if(rank == 2) {
	  contract[0] = 19;
	  contract[1] = 17;
	}
	else {
	  contract[0] = 0;
	  contract[1] = 1;
	}
	
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
	if(rank==0) ret_op = ada->edge_contraction(contract[0],contract[1]);
	publish_data_netfem(netIndex,g); netIndex++;

	//CkPrintf("Starting Local vertex split on individual chunks\n");
	/*
	int vs[3];
	if(rank == 0) {
	  vs[0] = ret_op;
	  vs[1] = 9;
	  vs[2] = 13;
	}
	else if(rank == 1) {
	  vs[0] = ret_op;
	  vs[1] = 8;
	  vs[2] = 7;
	}
	else if(rank == 2) {
	  vs[0] = ret_op;
	  vs[1] = 14;
	  vs[2] = 23;
	}
	else {
	  vs[0] = ret_op;
	  vs[1] = 2;
	  vs[2] = 3;
	}
#ifdef SUMMARY_ON
	//FEM_Print_Mesh_Summary(mesh);
#endif
	//ret_op = ada->vertex_split(vs[0],vs[1],vs[2]);
	//publish_data_netfem(netIndex,g); netIndex++;
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
	*/
	/*
	CkPrintf("Starting shared edge contract on individual chunks\n");
	int scontract[2];
	if(rank == 0) {
	  scontract[0] = 9;
	  scontract[1] = 10;
	}
	else if(rank == 1) {
	  scontract[0] = 5;
	  scontract[1] = 6;
	}
	else if(rank == 2) {
	  scontract[0] = 11;
	  scontract[1] = 2;
	}
	else {
	  scontract[0] = 0;
	  scontract[1] = 1;
	}
	
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
	ret_op = ada->edge_contraction(scontract[0],scontract[1]);
	publish_data_netfem(netIndex,g); netIndex++;
	/*
	//CkPrintf("Starting shared vertex split on individual chunks\n");
	int svs[3];
	if(rank == 0) {
	  svs[0] = ret_op;
	  svs[1] = 1;
	  svs[2] = -6;
	}
	else if(rank == 1) {
	  svs[0] = ret_op;
	  svs[1] = 7;
	  svs[2] = 7;
	}
	else if(rank == 2) {
	  svs[0] = ret_op;
	  svs[1] = 0;
	  svs[2] = -2;
	}
	else {
	  svs[0] = ret_op;
	  svs[1] = 2;
	  svs[2] = 3;
	}
#ifdef SUMMARY_ON
	//FEM_Print_Mesh_Summary(mesh);
#endif
	//ret_op = ada->vertex_split(svs[0],svs[1],svs[2]);
	//publish_data_netfem(netIndex,g); netIndex++;
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
	*/

	/*
	CkPrintf("Starting LEB on individual chunks\n");
	int *leb_elem = (int*)malloc(1*sizeof(int));
	if(rank==0) {
	  leb_elem[0] = 2;
	}
	else if(rank==1) {
	  leb_elem[0] = 13; //4;
	}
	else if(rank==2) {
	  leb_elem[0] = 20; //26;
	}
	else if (rank == 3){
	  leb_elem[0] = 14;
	}
	else {
	  leb_elem[0] = 0;
	}

	adaptAlgs->refine_element_leb(leb_elem[0]);
	publish_data_netfem(netIndex,g); netIndex++;
	*/
	/*
	  int nEle;
	  //for(int tstep = 0; tstep < 2; tstep++) {
	  nEle = FEM_Mesh_get_length(mesh, FEM_ELEM);	
	  for (int i=0; i<nEle; i++)
	  if (FEM_is_valid(mesh, FEM_ELEM, i))
	  adaptAlgs->refine_element_leb(i);
	  publish_data_netfem(netIndex,g); netIndex++;
	  FEM_Print_Mesh_Summary(mesh);
	  //}
	  */

      
      double targetArea = 0.00004;
      
      for(int tstep = 0; tstep < 0; tstep++) {
	adaptAlgs->simple_refine(targetArea);
	publish_data_netfem(netIndex,g); netIndex++;
	adaptAlgs->tests();
	MPI_Barrier(comm);
	
	//int *nodes = new int[g.nnodes];
	//for (int i=0; i<g.nnodes; i++) nodes[i]=i;	
	//FEM_mesh_smooth(mesh, nodes, g.nnodes, FEM_DATA+0);
	//publish_data_netfem(netIndex,g); netIndex++;
	//delete [] nodes;

#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
	adaptAlgs->simple_coarsen(targetArea);
	publish_data_netfem(netIndex,g); netIndex++;
	adaptAlgs->tests();
	MPI_Barrier(comm);
	
	//int *nodes = new int[g.nnodes];
	//for (int i=0; i<g.nnodes; i++) nodes[i]=i;
	//FEM_mesh_smooth(mesh, nodes, g.nnodes, FEM_DATA+0);
	//publish_data_netfem(netIndex,g); netIndex++;
	//delete [] nodes;

#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
      }

      targetArea = 0.00004;
      
      for(int tstep = 0; tstep < 0; tstep++) {
	adaptAlgs->simple_refine(targetArea);
	publish_data_netfem(netIndex,g); netIndex++;
	adaptAlgs->tests();
	MPI_Barrier(comm);
	
	//int *nodes = new int[g.nnodes];
	//for (int i=0; i<g.nnodes; i++) nodes[i]=i;	
	//FEM_mesh_smooth(mesh, nodes, g.nnodes, FEM_DATA+0);
	//publish_data_netfem(netIndex,g); netIndex++;
	//delete [] nodes;


	targetArea *= 0.5;
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
      }
      targetArea /= 0.4;
      
      for(int tstep = 0; tstep < 0; tstep++) {
	adaptAlgs->simple_coarsen(targetArea);
	publish_data_netfem(netIndex,g); netIndex++;
	adaptAlgs->tests();
	MPI_Barrier(comm);
	
	//int *nodes = new int[g.nnodes];
	//for (int i=0; i<g.nnodes; i++) nodes[i]=i;
	//FEM_mesh_smooth(mesh, nodes, g.nnodes, FEM_DATA+0);
	//publish_data_netfem(netIndex,g); netIndex++;
	//delete [] nodes;

	targetArea *= 1.5;
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
      }

      //wave propagation on a bar
      targetArea = 0.00004;
      double xmin = 0.00;
      double xmax = 0.1;
      double ymin = 0.00;
      double ymax = 0.01;
      for(int tstep = 0; tstep < 0; tstep++) {
	targetArea = 0.000002;
	adaptAlgs->simple_refine(targetArea, xmin, ymin, xmax, ymax);
	publish_data_netfem(netIndex,g); netIndex++;
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
	targetArea = 0.0000014;
	adaptAlgs->simple_coarsen(targetArea, xmin, ymin, xmax, ymax);
	publish_data_netfem(netIndex,g); netIndex++;
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
	ymin += 0.01;
	ymax += 0.01;
      }

      //crack propagation on a block
      targetArea = 0.00004;
      xmin = 0.00;
      xmax = 0.2;
      double xcrackmin = 0.09;
      double xcrackmax = 0.10;
      ymin = 0.00;
      ymax = 0.02;
      for(int tstep = 0; tstep < 0; tstep++) {
	targetArea = 0.000025;
	adaptAlgs->simple_refine(targetArea, xmin, ymin, xmax, ymax);
	publish_data_netfem(netIndex,g); netIndex++;
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
	targetArea = 0.00005;
	adaptAlgs->simple_coarsen(targetArea, xmin, ymin, xmax, ymax);
	//publish_data_netfem(netIndex,g); netIndex++;
#ifdef SUMMARY_ON
	FEM_Print_Mesh_Summary(mesh);
#endif
	/*if(tstep > 2) {
	  targetArea = 0.000025;
	  adaptAlgs->simple_refine(targetArea, xcrackmin, ymin, xcrackmax, ymax);
	  //publish_data_netfem(netIndex,g); netIndex++;
#ifdef SUMMARY_ON
	  FEM_Print_Mesh_Summary(mesh);
#endif
	  xcrackmin -= 0.004;
	  xcrackmax += 0.004;
	}
	*/

	ymin += 0.02;
	ymax += 0.02;
      }


      CkPrintf("chunk %d Waiting for Synchronization\n",rank);
      MPI_Barrier(comm);
      CkPrintf("Synchronized\n");
#ifdef SUMMARY_ON
      FEM_Print_Mesh_Summary(mesh);
#endif
      publish_data_netfem(netIndex,g); netIndex++;
      
      CkExit();
  }
  
}
Example #2
0
int FEM_Adapt::vertex_split_help(int n, int n1, int n2, int e1, int e3)
{
  int e1_n = find_local_node_index(e1, n);
  int e1_n1 = find_local_node_index(e1, n1);
  int e2 = theMesh->e2e_getNbr(e1, get_edge_index(e1_n, e1_n1));
  int e3_n = find_local_node_index(e3, n);
  int e3_n2 = find_local_node_index(e3, n2);
  int e4 = theMesh->e2e_getNbr(e3, get_edge_index(e3_n, e3_n2));
  if (!check_orientation(e1, e3, n, n1, n2)) {
    int tmp = e3;
    e3 = e4;
    e4 = tmp;
    e3_n = find_local_node_index(e3, n);
    e3_n2 = find_local_node_index(e3, n2);
  }

  int locknodes[4];
  locknodes[0] = n1;
  locknodes[1] = n;
  locknodes[2] = n2;
  locknodes[3] = -1;
  int lockelems[6];
  lockelems[0] = e1;
  lockelems[1] = e2;
  lockelems[2] = e3;
  lockelems[3] = e4;
  lockelems[4] = -1;
  lockelems[5] = -1;
  int elemConn[3];

  //FEM_Modify_Lock(theMesh, locknodes, 4, lockelems, 6);
#ifdef DEBUG_1
  CkPrintf("Vertex Split, %d-%d-%d on chunk %d\n", n1, n, n2, theMod->getfmUtil()->getIdx());
#endif
  int adjnodes[2];
  adjnodes[0] = n; //looks like it will never be shared, since according to later code, all n1, n & n2 should be local.. appears to be not correct
  //the new node will be shared to wahtever the old node was shared to, we'll do this later
  int *chunks = NULL;
  int numChunks = 0;
  int np = FEM_add_node(theMesh,adjnodes,1,chunks,numChunks,0);
  locknodes[3] = np;

  int current, next, nt, nl, eknp, eknt, eknl;
  // traverse elements on one side of n starting with e2
  current = e2;
  nt = n1;
  while ((current != e3) && (current != -1)) { 
    eknp = find_local_node_index(current, n);
    eknt = find_local_node_index(current, nt);
    eknl = 3 - eknp - eknt;
    next = theMesh->e2e_getNbr(current, get_edge_index(eknp, eknl));
    nl = theMesh->e2n_getNode(current, eknl);
    FEM_remove_element(theMesh, current, 0);
    // add nl, nt, np
    elemConn[eknp] = np; elemConn[eknt] = nt; elemConn[eknl] = nl;
    int newelem = FEM_add_element(theMesh, elemConn, 3, 0);
    nt = nl;
    current = next;
  }
  if (current == -1) { // didn't make it all the way around
    // traverse elements on one side of n starting with e4
    current = e4;
    nt = n2;
    while ((current != e1) && (current != -1)) {
      eknp = find_local_node_index(current, n);
      eknt = find_local_node_index(current, nt);
      eknl = 3 - eknp - eknt;
      next = theMesh->e2e_getNbr(current, get_edge_index(eknp, eknl));
      nl = theMesh->e2n_getNode(current, eknl);
      FEM_remove_element(theMesh, current, 0);
      // add nl, nt, np
      elemConn[eknp] = np; elemConn[eknt] = nt; elemConn[eknl] = nl;
      int newelem = FEM_add_element(theMesh, elemConn, 3, 0);
      nt = nl;
      current = next;
    }
  }

  // add n, n1, np
  elemConn[e1_n] = n; elemConn[e1_n1] = n1; elemConn[3 - e1_n - e1_n1] = np;
  lockelems[4] = FEM_add_element(theMesh, elemConn, 3, 0);
  // add n, n2, np
  elemConn[e3_n] = n; elemConn[e3_n2] = n2; elemConn[3 - e3_n - e3_n2] = np;
  lockelems[5] = FEM_add_element(theMesh, elemConn, 3, 0);

  return np;
}
Example #3
0
/** Given edge e:(n1, n2), remove the two elements (n1,n2,n3) and 
   (n2,n1,n4) adjacent to e, and bisect e by adding node 
   n5. Add elements (n1,n5,n3), (n5,n2,n3), (n5,n1,n4) and (n2,n5,n4); 
   returns new node n5.

       n3                 n3
        o                  o
       / \                /|\
      /   \              / | \
     /     \            /  |  \
    /       \          /   |n5 \
n1 o---------o n2  n1 o----o----o n2
    \       /          \   |   / 
     \     /            \  |  /
      \   /              \ | /
       \ /                \|/
        o                  o
       n4                 n4
*/
int FEM_Adapt::edge_bisect_help(int e1, int e2, int n1, int n2, int e1_n1, 
				int e1_n2, int e1_n3, int e2_n1, int e2_n2, 
				int e2_n3, int n3, int n4)
{
  int n5;
  int numNodes = 4;
  int numElems = 2;
  int numNodesNew = 5;
  int numElemsNew = 4;
  int locknodes[5];
  int lockelems[4];
  int elemConn[3];

  locknodes[0] = n1;
  locknodes[1] = n2;
  locknodes[2] = n3;
  locknodes[3] = n4;
  locknodes[4] = -1;
  lockelems[0] = e1;
  lockelems[1] = e2;
  lockelems[2] = -1;
  lockelems[3] = -1;

  //FEM_Modify_Lock(theMesh, locknodes, numNodes, lockelems, numElems);

  int e1chunk=-1, e2chunk=-1, e3chunk=-1, e4chunk=-1, n5chunk=-1;
  int index = theMod->getIdx();

#ifdef DEBUG_1
  CkPrintf("Bisect edge %d->%d on chunk %d\n", n1, n2, theMod->getfmUtil()->getIdx());
#endif
  //verify quality
  bool flag = theMod->fmAdaptAlgs->controlQualityR(n1,n2,n3,n4);
  if(flag) return -1;

  //add node
  if(e1==-1) e1chunk=-1;
  else if(e1>=0) e1chunk=index;
  else {
    int ghostid = FEM_To_ghost_index(e1);
    const IDXL_Rec *irec = theMesh->elem[0].ghost->ghostRecv.getRec(ghostid);
    CkAssert(irec->getShared()==1);
    e1chunk = irec->getChk(0);
  }
  if(e2==-1) e2chunk=-1;
  else if(e2>=0) e2chunk=index;
  else {
    int ghostid = FEM_To_ghost_index(e2);
    const IDXL_Rec *irec = theMesh->elem[0].ghost->ghostRecv.getRec(ghostid);
    CkAssert(irec->getShared()==1);
    e2chunk = irec->getChk(0);
  }
  int adjnodes[2];
  adjnodes[0] = n1;
  adjnodes[1] = n2;
  int *chunks;
  int numChunks=0;
  int forceshared = 0;
  if(e1chunk==e2chunk || (e1chunk==-1 || e2chunk==-1)) {
    forceshared = -1;
    numChunks = 1;
    chunks = new int[1];
    if(e1chunk!=-1) chunks[0] = e1chunk;
    else chunks[0] = e2chunk;
  }
  else {
    numChunks = 2;
    chunks = new int[2];
    chunks[0] = e1chunk;
    chunks[1] = e2chunk;
  }
  n5 = FEM_add_node(theMesh,adjnodes,2,chunks,numChunks,forceshared);
  delete[] chunks;
  //lock this node immediately
  FEM_Modify_LockN(theMesh, n5, 0);

  //remove elements
  e1chunk = FEM_remove_element(theMesh, e1, 0); 
  e2chunk = FEM_remove_element(theMesh, e2, 0);  // assumes intelligent behavior when no e2 exists

  // hmm... if e2 is a ghost and we remove it and create all the new elements
  // locally, then we don't really need to add a *shared* node
  //but we are not moving chunk boundaries for bisect
  if(e1chunk==-1 || e2chunk==-1) {
    //it is fine, let it continue
    e4chunk = e2chunk;
    e3chunk = e1chunk;
  }
  else if(e1chunk==e2chunk && e1chunk!=index) {
    n5chunk = e1chunk;
    e4chunk = e2chunk;
    e3chunk = e1chunk;
  }
  else {
    //there can be a lot of conditions, but we do not have to do aything special now
    n5chunk = -1;
    e4chunk = e2chunk;
    e3chunk = e1chunk;
  }

  // add n1, n5, n3
  elemConn[e1_n1] = n1;  elemConn[e1_n2] = n5;  elemConn[e1_n3] = n3;
  lockelems[0] = FEM_add_element(theMesh, elemConn, 3, 0, e1chunk);
  theMod->fmUtil->copyElemData(0,e1,lockelems[0]);
  // add n2, n5, n3
  elemConn[e1_n1] = n5;  elemConn[e1_n2] = n2;  elemConn[e1_n3] = n3;
  lockelems[1] = FEM_add_element(theMesh, elemConn, 3, 0, e3chunk);
  theMod->fmUtil->copyElemData(0,e1,lockelems[1]);
  if (e2 != -1) { // e2 exists
    // add n1, n5, n4
    elemConn[e2_n1] = n1;  elemConn[e2_n2] = n5;  elemConn[e2_n3] = n4;
    lockelems[2] = FEM_add_element(theMesh, elemConn, 3, 0, e2chunk);
    theMod->fmUtil->copyElemData(0,e2,lockelems[2]);
    // add n2, n5, n4
    elemConn[e2_n1] = n5;  elemConn[e2_n2] = n2;  elemConn[e2_n3] = n4;
    lockelems[3] = FEM_add_element(theMesh, elemConn, 3, 0, e4chunk);
    theMod->fmUtil->copyElemData(0,e2,lockelems[3]);
  }

  FEM_purge_element(theMesh,e1,0);
  FEM_purge_element(theMesh,e2,0);

  //get rid of some unnecessary ghost node sends
  for(int i=0; i<4;i++) {
    int nodeToUpdate = -1;
    if(i==0) nodeToUpdate = n1;
    else if(i==1) nodeToUpdate = n2;
    else if(i==2) nodeToUpdate = n3;
    else if(i==3) nodeToUpdate = n4;
    //if any of the chunks sharing this node sends this as a ghost, then all of them have to
    //so find out the set of chunks I need to send this as a ghost to
    //collect info from each of the shared chunks, do a union of all these chunks
    //send this updated list to everyone.
    //if anyone needs to add or delete some ghosts, they will
    int *chkl, numchkl=0;
    CkVec<int> finalchkl;
    theMod->fmUtil->findGhostSend(nodeToUpdate, chkl, numchkl);
    for(int j=0; j<numchkl; j++) {
      finalchkl.push_back(chkl[j]);
    }
    if(numchkl>0) delete[] chkl;

    const IDXL_Rec *irec=theMesh->node.shared.getRec(nodeToUpdate);
    int numchunks=0;
    int *chunks1, *inds1;
    if(irec) {
      numchunks = irec->getShared();
      chunks1 = new int[numchunks];
      inds1 = new int[numchunks];
      for(int j=0; j<numchunks; j++) {
	chunks1[j] = irec->getChk(j);
	inds1[j] = irec->getIdx(j);
      }
    }
    for(int j=0; j<numchunks; j++) {
      findgsMsg *fmsg = meshMod[chunks1[j]].findghostsend(index,inds1[j]);
      if(fmsg->numchks>0) {
	for(int k=0; k<fmsg->numchks; k++) {
	  bool shouldbeadded = true;
	  for(int l=0; l<finalchkl.size(); l++) {
	    if(fmsg->chunks[k]==finalchkl[l]) {
	      shouldbeadded = false;
	      break;
	    }
	  }
	  if(shouldbeadded) finalchkl.push_back(fmsg->chunks[k]);
	}
      }
      delete fmsg;
    }

    int *finall, numfinall=finalchkl.size();
    if(numfinall>0) finall = new int[numfinall];
    for(int j=0; j<numfinall; j++) finall[j] = finalchkl[j];
    finalchkl.free();

    theMod->fmUtil->UpdateGhostSend(nodeToUpdate, finall, numfinall);
    for(int j=0; j<numchunks; j++) {
      verifyghostsendMsg *vmsg = new(numfinall)verifyghostsendMsg();
      vmsg->fromChk = index;
      vmsg->sharedIdx = inds1[j];
      vmsg->numchks = numfinall;
      for(int k=0; k<numfinall; k++) vmsg->chunks[k] = finall[k];
      meshMod[chunks1[j]].updateghostsend(vmsg);
    }
    if(numfinall>0) delete[] finall;
    if(numchunks>0) {
      delete[] chunks1;
      delete[] inds1;
    }
  }

  FEM_Modify_UnlockN(theMesh, n5, 0);
  return n5;
}
Example #4
0
/** Inverse of edge bisect, this removes a degree 4 vertex n1 and 2 of its
   adjacent elements.  n2 indicates that the two elements removed are
   adjacent to edge [n1,n2]. This could be performed with edge_contraction,
   but this is a simpler operation. 

         n3	             n3        
          o	              o        
         /|\	             / \       
        / | \	            /   \      
       /  |  \	           /     \     
      /   |n1 \           /       \    
  n5 o----o----o n2   n5 o---------o n2
      \   |   /           \       /    
       \  |  /	           \     /     
        \ | /	            \   /      
         \|/	             \ /       
          o	              o        
         n4                  n4        
*/
int FEM_Adapt::vertex_remove_help(int e1, int e2, int n1, int n2, int e1_n1, 
				  int e1_n2, int e1_n3, int e2_n1, int e2_n2, 
				  int e2_n3, int n3, int n4, int n5)
{
  int numNodes = 5;
  int numElems = 4;
  int numNodesNew = 4;
  int numElemsNew = 2;
  int locknodes[5];
  int lockelems[4];
  int elemConn[3];

  locknodes[0] = n2;
  locknodes[1] = n3;
  locknodes[2] = n4;
  locknodes[3] = n5;
  locknodes[4] = n1;
  lockelems[0] = e1;
  lockelems[1] = e2;
  lockelems[2] = -1;
  lockelems[3] = -1;

  int e3 = theMesh->e2e_getNbr(e1, get_edge_index(e1_n1, e1_n3));
  int e4 = -1;
  lockelems[2] = e3;
  if (e3 != -1) {
    if (e2 != -1) {
      e4 = theMesh->e2e_getNbr(e2, get_edge_index(e2_n1, e2_n3));
      lockelems[3] = e4;
      if(e4 == -1 ) {
	return 0;
      }
    }
    //FEM_Modify_Lock(theMesh, locknodes, numNodes, lockelems, numElems);

    int e1chunk=-1, e2chunk=-1, e3chunk=-1, e4chunk=-1;
    int index = theMod->getIdx();

#ifdef DEBUG_1
    CkPrintf("Vertex Remove edge %d->%d on chunk %d\n", n1, n2, theMod->getfmUtil()->getIdx());
#endif
    
    e1chunk = FEM_remove_element(theMesh, e1, 0);
    e3chunk = FEM_remove_element(theMesh, e3, 0);
    if (e2 != -1) {
      e2chunk = FEM_remove_element(theMesh, e2, 0);
      e4chunk = FEM_remove_element(theMesh, e4, 0);
    }
    FEM_remove_node(theMesh, n1);
    
    // add n2, n5, n3
    elemConn[e1_n1] = n2;  elemConn[e1_n2] = n3;  elemConn[e1_n3] = n5;
    lockelems[0] = FEM_add_element(theMesh, elemConn, 3, 0, e1chunk);
    if (e2 != -1) {
      // add n2, n5, n4
      elemConn[e2_n1] = n5;  elemConn[e2_n2] = n4;  elemConn[e2_n3] = n2;
      lockelems[1] = FEM_add_element(theMesh, elemConn, 3, 0, e2chunk);
    }

    return 1;
  }

  return 0;
}
Example #5
0
/** Perform a Delaunay flip of the edge (n1, n2) returning 1 if successful, 0 if
   not (likely due to the edge being on a boundary). The convexity of the 
   quadrilateral formed by two faces incident to edge (n1, n2) is assumed. n1 
   and n2 are assumed to be local to this chunk.  An adjacency test is 
   performed on n1 and n2 by searching for an element with edge [n1,n2].

       n3                 n3
        o                  o
       / \                /|\
      /   \              / | \
     /     \            /  |  \
    /       \          /   |   \
n1 o---------o n2  n1 o    |    o n2
    \       /          \   |   / 
     \     /            \  |  /
      \   /              \ | /
       \ /                \|/
        o                  o
       n4                 n4
*/
int FEM_Adapt::edge_flip_help(int e1, int e2, int n1, int n2, int e1_n1, 
			      int e1_n2, int e1_n3, int n3, int n4, int *locknodes) 
{
  int numNodes = 4;
  int numElems = 2;
  int lockelems[2];
  int elemConn[3];
  locknodes[0] = n1;
  locknodes[1] = n2;
  locknodes[2] = n3;
  locknodes[3] = n4;
  lockelems[0] = e1;
  lockelems[1] = e2;
  if(n1 < 0 || n2 < 0) {
    return -1;
  }
  int index = theMod->getIdx();
  bool flag = theMod->fmAdaptAlgs->controlQualityF(n1,n2,n3,n4);
  if(flag) return -1;
  int e1Topurge = e1;
  int e2Topurge = e2;

#ifdef DEBUG_1
  CkPrintf("Flipping edge %d->%d on chunk %d\n", n1, n2, theMod->getfmUtil()->getIdx());
#endif
  //FEM_Modify_Lock(theMesh, locknodes, numNodes, lockelems, numElems);
  //if any of the two elements is remote, eat those
  if(n3 < 0) {
    e1Topurge = theMod->fmUtil->eatIntoElement(e1);
    theMesh->e2n_getAll(e1Topurge,elemConn);
    for(int i=0; i<3; i++) {
      if(elemConn[i]!=n1 && elemConn[i]!=n2) {
	n3 = elemConn[i];
      }
    }
    locknodes[2] = n3;
  }
  if(n4 < 0) {
    e2Topurge = theMod->fmUtil->eatIntoElement(e2);
    theMesh->e2n_getAll(e2Topurge,elemConn);
    for(int i=0; i<3; i++) {
      if(elemConn[i]!=n1 && elemConn[i]!=n2) {
	n4 = elemConn[i];
      }
    }
    locknodes[3] = n4;
  }

  FEM_remove_element(theMesh,e1Topurge,0,0);
  FEM_remove_element(theMesh,e2Topurge,0,0);
  // add n1, n3, n4
  elemConn[e1_n1] = n1;  elemConn[e1_n2] = n4;  elemConn[e1_n3] = n3;
  lockelems[0] = FEM_add_element(theMesh, elemConn, 3, 0, index);
  //the attributes should really be interpolated, i.e. on both new elems,
  //the values should be an average of the previous two elements
  theMod->fmUtil->copyElemData(0,e1Topurge,lockelems[0]);
  // add n2, n3, n4
  elemConn[e1_n1] = n4;  elemConn[e1_n2] = n2;  elemConn[e1_n3] = n3;
  lockelems[1] = FEM_add_element(theMesh, elemConn, 3, 0, index);
  theMod->fmUtil->copyElemData(0,e1Topurge,lockelems[1]); //both of the new elements copy from one element
  //purge the two elements
  FEM_purge_element(theMesh,e1Topurge,0);
  FEM_purge_element(theMesh,e2Topurge,0);

  //get rid of some unnecessary ghost node sends
  for(int i=0; i<4;i++) {
    int nodeToUpdate = -1;
    if(i==0) nodeToUpdate = n1;
    else if(i==1) nodeToUpdate = n2;
    else if(i==2) nodeToUpdate = n3;
    else if(i==3) nodeToUpdate = n4;
    //if any of the chunks sharing this node sends this as a ghost, then all of them have to
    //so find out the set of chunks I need to send this as a ghost to
    //collect info from each of the shared chunks, do a union of all these chunks
    //send this updated list to everyone.
    //if anyone needs to add or delete some ghosts, they will
    int *chkl, numchkl=0;
    CkVec<int> finalchkl;
    theMod->fmUtil->findGhostSend(nodeToUpdate, chkl, numchkl);
    for(int j=0; j<numchkl; j++) {
      finalchkl.push_back(chkl[j]);
    }
    if(numchkl>0) delete[] chkl;

    const IDXL_Rec *irec=theMesh->node.shared.getRec(nodeToUpdate);
    int numchunks=0;
    int *chunks1, *inds1;
    if(irec) {
      numchunks = irec->getShared();
      chunks1 = new int[numchunks];
      inds1 = new int[numchunks];
      for(int j=0; j<numchunks; j++) {
	chunks1[j] = irec->getChk(j);
	inds1[j] = irec->getIdx(j);
      }
    }
    for(int j=0; j<numchunks; j++) {
      findgsMsg *fmsg = meshMod[chunks1[j]].findghostsend(index,inds1[j]);
      if(fmsg->numchks>0) {
	for(int k=0; k<fmsg->numchks; k++) {
	  bool shouldbeadded = true;
	  for(int l=0; l<finalchkl.size(); l++) {
	    if(fmsg->chunks[k]==finalchkl[l]) {
	      shouldbeadded = false;
	      break;
	    }
	  }
	  if(shouldbeadded) finalchkl.push_back(fmsg->chunks[k]);
	}
      }
      delete fmsg;
    }

    int *finall, numfinall=finalchkl.size();
    if(numfinall>0) finall = new int[numfinall];
    for(int j=0; j<numfinall; j++) finall[j] = finalchkl[j];
    finalchkl.free();

    theMod->fmUtil->UpdateGhostSend(nodeToUpdate, finall, numfinall);
    for(int j=0; j<numchunks; j++) {
      verifyghostsendMsg *vmsg = new(numfinall)verifyghostsendMsg();
      vmsg->fromChk = index;
      vmsg->sharedIdx = inds1[j];
      vmsg->numchks = numfinall;
      for(int k=0; k<numfinall; k++) vmsg->chunks[k] = finall[k];
      meshMod[chunks1[j]].updateghostsend(vmsg);
    }
    if(numfinall>0) delete[] finall;
    if(numchunks>0) {
      delete[] chunks1;
      delete[] inds1;
    }
  }
  //make sure that it always comes here, don't return with unlocking
  return 1; //return newNode;
}