示例#1
0
int main(int argc, char *argv[]) {
  
  /*--- Local variables ---*/
  
	unsigned short iDV, nZone = 1, iFFDBox, iPlane, nPlane, iVar;
	double *ObjectiveFunc, *ObjectiveFunc_New, *Gradient, delta_eps, MinPlane, MaxPlane, MinXCoord, MaxXCoord,
  **Plane_P0, **Plane_Normal, Volume, Volume_New, Volume_Grad;
  vector<double> *Xcoord_Airfoil, *Ycoord_Airfoil, *Zcoord_Airfoil, *Variable_Airfoil;
  char grid_file[MAX_STRING_SIZE], buffer_char[50], out_file[MAX_STRING_SIZE];

 	char *cstr;
	ofstream Gradient_file, ObjFunc_file;
	int rank = MASTER_NODE;
  int size = SINGLE_NODE;
  
  /*--- MPI initialization ---*/

#ifdef HAVE_MPI
	MPI_Init(&argc,&argv);
	MPI_Comm_rank(MPI_COMM_WORLD,&rank);
  MPI_Comm_size(MPI_COMM_WORLD,&size);
#endif
	
	/*--- Pointer to different structures that will be used throughout the entire code ---*/
  
	CFreeFormDefBox** FFDBox = NULL;
	CConfig *config = NULL;
	CGeometry *boundary = NULL;
	CSurfaceMovement *surface_mov = NULL;
	
	/*--- Definition of the class for the definition of the problem ---*/
  
	if (argc == 2) config = new CConfig(argv[1], SU2_GEO, ZONE_0, nZone, 0, VERB_HIGH);
	else {
		strcpy (grid_file, "default.cfg");
		config = new CConfig(grid_file, SU2_GEO, ZONE_0, nZone, 0, VERB_HIGH);
	}
	
  /*--- Change the name of the input-output files for the parallel computation ---*/
  
#ifdef HAVE_MPI
	config->SetFileNameDomain(rank+1);
#endif
	
	/*--- Definition of the class for the boundary of the geometry ---*/
  
	boundary = new CBoundaryGeometry(config, config->GetMesh_FileName(), config->GetMesh_FileFormat());
  
  /*--- Set the number of sections, and allocate the memory ---*/
  
  if (boundary->GetnDim() == 2) nPlane = 1;
  else nPlane = config->GetnSections();

  Xcoord_Airfoil = new vector<double>[nPlane];
  Ycoord_Airfoil = new vector<double>[nPlane];
  Zcoord_Airfoil = new vector<double>[nPlane];
  Variable_Airfoil = new vector<double>[nPlane];

  Plane_P0 = new double*[nPlane];
  Plane_Normal = new double*[nPlane];
  for(iPlane = 0; iPlane < nPlane; iPlane++ ) {
    Plane_P0[iPlane] = new double[3];
    Plane_Normal[iPlane] = new double[3];
  }
  
  ObjectiveFunc = new double[nPlane*20];
  ObjectiveFunc_New = new double[nPlane*20];
  Gradient = new double[nPlane*20];

  for (iVar = 0; iVar < nPlane*20; iVar++) {
    ObjectiveFunc[iVar] = 0.0;
    ObjectiveFunc_New[iVar] = 0.0;
    Gradient[iVar] = 0.0;
  }
  
  /*--- Evaluation of the objective function ---*/
  
	if (rank == MASTER_NODE)
		cout << endl <<"----------------------- Preprocessing computations ----------------------" << endl;

  
  /*--- Boundary geometry preprocessing ---*/
  
	if (rank == MASTER_NODE) cout << "Identify vertices." <<endl;
	boundary->SetVertex();
  
  /*--- Compute elements surrounding points & points surrounding points ---*/
  
  if (rank == MASTER_NODE) cout << "Setting local point and element connectivity." << endl;
	boundary->SetPoint_Connectivity();
  boundary->SetEdges();

	/*--- Create the control volume structures ---*/
  
	if (rank == MASTER_NODE) cout << "Set boundary control volume structure." << endl;
	boundary->SetBoundControlVolume(config, ALLOCATE);
	
  /*--- Compute the surface curvature ---*/
  
  if (rank == MASTER_NODE) cout << "Compute the surface curvature." << endl;
  boundary->ComputeSurf_Curvature(config);
  
  if (rank == MASTER_NODE) cout << "Writing a Tecplot file of the surface curvature." << endl;
  if (size > 1) sprintf (buffer_char, "_%d.plt", rank+1); else sprintf (buffer_char, ".plt");
  strcpy (out_file, "Surface_Curvature"); strcat(out_file, buffer_char); boundary->SetBoundTecPlot(out_file, true, config);
  
	/*--- Create plane structure ---*/
  
  if (rank == MASTER_NODE) cout << "Set plane structure." << endl;
  if (boundary->GetnDim() == 2) {
    MinXCoord = -1E6; MaxXCoord = 1E6;
    Plane_Normal[0][0] = 0.0;   Plane_P0[0][0] = 0.0;
    Plane_Normal[0][1] = 1.0;   Plane_P0[0][1] = 0.0;
    Plane_Normal[0][2] = 0.0;   Plane_P0[0][2] = 0.0;
  }
  else if (boundary->GetnDim() == 3) {
    MinPlane = config->GetSection_Location(0); MaxPlane = config->GetSection_Location(1);
    MinXCoord = -1E6; MaxXCoord = 1E6;
    for (iPlane = 0; iPlane < nPlane; iPlane++) {
      Plane_Normal[iPlane][0] = 0.0;    Plane_P0[iPlane][0] = 0.0;
      Plane_Normal[iPlane][1] = 0.0;    Plane_P0[iPlane][1] = 0.0;
      Plane_Normal[iPlane][2] = 0.0;    Plane_P0[iPlane][2] = 0.0;
      Plane_Normal[iPlane][config->GetAxis_Orientation()] = 1.0;
      Plane_P0[iPlane][config->GetAxis_Orientation()] = MinPlane + iPlane*(MaxPlane - MinPlane)/double(nPlane-1);
    }
  }

  /*--- Create airfoil section structure ---*/
  
  if (rank == MASTER_NODE) cout << "Set airfoil section structure." << endl;
  for (iPlane = 0; iPlane < nPlane; iPlane++) {
    boundary->ComputeAirfoil_Section(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, MinXCoord, MaxXCoord, NULL,
                                     Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], Variable_Airfoil[iPlane], true, config);
  }
  
  /*--- Compute the internal volume of a 3D body. ---*/
  
  if (rank == MASTER_NODE)  cout << "Computing the internal volume." << endl;
  if (boundary->GetnDim() == 3) Volume = boundary->Compute_Volume(config, true);
  
  if (rank == MASTER_NODE)
    cout << endl <<"-------------------- Objective function evaluation ----------------------" << endl;

  if (rank == MASTER_NODE) {
    
    /*--- Evaluate objective function ---*/
    for (iPlane = 0; iPlane < nPlane; iPlane++) {

      if (Xcoord_Airfoil[iPlane].size() != 0) {
        
        cout << "\nSection " << (iPlane+1) << ". Plane (yCoord): " << Plane_P0[iPlane][1] << "." << endl;
        
        ObjectiveFunc[iPlane]           = boundary->Compute_MaxThickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, config, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], true);
        ObjectiveFunc[1*nPlane+iPlane]  = boundary->Compute_Thickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, 0.250000, config, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], true);
        ObjectiveFunc[2*nPlane+iPlane]  = boundary->Compute_Thickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, 0.333333, config, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], true);
        ObjectiveFunc[3*nPlane+iPlane]  = boundary->Compute_Thickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, 0.500000, config, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], true);
        ObjectiveFunc[4*nPlane+iPlane]  = boundary->Compute_Thickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, 0.666666, config, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], true);
        ObjectiveFunc[5*nPlane+iPlane]  = boundary->Compute_Thickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, 0.750000, config, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], true);
        ObjectiveFunc[6*nPlane+iPlane]  = boundary->Compute_Area(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, config, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], true);
        ObjectiveFunc[7*nPlane+iPlane]  = boundary->Compute_AoA(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], true);
        ObjectiveFunc[8*nPlane+iPlane]  = boundary->Compute_Chord(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], true);
        
        cout << "Maximum thickness: "   << ObjectiveFunc[iPlane] << "." << endl;
        cout << "1/4 chord thickness: " << ObjectiveFunc[1*nPlane+iPlane] << "." << endl;
        cout << "1/3 chord thickness: " << ObjectiveFunc[2*nPlane+iPlane] << "." << endl;
        cout << "1/2 chord thickness: " << ObjectiveFunc[3*nPlane+iPlane] << "." << endl;
        cout << "2/3 chord thickness: " << ObjectiveFunc[4*nPlane+iPlane] << "." << endl;
        cout << "3/4 chord thickness: " << ObjectiveFunc[5*nPlane+iPlane] << "." << endl;
        cout << "Area: "                << ObjectiveFunc[6*nPlane+iPlane] << "." << endl;
        cout << "Angle of attack: "     << ObjectiveFunc[7*nPlane+iPlane] << "." << endl;
        cout << "Chord: "               << ObjectiveFunc[8*nPlane+iPlane] << "." << endl;
        
      }
      
    }
    
    /*--- The value for Volume to the area of the first section
     in case this is a 2D calculation ---*/
    
    if (boundary->GetnDim() == 2) Volume = ObjectiveFunc[6];
    cout << "\nInternal volume: " << Volume << "." << endl;
    
    /*--- Write the objective function in a external file ---*/
		cstr = new char [config->GetObjFunc_Value_FileName().size()+1];
		strcpy (cstr, config->GetObjFunc_Value_FileName().c_str());
		ObjFunc_file.open(cstr, ios::out);
    ObjFunc_file << "TITLE = \"SU2_GEO Simulation\"" << endl;
    
    if (boundary->GetnDim() == 2) {
      ObjFunc_file << "VARIABLES = \"MAX_THICKNESS\",\"1/4_THICKNESS\",\"1/3_THICKNESS\",\"1/2_THICKNESS\",\"2/3_THICKNESS\",\"3/4_THICKNESS\",\"AREA\",\"AOA\",\"CHORD\",\"VOLUME\"" << endl;
    }
    else if (boundary->GetnDim() == 3) {
      ObjFunc_file << "VARIABLES = ";
      for (iPlane = 0; iPlane < nPlane; iPlane++) ObjFunc_file << "\"MAX_THICKNESS_SEC"<< (iPlane+1) << "\", ";
      for (iPlane = 0; iPlane < nPlane; iPlane++) ObjFunc_file << "\"1/4_THICKNESS_SEC"<< (iPlane+1) << "\", ";
      for (iPlane = 0; iPlane < nPlane; iPlane++) ObjFunc_file << "\"1/3_THICKNESS_SEC"<< (iPlane+1) << "\", ";
      for (iPlane = 0; iPlane < nPlane; iPlane++) ObjFunc_file << "\"1/2_THICKNESS_SEC"<< (iPlane+1) << "\", ";
      for (iPlane = 0; iPlane < nPlane; iPlane++) ObjFunc_file << "\"2/3_THICKNESS_SEC"<< (iPlane+1) << "\", ";
      for (iPlane = 0; iPlane < nPlane; iPlane++) ObjFunc_file << "\"3/4_THICKNESS_SEC"<< (iPlane+1) << "\", ";
      for (iPlane = 0; iPlane < nPlane; iPlane++) ObjFunc_file << "\"AREA_SEC"<< (iPlane+1) << "\", ";
      for (iPlane = 0; iPlane < nPlane; iPlane++) ObjFunc_file << "\"AOA_SEC"<< (iPlane+1) << "\", ";
      for (iPlane = 0; iPlane < nPlane; iPlane++) ObjFunc_file << "\"CHORD_SEC"<< (iPlane+1) << "\", ";
      ObjFunc_file << "\"VOLUME\"" << endl;
    }
    
    ObjFunc_file << "ZONE T= \"Geometrical variables (value)\"" << endl;
    
    for (iPlane = 0; iPlane < nPlane*9; iPlane++)
      ObjFunc_file << ObjectiveFunc[iPlane] <<", ";
    ObjFunc_file << Volume << endl;

    ObjFunc_file.close();
    
	}
	
	if (config->GetGeometryMode() == GRADIENT) {
		
		/*--- Definition of the Class for surface deformation ---*/
		surface_mov = new CSurfaceMovement();
		
		/*--- Definition of the FFD deformation class ---*/
		FFDBox = new CFreeFormDefBox*[MAX_NUMBER_FFD];
		
		if (rank == MASTER_NODE)
			cout << endl <<"------------- Gradient evaluation using finite differences --------------" << endl;

		/*--- Write the gradient in a external file ---*/
		if (rank == MASTER_NODE) {
			cstr = new char [config->GetObjFunc_Grad_FileName().size()+1];
			strcpy (cstr, config->GetObjFunc_Grad_FileName().c_str());
			Gradient_file.open(cstr, ios::out);
		}
		
		for (iDV = 0; iDV < config->GetnDV(); iDV++) {
			   
      /*--- Free Form deformation based ---*/
      
      if ((config->GetDesign_Variable(iDV) == FFD_CONTROL_POINT_2D) ||
          (config->GetDesign_Variable(iDV) == FFD_CAMBER_2D) ||
          (config->GetDesign_Variable(iDV) == FFD_THICKNESS_2D) ||
          (config->GetDesign_Variable(iDV) == FFD_CONTROL_POINT) ||
          (config->GetDesign_Variable(iDV) == FFD_DIHEDRAL_ANGLE) ||
          (config->GetDesign_Variable(iDV) == FFD_TWIST_ANGLE) ||
          (config->GetDesign_Variable(iDV) == FFD_ROTATION) ||
          (config->GetDesign_Variable(iDV) == FFD_CAMBER) ||
          (config->GetDesign_Variable(iDV) == FFD_THICKNESS) ) {
        
        /*--- Read the FFD information in the first iteration ---*/
        
        if (iDV == 0) {
          
          if (rank == MASTER_NODE) cout << "Read the FFD information from mesh file." << endl;
          
          /*--- Read the FFD information from the grid file ---*/
          
          surface_mov->ReadFFDInfo(boundary, config, FFDBox, config->GetMesh_FileName(), true);
          
          /*--- If the FFDBox was not defined in the input file ---*/
          
          if (!surface_mov->GetFFDBoxDefinition() && (rank == MASTER_NODE)) {
            cout << "The input grid doesn't have the entire FFD information!" << endl;
            cout << "Press any key to exit..." << endl;
            cin.get();
          }
          
          if (rank == MASTER_NODE)
            cout <<"-------------------------------------------------------------------------" << endl;
          
        }
        
        if (rank == MASTER_NODE) {
          cout << endl << "Design variable number "<< iDV <<"." << endl;
          cout << "Perform 3D deformation of the surface." << endl;
        }
        
        /*--- Apply the control point change ---*/
        
        for (iFFDBox = 0; iFFDBox < surface_mov->GetnFFDBox(); iFFDBox++) {
          
          switch ( config->GetDesign_Variable(iDV) ) {
            case FFD_CONTROL_POINT_2D : surface_mov->SetFFDCPChange_2D(boundary, config, FFDBox[iFFDBox], iDV, true); break;
            case FFD_CAMBER_2D :        surface_mov->SetFFDCamber_2D(boundary, config, FFDBox[iFFDBox], iDV, true); break;
            case FFD_THICKNESS_2D :     surface_mov->SetFFDThickness_2D(boundary, config, FFDBox[iFFDBox], iDV, true); break;
            case FFD_CONTROL_POINT :    surface_mov->SetFFDCPChange(boundary, config, FFDBox[iFFDBox], iDV, true); break;
            case FFD_DIHEDRAL_ANGLE :   surface_mov->SetFFDDihedralAngle(boundary, config, FFDBox[iFFDBox], iDV, true); break;
            case FFD_TWIST_ANGLE :      surface_mov->SetFFDTwistAngle(boundary, config, FFDBox[iFFDBox], iDV, true); break;
            case FFD_ROTATION :         surface_mov->SetFFDRotation(boundary, config, FFDBox[iFFDBox], iDV, true); break;
            case FFD_CAMBER :           surface_mov->SetFFDCamber(boundary, config, FFDBox[iFFDBox], iDV, true); break;
            case FFD_THICKNESS :        surface_mov->SetFFDThickness(boundary, config, FFDBox[iFFDBox], iDV, true); break;
            case FFD_CONTROL_SURFACE :  surface_mov->SetFFDControl_Surface(boundary, config, FFDBox[iFFDBox], iDV, true); break;
          }
          
          /*--- Recompute cartesian coordinates using the new control points position ---*/
          
          surface_mov->SetCartesianCoord(boundary, config, FFDBox[iFFDBox], iFFDBox);
          
        }
        
      }
      
      /*--- Hicks Henne design variable ---*/
      
      else if (config->GetDesign_Variable(iDV) == HICKS_HENNE) {
        if (rank == MASTER_NODE) {
          cout << endl << "Design variable number "<< iDV <<"." << endl;
          cout << "Perform 2D deformation of the surface." << endl;
        }
        surface_mov->SetHicksHenne(boundary, config, iDV, true);
      }
      
      /*--- Displacement design variable ---*/
      
      else if (config->GetDesign_Variable(iDV) == DISPLACEMENT) {
        if (rank == MASTER_NODE) {
          cout << endl << "Design variable number "<< iDV <<"." << endl;
          cout << "Perform 2D deformation of the surface." << endl;
        }
        surface_mov->SetDisplacement(boundary, config, iDV, true);
      }
      
      /*--- Rotation design variable ---*/
      
      else if (config->GetDesign_Variable(iDV) == ROTATION) {
        if (rank == MASTER_NODE) {
          cout << endl << "Design variable number "<< iDV <<"." << endl;
          cout << "Perform 2D deformation of the surface." << endl;
        }
        surface_mov->SetRotation(boundary, config, iDV, true);
      }
      
      /*--- CosBump design variable ---*/
      
      else if (config->GetDesign_Variable(iDV) == COSINE_BUMP) {
        if (rank == MASTER_NODE) {
          cout << endl << "Design variable number "<< iDV <<"." << endl;
          cout << "Perform 2D deformation of the surface." << endl;
        }
        surface_mov->SetCosBump(boundary, config, iDV, true);
      }
      
      /*--- Fourier design variable ---*/
      
      else if (config->GetDesign_Variable(iDV) == FOURIER) {
        if (rank == MASTER_NODE) {
          cout << endl << "Design variable number "<< iDV <<"." << endl;
          cout << "Perform 2D deformation of the surface." << endl;
        }
        surface_mov->SetFourier(boundary, config, iDV, true);
      }
      
      /*--- NACA_4Digits design variable ---*/
      
      else if (config->GetDesign_Variable(iDV) == NACA_4DIGITS) {
        if (rank == MASTER_NODE) {
          cout << endl << "Design variable number "<< iDV <<"." << endl;
          cout << "Perform 2D deformation of the surface." << endl;
        }
        surface_mov->SetNACA_4Digits(boundary, config);
      }
      
      /*--- Parabolic design variable ---*/
      
      else if (config->GetDesign_Variable(iDV) == PARABOLIC) {
        if (rank == MASTER_NODE) {
          cout << endl << "Design variable number "<< iDV <<"." << endl;
          cout << "Perform 2D deformation of the surface." << endl;
        }
        surface_mov->SetParabolic(boundary, config);
      }
      
      /*--- Spherical design variable ---*/
      
      else if (config->GetDesign_Variable(iDV) == SPHERICAL) {
        if (rank == MASTER_NODE) {
          cout << endl << "Design variable number "<< iDV <<"." << endl;
          cout << "Perform 3D deformation of the surface." << endl;
        }
        surface_mov->SetSpherical(boundary, config, iDV, true);
      }
      
      /*--- Design variable not implement ---*/
      
      else { cout << "Design Variable not implement yet" << endl; }
      
      /*--- Create airfoil structure ---*/
      for (iPlane = 0; iPlane < nPlane; iPlane++) {
        boundary->ComputeAirfoil_Section(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, MinXCoord, MaxXCoord, NULL,
                                         Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], Variable_Airfoil[iPlane], false, config);
      }
      
      /*--- Compute the gradient for the volume. In 2D this is just
       the gradient of the area. ---*/
      
      if (boundary->GetnDim() == 3) Volume_New = boundary->Compute_Volume(config, false);
      
			/*--- Compute gradient ---*/
			if (rank == MASTER_NODE) {
        
        delta_eps = config->GetDV_Value(iDV);
        
        if (delta_eps == 0) {
          cout << "The finite difference steps is zero!!" << endl;
          cout << "Press any key to exit..." << endl;
          cin.get();
#ifdef HAVE_MPI
          MPI_Abort(MPI_COMM_WORLD,1);
          MPI_Finalize();
#else
          exit(1);
#endif
        }

        for (iPlane = 0; iPlane < nPlane; iPlane++) {
          
          if (Xcoord_Airfoil[iPlane].size() != 0) {
            
            cout << "\nSection " << (iPlane+1) << ". Plane (yCoord): " << Plane_P0[iPlane][1] << "." << endl;
            
            ObjectiveFunc_New[iPlane] = boundary->Compute_MaxThickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, config, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], false);
            Gradient[iPlane] = (ObjectiveFunc_New[iPlane] - ObjectiveFunc[iPlane]) / delta_eps;
            
            ObjectiveFunc_New[1*nPlane + iPlane] = boundary->Compute_Thickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, 0.250000, config, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], false);
            Gradient[1*nPlane + iPlane] = (ObjectiveFunc_New[1*nPlane + iPlane] - ObjectiveFunc[1*nPlane + iPlane]) / delta_eps;
            
            ObjectiveFunc_New[2*nPlane + iPlane] = boundary->Compute_Thickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, 0.333333, config, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], false);
            Gradient[2*nPlane + iPlane] = (ObjectiveFunc_New[2*nPlane + iPlane] - ObjectiveFunc[2*nPlane + iPlane]) / delta_eps;
            
            ObjectiveFunc_New[3*nPlane + iPlane] = boundary->Compute_Thickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, 0.500000, config, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], false);
            Gradient[3*nPlane + iPlane] = (ObjectiveFunc_New[3*nPlane + iPlane] - ObjectiveFunc[3*nPlane + iPlane]) / delta_eps;
            
            ObjectiveFunc_New[4*nPlane + iPlane] = boundary->Compute_Thickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, 0.666666, config, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], false);
            Gradient[4*nPlane + iPlane] = (ObjectiveFunc_New[4*nPlane + iPlane] - ObjectiveFunc[4*nPlane + iPlane]) / delta_eps;
            
            ObjectiveFunc_New[5*nPlane + iPlane] = boundary->Compute_Thickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, 0.750000, config, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], false);
            Gradient[5*nPlane + iPlane] = (ObjectiveFunc_New[5*nPlane + iPlane] - ObjectiveFunc[5*nPlane + iPlane]) / delta_eps;
            
            ObjectiveFunc_New[6*nPlane + iPlane] = boundary->Compute_Area(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, config, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], false);
            Gradient[6*nPlane + iPlane] = (ObjectiveFunc_New[6*nPlane + iPlane] - ObjectiveFunc[6*nPlane + iPlane]) / delta_eps;
            
            ObjectiveFunc_New[7*nPlane + iPlane] = boundary->Compute_AoA(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], false);
            Gradient[7*nPlane + iPlane] = (ObjectiveFunc_New[7*nPlane + iPlane] - ObjectiveFunc[7*nPlane + iPlane]) / delta_eps;
            
            ObjectiveFunc_New[8*nPlane + iPlane] = boundary->Compute_Chord(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], false);
            Gradient[8*nPlane + iPlane] = (ObjectiveFunc_New[8*nPlane + iPlane] - ObjectiveFunc[8*nPlane + iPlane]) / delta_eps;
            
            cout << "Maximum thickness gradient: "    << Gradient[iPlane] << "." << endl;
            cout << "1/4 chord thickness gradient: "  << Gradient[1*nPlane + iPlane] << "." << endl;
            cout << "1/3 chord thickness gradient: "  << Gradient[2*nPlane + iPlane] << "." << endl;
            cout << "1/2 chord thickness gradient: "  << Gradient[3*nPlane + iPlane] << "." << endl;
            cout << "2/3 chord thickness gradient: "  << Gradient[4*nPlane + iPlane] << "." << endl;
            cout << "3/4 chord thickness gradient: "  << Gradient[5*nPlane + iPlane] << "." << endl;
            cout << "Area gradient: "                 << Gradient[6*nPlane + iPlane] << "." << endl;
            cout << "Angle of attack gradient: "      << Gradient[7*nPlane + iPlane] << "." << endl;
            cout << "Chord gradient: "                << Gradient[8*nPlane + iPlane] << "." << endl;
            
          }
          
        }
        
        /*--- Compute the gradient for the volume. In 2D this is just
         the gradient of the area. ---*/
        
        if (boundary->GetnDim() == 2) Volume_New = ObjectiveFunc_New[6];
        Volume_Grad = (Volume_New - Volume)/ delta_eps;
        cout << "\nInternal volume gradient: " << Volume_Grad << "." << endl;
 				
        if (iDV == 0) {
          Gradient_file << "TITLE = \"SU2_GEO Simulation\"" << endl;

          if (boundary->GetnDim() == 2) {
            Gradient_file << "VARIABLES = \"DESIGN_VARIABLE\",\"MAX_THICKNESS\",\"1/4_THICKNESS\",\"1/3_THICKNESS\",\"1/2_THICKNESS\",\"2/3_THICKNESS\",\"3/4_THICKNESS\",\"AREA\",\"AOA\",\"CHORD\",\"VOLUME\"" << endl;
          }
          else if (boundary->GetnDim() == 3) {
            Gradient_file << "VARIABLES = \"DESIGN_VARIABLE\",";
            for (iPlane = 0; iPlane < nPlane; iPlane++) Gradient_file << "\"MAX_THICKNESS_SEC"<< (iPlane+1) << "\", ";
            for (iPlane = 0; iPlane < nPlane; iPlane++) Gradient_file << "\"1/4_THICKNESS_SEC"<< (iPlane+1) << "\", ";
            for (iPlane = 0; iPlane < nPlane; iPlane++) Gradient_file << "\"1/3_THICKNESS_SEC"<< (iPlane+1) << "\", ";
            for (iPlane = 0; iPlane < nPlane; iPlane++) Gradient_file << "\"1/2_THICKNESS_SEC"<< (iPlane+1) << "\", ";
            for (iPlane = 0; iPlane < nPlane; iPlane++) Gradient_file << "\"2/3_THICKNESS_SEC"<< (iPlane+1) << "\", ";
            for (iPlane = 0; iPlane < nPlane; iPlane++) Gradient_file << "\"3/4_THICKNESS_SEC"<< (iPlane+1) << "\", ";
            for (iPlane = 0; iPlane < nPlane; iPlane++) Gradient_file << "\"AREA_SEC"<< (iPlane+1) << "\", ";
            for (iPlane = 0; iPlane < nPlane; iPlane++) Gradient_file << "\"AOA_SEC"<< (iPlane+1) << "\", ";
            for (iPlane = 0; iPlane < nPlane; iPlane++) Gradient_file << "\"CHORD_SEC"<< (iPlane+1) << "\", ";
            Gradient_file << "\"VOLUME\"" << endl;
          }
          
          Gradient_file << "ZONE T= \"Geometrical variables (gradient)\"" << endl;
          
        }
        
        Gradient_file << (iDV) <<", ";
        for (iPlane = 0; iPlane < nPlane*9; iPlane++)
          Gradient_file << Gradient[iPlane] <<", ";
        Gradient_file << Volume_Grad << endl;
        
				if (iDV != (config->GetnDV()-1)) cout <<"-------------------------------------------------------------------------" << endl;
				
			}

		}
		
		if (rank == MASTER_NODE)
			Gradient_file.close();
    
	}
	
  /*--- Finalize MPI parallelization ---*/
	
#ifdef HAVE_MPI
	MPI_Finalize();
#endif
	
  /*--- Deallocate memory ---*/
  
  delete [] Xcoord_Airfoil;
  delete [] Ycoord_Airfoil;
  delete [] Zcoord_Airfoil;
  
  delete [] ObjectiveFunc;
  delete [] ObjectiveFunc_New;
  delete [] Gradient;
  
  for(iPlane = 0; iPlane < nPlane; iPlane++ ) {
    delete Plane_P0[iPlane];
    delete Plane_Normal[iPlane];
  }
  delete [] Plane_P0;
  delete [] Plane_Normal;
  
  /*--- End solver ---*/
  
	if (rank == MASTER_NODE)
		cout << endl <<"------------------------- Exit Success (SU2_GEO) ------------------------" << endl << endl;

  
	return EXIT_SUCCESS;
	
}
示例#2
0
int main(int argc, char *argv[]) {
  
  unsigned short iZone, nZone = SINGLE_ZONE;
  su2double StartTime = 0.0, StopTime = 0.0, UsedTime = 0.0;
  
  char config_file_name[MAX_STRING_SIZE], *cstr = NULL;
  ofstream Gradient_file;

  su2double** Gradient;
  unsigned short iDV, iDV_Value;
  int rank, size;

  /*--- MPI initialization, and buffer setting ---*/
  
#ifdef HAVE_MPI
  SU2_MPI::Init(&argc,&argv);
  SU2_MPI::Comm MPICommunicator(MPI_COMM_WORLD);
#else
  SU2_Comm MPICommunicator(0);
#endif

  rank = SU2_MPI::GetRank();
  size = SU2_MPI::GetSize();
  
  /*--- Pointer to different structures that will be used throughout the entire code ---*/
  
  CConfig **config_container          = NULL;
  CGeometry **geometry_container      = NULL;
  CSurfaceMovement **surface_movement = NULL;
  CVolumetricMovement **grid_movement = NULL;
  COutput *output                     = NULL;

  /*--- Load in the number of zones and spatial dimensions in the mesh file (if no config
   file is specified, default.cfg is used) ---*/
  
  if (argc == 2) { strcpy(config_file_name,argv[1]); }
  else { strcpy(config_file_name, "default.cfg"); }

  /*--- Read the name and format of the input mesh file to get from the mesh
   file the number of zones and dimensions from the numerical grid (required
   for variables allocation)  ---*/

  CConfig *config = NULL;
  config = new CConfig(config_file_name, SU2_DEF);

  nZone = CConfig::GetnZone(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);


  /*--- Definition of the containers per zones ---*/
  
  config_container = new CConfig*[nZone];
  geometry_container = new CGeometry*[nZone];
  surface_movement   = new CSurfaceMovement*[nZone];
  grid_movement      = new CVolumetricMovement*[nZone];
  
  for (iZone = 0; iZone < nZone; iZone++) {
    config_container[iZone]       = NULL;
    geometry_container[iZone]     = NULL;
    grid_movement [iZone]     = NULL;
    surface_movement[iZone]   = NULL;
  }
  
  /*--- Loop over all zones to initialize the various classes. In most
   cases, nZone is equal to one. This represents the solution of a partial
   differential equation on a single block, unstructured mesh. ---*/
  
  for (iZone = 0; iZone < nZone; iZone++) {
    
    /*--- Definition of the configuration option class for all zones. In this
     constructor, the input configuration file is parsed and all options are
     read and stored. ---*/
    
    config_container[iZone] = new CConfig(config_file_name, SU2_DOT, iZone, nZone, 0, VERB_HIGH);

    /*--- Set the MPI communicator ---*/
    config_container[iZone]->SetMPICommunicator(MPICommunicator);
        
    /*--- Definition of the geometry class to store the primal grid in the partitioning process. ---*/
    
    CGeometry *geometry_aux = NULL;
    
    /*--- All ranks process the grid and call ParMETIS for partitioning ---*/
    
    geometry_aux = new CPhysicalGeometry(config_container[iZone], iZone, nZone);
    
    /*--- Color the initial grid and set the send-receive domains (ParMETIS) ---*/
    
    geometry_aux->SetColorGrid_Parallel(config_container[iZone]);
    
    /*--- Allocate the memory of the current domain, and
     divide the grid between the nodes ---*/
    
    geometry_container[iZone] = new CPhysicalGeometry(geometry_aux, config_container[iZone]);
    
    /*--- Deallocate the memory of geometry_aux ---*/
    
    delete geometry_aux;
    
    /*--- Add the Send/Receive boundaries ---*/
    
    geometry_container[iZone]->SetSendReceive(config_container[iZone]);
    
    /*--- Add the Send/Receive boundaries ---*/
    
    geometry_container[iZone]->SetBoundaries(config_container[iZone]);
    
  }
  
  /*--- Set up a timer for performance benchmarking (preprocessing time is included) ---*/
  
#ifdef HAVE_MPI
  StartTime = MPI_Wtime();
#else
  StartTime = su2double(clock())/su2double(CLOCKS_PER_SEC);
#endif
  
  for (iZone = 0; iZone < nZone; iZone++){
  
  if (rank == MASTER_NODE)
    cout << endl <<"----------------------- Preprocessing computations ----------------------" << endl;
  
  /*--- Compute elements surrounding points, points surrounding points ---*/
  
  if (rank == MASTER_NODE) cout << "Setting local point connectivity." <<endl;
    geometry_container[iZone]->SetPoint_Connectivity();
  
  /*--- Check the orientation before computing geometrical quantities ---*/
  
    geometry_container[iZone]->SetBoundVolume();
    if (config_container[iZone]->GetReorientElements()) {
      if (rank == MASTER_NODE) cout << "Checking the numerical grid orientation of the elements." <<endl;
      geometry_container[iZone]->Check_IntElem_Orientation(config_container[iZone]);
      geometry_container[iZone]->Check_BoundElem_Orientation(config_container[iZone]);
    }
  
  /*--- Create the edge structure ---*/
  
  if (rank == MASTER_NODE) cout << "Identify edges and vertices." <<endl;
    geometry_container[iZone]->SetEdges(); geometry_container[iZone]->SetVertex(config_container[iZone]);
  
  /*--- Compute center of gravity ---*/
  
  if (rank == MASTER_NODE) cout << "Computing centers of gravity." << endl;
  geometry_container[iZone]->SetCoord_CG();
  
  /*--- Create the dual control volume structures ---*/
  
  if (rank == MASTER_NODE) cout << "Setting the bound control volume structure." << endl;
  geometry_container[iZone]->SetBoundControlVolume(config_container[ZONE_0], ALLOCATE);

  /*--- Store the global to local mapping after preprocessing. ---*/
 
  if (rank == MASTER_NODE) cout << "Storing a mapping from global to local point index." << endl;
  geometry_container[iZone]->SetGlobal_to_Local_Point();
 
  /*--- Load the surface sensitivities from file. This is done only
   once: if this is an unsteady problem, a time-average of the surface
   sensitivities at each node is taken within this routine. ---*/
    if (!config_container[iZone]->GetDiscrete_Adjoint()){
      if (rank == MASTER_NODE) cout << "Reading surface sensitivities at each node from file." << endl;
      geometry_container[iZone]->SetBoundSensitivity(config_container[iZone]);
    } else {
      if (rank == MASTER_NODE) cout << "Reading volume sensitivities at each node from file." << endl;
      grid_movement[iZone] = new CVolumetricMovement(geometry_container[iZone], config_container[iZone]);
      geometry_container[iZone]->SetSensitivity(config_container[iZone]);

      if (rank == MASTER_NODE)
        cout << endl <<"---------------------- Mesh sensitivity computation ---------------------" << endl;
      grid_movement[iZone]->SetVolume_Deformation(geometry_container[iZone], config_container[iZone], false, true);

    }
  }

   if (config_container[ZONE_0]->GetDiscrete_Adjoint()){
     if (rank == MASTER_NODE)
       cout << endl <<"------------------------ Mesh sensitivity Output ------------------------" << endl;
     output = new COutput(config_container[ZONE_0]);
     output->SetSensitivity_Files(geometry_container, config_container, nZone);
   }

   if (config_container[ZONE_0]->GetDesign_Variable(0) != NONE){

     /*--- Initialize structure to store the gradient ---*/

     Gradient = new su2double*[config_container[ZONE_0]->GetnDV()];

     for (iDV = 0; iDV  < config_container[ZONE_0]->GetnDV(); iDV++){
       Gradient[iDV] = new su2double[config_container[ZONE_0]->GetnDV_Value(iDV)];
       for (iDV_Value = 0; iDV_Value < config_container[ZONE_0]->GetnDV_Value(iDV); iDV_Value++){
         Gradient[iDV][iDV_Value] = 0.0;
       }
     }

     if (rank == MASTER_NODE)
       cout << endl <<"---------- Start gradient evaluation using sensitivity information ----------" << endl;

     /*--- Write the gradient in a external file ---*/

     if (rank == MASTER_NODE) {
       cstr = new char [config_container[ZONE_0]->GetObjFunc_Grad_FileName().size()+1];
       strcpy (cstr, config_container[ZONE_0]->GetObjFunc_Grad_FileName().c_str());
       Gradient_file.open(cstr, ios::out);
     }

     /*--- Loop through each zone and add it's contribution to the gradient array ---*/

     for (iZone = 0; iZone < nZone; iZone++){

       /*--- Definition of the Class for surface deformation ---*/

       surface_movement[iZone] = new CSurfaceMovement();

       /*--- Copy coordinates to the surface structure ---*/

       surface_movement[iZone]->CopyBoundary(geometry_container[iZone], config_container[iZone]);

       /*--- If AD mode is enabled we can use it to compute the projection,
        *    otherwise we use finite differences. ---*/

       if (config_container[iZone]->GetAD_Mode()){
         SetProjection_AD(geometry_container[iZone], config_container[iZone], surface_movement[iZone] , Gradient);
       }else{
         SetProjection_FD(geometry_container[iZone], config_container[iZone], surface_movement[iZone] , Gradient);
       }
     }

     /*--- Print gradients to screen and file ---*/

     OutputGradient(Gradient, config_container[ZONE_0], Gradient_file);

     if (rank == MASTER_NODE)
       Gradient_file.close();

     for (iDV = 0; iDV  < config_container[ZONE_0]->GetnDV(); iDV++){
       delete [] Gradient[iDV];
     }
     delete [] Gradient;

   }

  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Solver Postprocessing -------------------------" << endl;
  
  if (geometry_container != NULL) {
    for (iZone = 0; iZone < nZone; iZone++) {
      if (geometry_container[iZone] != NULL) {
        delete geometry_container[iZone];
      }
    }
    delete [] geometry_container;
  }
  if (rank == MASTER_NODE) cout << "Deleted CGeometry container." << endl;
  
  if (surface_movement != NULL) {
    for (iZone = 0; iZone < nZone; iZone++) {
      if (surface_movement[iZone] != NULL) {
        delete surface_movement[iZone];
      }
    }
    delete [] surface_movement;
  }
  if (rank == MASTER_NODE) cout << "Deleted CSurfaceMovement class." << endl;
  
  if (grid_movement != NULL) {
    for (iZone = 0; iZone < nZone; iZone++) {
      if (grid_movement[iZone] != NULL) {
        delete grid_movement[iZone];
      }
    }
    delete [] grid_movement;
  }
  if (rank == MASTER_NODE) cout << "Deleted CVolumetricMovement class." << endl;
  
  delete config;
  config = NULL;
  if (config_container != NULL) {
    for (iZone = 0; iZone < nZone; iZone++) {
      if (config_container[iZone] != NULL) {
        delete config_container[iZone];
      }
    }
    delete [] config_container;
  }
  if (rank == MASTER_NODE) cout << "Deleted CConfig container." << endl;
  
  if (output != NULL) delete output;
  if (rank == MASTER_NODE) cout << "Deleted COutput class." << endl;

  if (cstr != NULL) delete cstr;
  
  /*--- Synchronization point after a single solver iteration. Compute the
   wall clock time required. ---*/
  
#ifdef HAVE_MPI
  StopTime = MPI_Wtime();
#else
  StopTime = su2double(clock())/su2double(CLOCKS_PER_SEC);
#endif
  
  /*--- Compute/print the total time for performance benchmarking. ---*/

  UsedTime = StopTime-StartTime;
  if (rank == MASTER_NODE) {
    cout << "\nCompleted in " << fixed << UsedTime << " seconds on "<< size;
    if (size == 1) cout << " core." << endl; else cout << " cores." << endl;
  }
  
  /*--- Exit the solver cleanly ---*/
  
  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Exit Success (SU2_DOT) ------------------------" << endl << endl;
  
  /*--- Finalize MPI parallelization ---*/
  
#ifdef HAVE_MPI
  SU2_MPI::Finalize();
#endif
  
  return EXIT_SUCCESS;
  
}
示例#3
0
int main(int argc, char *argv[]) {
  
  bool StopCalc = false;
  su2double StartTime = 0.0, StopTime = 0.0, UsedTime = 0.0;
  unsigned long ExtIter = 0;
  unsigned short iMesh, iZone, nZone, nDim;
  char config_file_name[MAX_STRING_SIZE];
  char runtime_file_name[MAX_STRING_SIZE];
  ofstream ConvHist_file;
  int rank = MASTER_NODE;
  int size = SINGLE_NODE;
  
  /*--- MPI initialization, and buffer setting ---*/
  
#ifdef HAVE_MPI
  int *bptr, bl;
  SU2_MPI::Init(&argc, &argv);
  MPI_Buffer_attach( malloc(BUFSIZE), BUFSIZE );
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &size);
#endif
  
  /*--- Create pointers to all of the classes that may be used throughout
   the SU2_CFD code. In general, the pointers are instantiated down a
   heirarchy over all zones, multigrid levels, equation sets, and equation
   terms as described in the comments below. ---*/
  
  CDriver *driver                         = NULL;
  CIteration **iteration_container        = NULL;
  COutput *output                         = NULL;
  CIntegration ***integration_container   = NULL;
  CGeometry ***geometry_container         = NULL;
  CSolver ****solver_container            = NULL;
  CNumerics *****numerics_container       = NULL;
  CConfig **config_container              = NULL;
  CSurfaceMovement **surface_movement     = NULL;
  CVolumetricMovement **grid_movement     = NULL;
  CFreeFormDefBox*** FFDBox               = NULL;
  CInterpolator ***interpolator_container = NULL;
  CTransfer ***transfer_container         = NULL;
  
  /*--- Load in the number of zones and spatial dimensions in the mesh file (If no config
   file is specified, default.cfg is used) ---*/
  
  if (argc == 2) { strcpy(config_file_name, argv[1]); }
  else { strcpy(config_file_name, "default.cfg"); }
  
  /*--- Read the name and format of the input mesh file to get from the mesh
   file the number of zones and dimensions from the numerical grid (required
   for variables allocation)  ---*/
  
  CConfig *config = NULL;
  config = new CConfig(config_file_name, SU2_CFD);
  
  nZone = GetnZone(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);
  nDim  = GetnDim(config->GetMesh_FileName(), config->GetMesh_FileFormat());
  delete config;
  /*--- Definition and of the containers for all possible zones. ---*/
  
  iteration_container    = new CIteration*[nZone];
  solver_container       = new CSolver***[nZone];
  integration_container  = new CIntegration**[nZone];
  numerics_container     = new CNumerics****[nZone];
  config_container       = new CConfig*[nZone];
  geometry_container     = new CGeometry**[nZone];
  surface_movement       = new CSurfaceMovement*[nZone];
  grid_movement          = new CVolumetricMovement*[nZone];
  FFDBox                 = new CFreeFormDefBox**[nZone];
  interpolator_container = new CInterpolator**[nZone];
  transfer_container     = new CTransfer**[nZone];
  
  for (iZone = 0; iZone < nZone; iZone++) {
    solver_container[iZone]       = NULL;
    integration_container[iZone]  = NULL;
    numerics_container[iZone]     = NULL;
    config_container[iZone]       = NULL;
    geometry_container[iZone]     = NULL;
    surface_movement[iZone]       = NULL;
    grid_movement[iZone]          = NULL;
    FFDBox[iZone]                 = NULL;
    interpolator_container[iZone] = NULL;
    transfer_container[iZone]     = NULL;
  }
  
  /*--- Loop over all zones to initialize the various classes. In most
   cases, nZone is equal to one. This represents the solution of a partial
   differential equation on a single block, unstructured mesh. ---*/
  
  for (iZone = 0; iZone < nZone; iZone++) {
    
    /*--- Definition of the configuration option class for all zones. In this
     constructor, the input configuration file is parsed and all options are
     read and stored. ---*/
    
    config_container[iZone] = new CConfig(config_file_name, SU2_CFD, iZone, nZone, nDim, VERB_HIGH);
    
    /*--- Definition of the geometry class to store the primal grid in the
     partitioning process. ---*/
    
    CGeometry *geometry_aux = NULL;
    
    /*--- All ranks process the grid and call ParMETIS for partitioning ---*/
    
    geometry_aux = new CPhysicalGeometry(config_container[iZone], iZone, nZone);
    
    /*--- Color the initial grid and set the send-receive domains (ParMETIS) ---*/
    
    geometry_aux->SetColorGrid_Parallel(config_container[iZone]);
    
    /*--- Allocate the memory of the current domain, and divide the grid
     between the ranks. ---*/
    
    geometry_container[iZone] = new CGeometry *[config_container[iZone]->GetnMGLevels()+1];
    geometry_container[iZone][MESH_0] = new CPhysicalGeometry(geometry_aux, config_container[iZone]);
    
    /*--- Deallocate the memory of geometry_aux ---*/
    
    delete geometry_aux;
    
    /*--- Add the Send/Receive boundaries ---*/
    
    geometry_container[iZone][MESH_0]->SetSendReceive(config_container[iZone]);
    
    /*--- Add the Send/Receive boundaries ---*/
    
    geometry_container[iZone][MESH_0]->SetBoundaries(config_container[iZone]);
    
  }

  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Geometry Preprocessing ------------------------" << endl;
  
  /*--- Preprocessing of the geometry for all zones. In this routine, the edge-
   based data structure is constructed, i.e. node and cell neighbors are
   identified and linked, face areas and volumes of the dual mesh cells are
   computed, and the multigrid levels are created using an agglomeration procedure. ---*/
  
  Geometrical_Preprocessing(geometry_container, config_container, nZone);
  
  for (iZone = 0; iZone < nZone; iZone++) {
    
    /*--- Computation of wall distances for turbulence modeling ---*/
    
    if (rank == MASTER_NODE)
      cout << "Computing wall distances." << endl;

    if ((config_container[iZone]->GetKind_Solver() == RANS) ||
        (config_container[iZone]->GetKind_Solver() == ADJ_RANS) ||
        (config_container[iZone]->GetKind_Solver() == DISC_ADJ_RANS))
      geometry_container[iZone][MESH_0]->ComputeWall_Distance(config_container[iZone]);
    
    /*--- Computation of positive surface area in the z-plane which is used for
     the calculation of force coefficient (non-dimensionalization). ---*/
    
    geometry_container[iZone][MESH_0]->SetPositive_ZArea(config_container[iZone]);
    
    /*--- Set the near-field, interface and actuator disk boundary conditions, if necessary. ---*/
    
    for (iMesh = 0; iMesh <= config_container[iZone]->GetnMGLevels(); iMesh++) {
      geometry_container[iZone][iMesh]->MatchNearField(config_container[iZone]);
      geometry_container[iZone][iMesh]->MatchInterface(config_container[iZone]);
      geometry_container[iZone][iMesh]->MatchActuator_Disk(config_container[iZone]);
    }
    
  }
  
  /*--- If activated by the compile directive, perform a partition analysis. ---*/
#if PARTITION
  Partition_Analysis(geometry_container[ZONE_0][MESH_0], config_container[ZONE_0]);
#endif
  
  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Driver Preprocessing --------------------------" << endl;
  
  /*--- First, given the basic information about the number of zones and the
   solver types from the config, instantiate the appropriate driver for the problem. ---*/
  
  Driver_Preprocessing(&driver, iteration_container, solver_container,
                       geometry_container, integration_container, numerics_container,
                       interpolator_container, transfer_container, config_container, nZone, nDim);
  
  
  /*--- Instantiate the geometry movement classes for the solution of unsteady
   flows on dynamic meshes, including rigid mesh transformations, dynamically
   deforming meshes, and time-spectral preprocessing. ---*/
  
  for (iZone = 0; iZone < nZone; iZone++) {
    
    if (config_container[iZone]->GetGrid_Movement() ||
        (config_container[iZone]->GetDirectDiff() == D_DESIGN)) {
      if (rank == MASTER_NODE)
        cout << "Setting dynamic mesh structure." << endl;
      grid_movement[iZone] = new CVolumetricMovement(geometry_container[iZone][MESH_0], config_container[iZone]);
      FFDBox[iZone] = new CFreeFormDefBox*[MAX_NUMBER_FFD];
      surface_movement[iZone] = new CSurfaceMovement();
      surface_movement[iZone]->CopyBoundary(geometry_container[iZone][MESH_0], config_container[iZone]);
      /*if (config_container[iZone]->GetUnsteady_Simulation() == SPECTRAL_METHOD && config_container[iZone]->GetGrid_Movement())
        SetGrid_Movement(geometry_container[iZone], surface_movement[iZone], grid_movement[iZone],
                         FFDBox[iZone], solver_container[iZone], config_container[iZone], iZone, 0, 0);*/
    }
    
    if (config_container[iZone]->GetDirectDiff() == D_DESIGN){
      if (rank == MASTER_NODE)
        cout << "Setting surface/volume derivatives." << endl;
      
      /*--- Set the surface derivatives, i.e. the derivative of the surface mesh nodes with respect to the design variables ---*/
      
      surface_movement[iZone]->SetSurface_Derivative(geometry_container[iZone][MESH_0],config_container[iZone]);
      cout << "Done setting Surface Derivatives " << endl;
      /*--- Call the volume deformation routine with derivative mode enabled.
       This computes the derivative of the volume mesh with respect to the surface nodes ---*/
      
      grid_movement[iZone]->SetVolume_Deformation(geometry_container[iZone][MESH_0],config_container[iZone], true, true);
      cout << "Done SetVolume_Deformation " << endl;
      /*--- Update the multi-grid structure to propagate the derivative information to the coarser levels ---*/
      
      geometry_container[iZone][MESH_0]->UpdateGeometry(geometry_container[iZone],config_container[iZone]);
      
      /*--- Set the derivative of the wall-distance with respect to the surface nodes ---*/
      
      if ( (config_container[iZone]->GetKind_Solver() == RANS) ||
          (config_container[iZone]->GetKind_Solver() == ADJ_RANS) ||
          (config_container[iZone]->GetKind_Solver() == DISC_ADJ_RANS))
        geometry_container[iZone][MESH_0]->ComputeWall_Distance(config_container[iZone]);
    }

    
  }
  
  /*--- Coupling between zones (limited to two zones at the moment) ---*/

  bool fsi = config_container[ZONE_0]->GetFSI_Simulation();
  
  if ((nZone == 2) && !(fsi)) {
    if (rank == MASTER_NODE)
      cout << endl <<"--------------------- Setting Coupling Between Zones --------------------" << endl;
    geometry_container[ZONE_0][MESH_0]->MatchZone(config_container[ZONE_0], geometry_container[ZONE_1][MESH_0],
                                                  config_container[ZONE_1], ZONE_0, nZone);
    geometry_container[ZONE_1][MESH_0]->MatchZone(config_container[ZONE_1], geometry_container[ZONE_0][MESH_0],
                                                  config_container[ZONE_0], ZONE_1, nZone);
  }
  
  /*--- Definition of the output class (one for all zones). The output class
   manages the writing of all restart, volume solution, surface solution,
   surface comma-separated value, and convergence history files (both in serial
   and in parallel). ---*/
  
  output = new COutput();
  
  /*--- Open the convergence history file ---*/
  
  if (rank == MASTER_NODE)
    output->SetConvHistory_Header(&ConvHist_file, config_container[ZONE_0]);
  
  /*--- Check for an unsteady restart. Update ExtIter if necessary. ---*/
  if (config_container[ZONE_0]->GetWrt_Unsteady() && config_container[ZONE_0]->GetRestart())
    ExtIter = config_container[ZONE_0]->GetUnst_RestartIter();
  
  /*--- Check for a dynamic restart (structural analysis). Update ExtIter if necessary. ---*/
  if (config_container[ZONE_0]->GetKind_Solver() == FEM_ELASTICITY
		  && config_container[ZONE_0]->GetWrt_Dynamic() && config_container[ZONE_0]->GetRestart())
	  	  ExtIter = config_container[ZONE_0]->GetDyn_RestartIter();

  /*--- Initiate value at each interface for the mixing plane ---*/
  if(config_container[ZONE_0]->GetBoolMixingPlane())
  	for (iZone = 0; iZone < nZone; iZone++)
  	  iteration_container[iZone]->Preprocess(output, integration_container, geometry_container, solver_container, numerics_container, config_container, surface_movement, grid_movement, FFDBox, iZone);

  /*--- Main external loop of the solver. Within this loop, each iteration ---*/
  
  if (rank == MASTER_NODE)
    cout << endl <<"------------------------------ Begin Solver -----------------------------" << endl;
  
  /*--- Set up a timer for performance benchmarking (preprocessing time is not included) ---*/
  
#ifndef HAVE_MPI
  StartTime = su2double(clock())/su2double(CLOCKS_PER_SEC);
#else
  StartTime = MPI_Wtime();
#endif

  /*--- This is temporal and just to check. It will have to be added to the regular history file ---*/
  
  ofstream historyFile_FSI;
  bool writeHistFSI = config_container[ZONE_0]->GetWrite_Conv_FSI();
  if (writeHistFSI && (rank == MASTER_NODE)){
    char cstrFSI[200];
    string filenameHistFSI = config_container[ZONE_0]->GetConv_FileName_FSI();
    strcpy (cstrFSI, filenameHistFSI.data());
    historyFile_FSI.open (cstrFSI);
    historyFile_FSI << "Time,Iteration,Aitken,URes,logResidual,orderMagnResidual" << endl;
    historyFile_FSI.close();
  }

  while (ExtIter < config_container[ZONE_0]->GetnExtIter()) {
    
    /*--- Set the value of the external iteration. ---*/
	for (iZone = 0; iZone < nZone; iZone++) config_container[iZone]->SetExtIter(ExtIter);

    
    /*--- Read the target pressure ---*/
    
    if (config_container[ZONE_0]->GetInvDesign_Cp() == YES)
      output->SetCp_InverseDesign(solver_container[ZONE_0][MESH_0][FLOW_SOL],
                                  geometry_container[ZONE_0][MESH_0], config_container[ZONE_0], ExtIter);
    
    /*--- Read the target heat flux ---*/
    
    if (config_container[ZONE_0]->GetInvDesign_HeatFlux() == YES)
      output->SetHeat_InverseDesign(solver_container[ZONE_0][MESH_0][FLOW_SOL],
                                    geometry_container[ZONE_0][MESH_0], config_container[ZONE_0], ExtIter);
    
    /*--- Perform a single iteration of the chosen PDE solver. ---*/

      /*--- Run a single iteration of the problem using the driver class. ---*/

      driver->Run(iteration_container, output, integration_container,
                  geometry_container, solver_container, numerics_container,
                  config_container, surface_movement, grid_movement, FFDBox,
                  interpolator_container, transfer_container);
      
    
    /*--- Synchronization point after a single solver iteration. Compute the
     wall clock time required. ---*/
    
#ifndef HAVE_MPI
    StopTime = su2double(clock())/su2double(CLOCKS_PER_SEC);
#else
    StopTime = MPI_Wtime();
#endif
    
    UsedTime = (StopTime - StartTime);
    
    /*--- For specific applications, evaluate and plot the equivalent area. ---*/
    
    if (config_container[ZONE_0]->GetEquivArea() == YES) {
      output->SetEquivalentArea(solver_container[ZONE_0][MESH_0][FLOW_SOL],
                                geometry_container[ZONE_0][MESH_0], config_container[ZONE_0], ExtIter);
    }
    
    /*--- Check if there is any change in the runtime parameters ---*/
    
    CConfig *runtime = NULL;
    strcpy(runtime_file_name, "runtime.dat");
    runtime = new CConfig(runtime_file_name, config_container[ZONE_0]);
    runtime->SetExtIter(ExtIter);
    
	/*--- Update the convergence history file (serial and parallel computations). ---*/

	if (!fsi){
		output->SetConvHistory_Body(&ConvHist_file, geometry_container, solver_container,
				config_container, integration_container, false, UsedTime, ZONE_0);

	}

    
    /*--- Evaluate the new CFL number (adaptive). ---*/
    
    if (config_container[ZONE_0]->GetCFL_Adapt() == YES) {
      output->SetCFL_Number(solver_container, config_container, ZONE_0);
    }
    
    /*--- Check whether the current simulation has reached the specified
     convergence criteria, and set StopCalc to true, if so. ---*/
    
    switch (config_container[ZONE_0]->GetKind_Solver()) {
      case EULER: case NAVIER_STOKES: case RANS:
        StopCalc = integration_container[ZONE_0][FLOW_SOL]->GetConvergence(); break;
      case WAVE_EQUATION:
        StopCalc = integration_container[ZONE_0][WAVE_SOL]->GetConvergence(); break;
      case HEAT_EQUATION:
        StopCalc = integration_container[ZONE_0][HEAT_SOL]->GetConvergence(); break;
	  case FEM_ELASTICITY:
	    StopCalc = integration_container[ZONE_0][FEA_SOL]->GetConvergence(); break;
      case ADJ_EULER: case ADJ_NAVIER_STOKES: case ADJ_RANS:
      case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES: case DISC_ADJ_RANS:
        StopCalc = integration_container[ZONE_0][ADJFLOW_SOL]->GetConvergence(); break;
    }
    
		/*--- Solution output. Determine whether a solution needs to be written
		 after the current iteration, and if so, execute the output file writing
		 routines. ---*/
		
		if ((ExtIter+1 >= config_container[ZONE_0]->GetnExtIter())
				
				||
				
				((ExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq() == 0) && (ExtIter != 0) &&
				 !((config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
					 (config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_2ND) ||
					 (config_container[ZONE_0]->GetUnsteady_Simulation() == TIME_STEPPING)))
				
				||
				
				(StopCalc)
				
				||
				
				(((config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
				 (config_container[ZONE_0]->GetUnsteady_Simulation() == TIME_STEPPING)) &&
				 ((ExtIter == 0) || (ExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0)))
				
				||
				
				((config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_2ND) && (!fsi) &&
				 ((ExtIter == 0) || ((ExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0) ||
														 ((ExtIter-1) % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0))))
				
				||
				
				((config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_2ND) && (fsi) &&
				 ((ExtIter == 0) || ((ExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0))))

				||

				(((config_container[ZONE_0]->GetDynamic_Analysis() == DYNAMIC) &&
						 ((ExtIter == 0) || (ExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0))))){

					
          /*--- Low-fidelity simulations (using a coarser multigrid level
           approximation to the solution) require an interpolation back to the
           finest grid. ---*/
          
          if (config_container[ZONE_0]->GetLowFidelitySim()) {
            integration_container[ZONE_0][FLOW_SOL]->SetProlongated_Solution(RUNTIME_FLOW_SYS, solver_container[ZONE_0][MESH_0][FLOW_SOL], solver_container[ZONE_0][MESH_1][FLOW_SOL], geometry_container[ZONE_0][MESH_0], geometry_container[ZONE_0][MESH_1], config_container[ZONE_0]);
            integration_container[ZONE_0][FLOW_SOL]->Smooth_Solution(RUNTIME_FLOW_SYS, solver_container[ZONE_0][MESH_0][FLOW_SOL], geometry_container[ZONE_0][MESH_0], 3, 1.25, config_container[ZONE_0]);
            solver_container[ZONE_0][MESH_0][config_container[ZONE_0]->GetContainerPosition(RUNTIME_FLOW_SYS)]->Set_MPI_Solution(geometry_container[ZONE_0][MESH_0], config_container[ZONE_0]);
            solver_container[ZONE_0][MESH_0][config_container[ZONE_0]->GetContainerPosition(RUNTIME_FLOW_SYS)]->Preprocessing(geometry_container[ZONE_0][MESH_0], solver_container[ZONE_0][MESH_0], config_container[ZONE_0], MESH_0, 0, RUNTIME_FLOW_SYS, true);
          }


          if (rank == MASTER_NODE) cout << endl << "-------------------------- File Output Summary --------------------------";
          
          /*--- Execute the routine for writing restart, volume solution,
           surface solution, and surface comma-separated value files. ---*/
          
          output->SetResult_Files(solver_container, geometry_container, config_container, ExtIter, nZone);
          
          /*--- Output a file with the forces breakdown. ---*/
          
          output->SetForces_Breakdown(geometry_container, solver_container,
                                      config_container, integration_container, ZONE_0);
          
          /*--- Compute the forces at different sections. ---*/
          
          if (config_container[ZONE_0]->GetPlot_Section_Forces()) {
            output->SetForceSections(solver_container[ZONE_0][MESH_0][FLOW_SOL],
                                     geometry_container[ZONE_0][MESH_0], config_container[ZONE_0], ExtIter);
          }
          
          if (rank == MASTER_NODE) cout << "-------------------------------------------------------------------------" << endl << endl;
          
        }
    
    /*--- If the convergence criteria has been met, terminate the simulation. ---*/
    
    if (StopCalc) break;
    
    ExtIter++;
    
  }
  
  /*--- Output some information to the console. ---*/
  
  if (rank == MASTER_NODE) {
    
    /*--- Print out the number of non-physical points and reconstructions ---*/
    
    if (config_container[ZONE_0]->GetNonphysical_Points() > 0)
      cout << "Warning: there are " << config_container[ZONE_0]->GetNonphysical_Points() << " non-physical points in the solution." << endl;
    if (config_container[ZONE_0]->GetNonphysical_Reconstr() > 0)
      cout << "Warning: " << config_container[ZONE_0]->GetNonphysical_Reconstr() << " reconstructed states for upwinding are non-physical." << endl;
    
    /*--- Close the convergence history file. ---*/
    
    ConvHist_file.close();
    cout << "History file, closed." << endl;
  }
  
  /*--- Deallocations: further work is needed,
   * these routines can be used to check for memory leaks---*/
  /*
  if (rank == MASTER_NODE)
      cout << endl <<"------------------------ Driver Postprocessing ------------------------" << endl;

  driver->Postprocessing(iteration_container, solver_container, geometry_container,
      integration_container, numerics_container, interpolator_container,
      transfer_container, config_container, nZone);

  delete driver;
  */

  /*--- Geometry class deallocation ---*/
  if (rank == MASTER_NODE)
        cout << endl <<"------------------------ Geometry Postprocessing ------------------------" << endl;
  for (iZone = 0; iZone < nZone; iZone++) {
    if (geometry_container[iZone]!=NULL){
      for (unsigned short iMGlevel = 1; iMGlevel < config_container[iZone]->GetnMGLevels()+1; iMGlevel++){
        if (geometry_container[iZone][iMGlevel]!=NULL) delete geometry_container[iZone][iMGlevel];
      }
      delete [] geometry_container[iZone];
    }
  }
  delete [] geometry_container;

  /*--- Free-form deformation class deallocation ---*/
  for (iZone = 0; iZone < nZone; iZone++) {
    delete FFDBox[iZone];
  }
  delete [] FFDBox;

  /*--- Grid movement and surface movement class deallocation ---*/
  delete [] surface_movement;
  delete [] grid_movement;

  /*Deallocate config container*/
  if (rank == MASTER_NODE)
        cout << endl <<"------------------------- Config Postprocessing -------------------------" << endl;
  if (config_container!=NULL){
    for (iZone = 0; iZone < nZone; iZone++) {
      if (config_container[iZone]!=NULL){
        delete config_container[iZone];
      }
    }
    delete [] config_container;
  }

  /*--- Deallocate output container ---*/
  if (output!=NULL) delete output;

  /*--- Synchronization point after a single solver iteration. Compute the
   wall clock time required. ---*/
  
#ifndef HAVE_MPI
  StopTime = su2double(clock())/su2double(CLOCKS_PER_SEC);
#else
  StopTime = MPI_Wtime();
#endif
  
  /*--- Compute/print the total time for performance benchmarking. ---*/
  
  UsedTime = StopTime-StartTime;
  if (rank == MASTER_NODE) {
    cout << "\nCompleted in " << fixed << UsedTime << " seconds on "<< size;
    if (size == 1) cout << " core." << endl; else cout << " cores." << endl;
  }
  
  /*--- Exit the solver cleanly ---*/
  
  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Exit Success (SU2_CFD) ------------------------" << endl << endl;

#ifdef HAVE_MPI
  /*--- Finalize MPI parallelization ---*/
  MPI_Buffer_detach(&bptr, &bl);
  MPI_Finalize();
#endif

  return EXIT_SUCCESS;

}
示例#4
0
文件: SU2_GPC.cpp 项目: wkernkamp/SU2
int main(int argc, char *argv[]) {	
  
  /*--- Local variables ---*/
	unsigned short iMarker, iDim, iDV, iFFDBox, nZone = 1;
	unsigned long iVertex, iPoint;
	double delta_eps, my_Gradient, Gradient, *Normal, dS;
  double *VarCoord, Sensitivity;
	double dalpha[3], deps[3], dalpha_deps;
	char *cstr;
	ofstream Gradient_file, Jacobian_file;
	bool *UpdatePoint, Comma;
	int rank = MASTER_NODE;
	int size = SINGLE_NODE;
  
#ifndef NO_MPI
	/*--- MPI initialization, and buffer setting ---*/
	MPI::Init(argc,argv);
	rank = MPI::COMM_WORLD.Get_rank();
  size = MPI::COMM_WORLD.Get_size();
#endif
	
	/*--- Pointer to different structures that will be used throughout the entire code ---*/
	CFreeFormDefBox** FFDBox = NULL;
	CConfig *config = NULL;
	CGeometry *boundary = NULL;
	CSurfaceMovement *surface_mov = NULL;
	
	/*--- Definition of the Class for the definition of the problem ---*/
	if (argc == 2) config = new CConfig(argv[1], SU2_GPC, ZONE_0, nZone, VERB_HIGH);
	else {
		char grid_file[200];
		strcpy (grid_file, "default.cfg");
		config = new CConfig(grid_file, SU2_GPC, ZONE_0, nZone, VERB_HIGH);
	}
	
#ifndef NO_MPI
	/*--- Change the name of the input-output files for the 
	 parallel computation ---*/
	config->SetFileNameDomain(rank+1);
#endif
	
	/*--- Definition of the Class for the boundary of the geometry,
   note that the orientation of the elements is not checked ---*/
	boundary = new CBoundaryGeometry(config, config->GetMesh_FileName(), config->GetMesh_FileFormat());
  
  /*--- Perform the non-dimensionalization, in case any values are needed ---*/
  config->SetNondimensionalization(boundary->GetnDim(), ZONE_0);
  
	if (rank == MASTER_NODE)
		cout << endl <<"----------------------- Preprocessing computations ----------------------" << endl;
	
  /*--- Boundary geometry preprocessing ---*/
	if (rank == MASTER_NODE) cout << "Identify vertices." <<endl; 
	boundary->SetVertex();
	
	/*--- Create the control volume structures ---*/
	if (rank == MASTER_NODE) cout << "Set boundary control volume structure." << endl; 
	boundary->SetBoundControlVolume(config, ALLOCATE);
  
  /*--- Load the surface sensitivities from file. This is done only
   once: if this is an unsteady problem, a time-average of the surface
   sensitivities at each node is taken within this routine. ---*/
  if (rank == MASTER_NODE) cout << "Reading surface sensitivities at each node from file." << endl; 
  boundary->SetBoundSensitivity(config);
  
  /*--- Boolean controlling points to be updated ---*/
	UpdatePoint = new bool[boundary->GetnPoint()];
	
	/*--- Definition of the Class for surface deformation ---*/
	surface_mov = new CSurfaceMovement();
	
	/*--- Definition of the FFD deformation class ---*/
	unsigned short nFFDBox = MAX_NUMBER_FFD;
	FFDBox = new CFreeFormDefBox*[nFFDBox];
	
	if (rank == MASTER_NODE) 
		cout << endl <<"---------- Start gradient evaluation using surface sensitivity ----------" << endl;
	
	/*--- Write the gradient in a external file ---*/
	if (rank == MASTER_NODE) {
		cstr = new char [config->GetObjFunc_Grad_FileName().size()+1];
		strcpy (cstr, config->GetObjFunc_Grad_FileName().c_str());
		Gradient_file.open(cstr, ios::out);
    
    /*--- Write an additional file with the geometric Jacobian ---*/
    /*--- WARNING: This is only for serial calculations!!! ---*/
    if (size == SINGLE_NODE) {
      Jacobian_file.open("geo_jacobian.csv", ios::out);
      Jacobian_file.precision(15);
      
      /*--- Write the CSV file header ---*/
      Comma = false;
      for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
        if (config->GetMarker_All_DV(iMarker) == YES) {
          for (iVertex = 0; iVertex < boundary->nVertex[iMarker]; iVertex++) {
            iPoint = boundary->vertex[iMarker][iVertex]->GetNode();
            if (!Comma) { Jacobian_file << "\t\"DesignVariable\""; Comma = true;}
            Jacobian_file  << ", " << "\t\"" << iPoint << "\"";
          }
        }
      }
      Jacobian_file << endl;
    }
	}
  
	for (iDV = 0; iDV < config->GetnDV(); iDV++) {
				
    if (size == SINGLE_NODE) {
      Jacobian_file << iDV;
    }
    
		/*--- Bump deformation for 2D problems ---*/
		if (boundary->GetnDim() == 2) {
			
			if (rank == MASTER_NODE)
				cout << "Perform 2D deformation of the surface." << endl;
			
			switch ( config->GetDesign_Variable(iDV) ) {
				case COSINE_BUMP :    surface_mov->SetCosBump(boundary, config, iDV, true); break;
				case FOURIER :        surface_mov->SetFourier(boundary, config, iDV, true); break;
				case HICKS_HENNE :    surface_mov->SetHicksHenne(boundary, config, iDV, true); break;
				case DISPLACEMENT :   surface_mov->SetDisplacement(boundary, config, iDV, true); break;
				case ROTATION :       surface_mov->SetRotation(boundary, config, iDV, true); break;
				case NACA_4DIGITS :   surface_mov->SetNACA_4Digits(boundary, config); break;
				case PARABOLIC :      surface_mov->SetParabolic(boundary, config); break;
			}
			
		}
		
		/*--- Free Form deformation for 3D problems ---*/
		if (boundary->GetnDim() == 3) {
			
      if (config->GetDesign_Variable(0) == SPHERICAL)  {
        
        if (rank == MASTER_NODE) {
          cout << endl << "Design variable number "<< iDV <<"." << endl;
          cout << "Spherical DV: Perform 3D deformation of the surface." << endl;
        }
        surface_mov->SetSpherical(boundary, config, iDV, true);
        
      }
      else {
        
        /*--- Read the FFD information in the first iteration ---*/
        if (iDV == 0) {
          
          if (rank == MASTER_NODE)
            cout << "Read the FFD information from mesh file." << endl;
          
          /*--- Read the FFD information from the grid file ---*/
          surface_mov->ReadFFDInfo(boundary, config, FFDBox, config->GetMesh_FileName(), true);
          
          /*--- If the FFDBox was not defined in the input file ---*/
          if (!surface_mov->GetFFDBoxDefinition() && (rank == MASTER_NODE)) {
            cout << "The input grid doesn't have the entire FFD information!" << endl;
            cout << "Press any key to exit..." << endl;
            cin.get();
          }
          
          if (rank == MASTER_NODE)
            cout <<"-------------------------------------------------------------------------" << endl;
          
        }
        
        if (rank == MASTER_NODE) {
          cout << endl << "Design variable number "<< iDV <<"." << endl;
          cout << "Perform 3D deformation of the surface." << endl;
        }
        
        /*--- Apply the control point change ---*/
        for (iFFDBox = 0; iFFDBox < surface_mov->GetnFFDBox(); iFFDBox++) {
          
          switch ( config->GetDesign_Variable(iDV) ) {
            case FFD_CONTROL_POINT : surface_mov->SetFFDCPChange(boundary, config, FFDBox[iFFDBox], iFFDBox, iDV, true); break;
            case FFD_DIHEDRAL_ANGLE : surface_mov->SetFFDDihedralAngle(boundary, config, FFDBox[iFFDBox], iFFDBox, iDV, true); break;
            case FFD_TWIST_ANGLE : surface_mov->SetFFDTwistAngle(boundary, config, FFDBox[iFFDBox], iFFDBox, iDV, true); break;
            case FFD_ROTATION : surface_mov->SetFFDRotation(boundary, config, FFDBox[iFFDBox], iFFDBox, iDV, true); break;
            case FFD_CAMBER : surface_mov->SetFFDCamber(boundary, config, FFDBox[iFFDBox], iFFDBox, iDV, true); break;
            case FFD_THICKNESS : surface_mov->SetFFDThickness(boundary, config, FFDBox[iFFDBox], iFFDBox, iDV, true); break;
            case FFD_VOLUME : surface_mov->SetFFDVolume(boundary, config, FFDBox[iFFDBox], iFFDBox, iDV, true); break;
          }
          
          /*--- Recompute cartesian coordinates using the new control points position ---*/
          surface_mov->SetCartesianCoord(boundary, config, FFDBox[iFFDBox], iFFDBox);
        }
      }
			
		}
		
		/*--- Continuous adjoint gradient computation ---*/
		if (rank == MASTER_NODE)
			cout << "Evaluate functional gradient using the continuous adjoint strategy." << endl;
		
    /*--- Load the delta change in the design variable (finite difference step). ---*/
		delta_eps = config->GetDV_Value(iDV);
    my_Gradient = 0.0; Gradient = 0.0;
      
      /*--- Reset update points ---*/
      for (iPoint = 0; iPoint < boundary->GetnPoint(); iPoint++)
        UpdatePoint[iPoint] = true;
      
      for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
				if (config->GetMarker_All_DV(iMarker) == YES) {
					for (iVertex = 0; iVertex < boundary->nVertex[iMarker]; iVertex++) {
						
						iPoint = boundary->vertex[iMarker][iVertex]->GetNode();
						if ((iPoint < boundary->GetnPointDomain()) && UpdatePoint[iPoint]) {
							
							Normal = boundary->vertex[iMarker][iVertex]->GetNormal();
							VarCoord = boundary->vertex[iMarker][iVertex]->GetVarCoord();
							Sensitivity = boundary->vertex[iMarker][iVertex]->GetAuxVar();
							
							dS = 0.0; 
							for (iDim = 0; iDim < boundary->GetnDim(); iDim++) {
								dS += Normal[iDim]*Normal[iDim];
								deps[iDim] = VarCoord[iDim] / delta_eps;
							}
							dS = sqrt(dS);
							
							dalpha_deps = 0.0;
							for (iDim = 0; iDim < boundary->GetnDim(); iDim++) {
								dalpha[iDim] = Normal[iDim] / dS;
								dalpha_deps -= dalpha[iDim]*deps[iDim];
							}
							
              /*--- Store the geometric sensitivity for this DV (rows) & this node (column) ---*/
              if (size == SINGLE_NODE) {
                Jacobian_file  << ", " << dalpha_deps;
              }
              
							my_Gradient += Sensitivity*dalpha_deps;
							UpdatePoint[iPoint] = false;
						}
					}
				}				
    }
    
#ifndef NO_MPI
		MPI::COMM_WORLD.Allreduce(&my_Gradient, &Gradient, 1, MPI::DOUBLE, MPI::SUM); 
#else
		Gradient = my_Gradient;
#endif
		
		if (rank == MASTER_NODE) {
			switch (config->GetKind_ObjFunc()) {
				case LIFT_COEFFICIENT : 
					if (iDV == 0) Gradient_file << "Lift coeff. grad. using cont. adj." << endl;
					cout << "Lift coefficient gradient: "<< Gradient << "." << endl; break;
				case DRAG_COEFFICIENT : 
					if (iDV == 0) Gradient_file << "Drag coeff. grad. using cont. adj." << endl;
					cout << "Drag coefficient gradient: "<< Gradient << "." << endl; break;
				case SIDEFORCE_COEFFICIENT :
					if (iDV == 0) Gradient_file << "Sideforce coeff. grad. using cont. adj." << endl;
					cout << "Sideforce coefficient gradient: "<< Gradient << "." << endl; break;
				case MOMENT_X_COEFFICIENT :
					if (iDV == 0) Gradient_file << "Moment x coeff. grad. using cont. adj." << endl;
					cout << "Moment x coefficient gradient: "<< Gradient << "." << endl; break;
				case MOMENT_Y_COEFFICIENT :
					if (iDV == 0) Gradient_file << "Moment y coeff. grad. using cont. adj." << endl;
					cout << "Moment y coefficient gradient: "<< Gradient << "." << endl; break;
				case MOMENT_Z_COEFFICIENT :
					if (iDV == 0) Gradient_file << "Moment z coeff. grad. using cont. adj." << endl;
					cout << "Moment z coefficient gradient: "<< Gradient << "." << endl; break;
				case EFFICIENCY :
					if (iDV == 0) Gradient_file << "Efficiency coeff. grad. using cont. adj." << endl;
					cout << "Efficiency coefficient gradient: "<< Gradient << "." << endl; break;
				case EQUIVALENT_AREA :
					if (iDV == 0) Gradient_file << "Equivalent area coeff. grad. using cont. adj." << endl;
					cout << "Equivalent Area coefficient gradient: "<< Gradient << "." << endl; break;
				case NEARFIELD_PRESSURE :
					if (iDV == 0) Gradient_file << "Near-field pressure coeff. grad. using cont. adj." << endl;
					cout << "Near-field pressure coefficient gradient: "<< Gradient << "." << endl; break;
				case FORCE_X_COEFFICIENT :
					if (iDV == 0) Gradient_file << "Force x coeff. grad. using cont. adj." << endl;
					cout << "Force x coefficient gradient: "<< Gradient << "." << endl; break;
				case FORCE_Y_COEFFICIENT :
					if (iDV == 0) Gradient_file << "Force y coeff. grad. using cont. adj." << endl;
					cout << "Force y coefficient gradient: "<< Gradient << "." << endl; break;
				case FORCE_Z_COEFFICIENT :
					if (iDV == 0) Gradient_file << "Force z coeff. grad. using cont. adj." << endl;
					cout << "Force z coefficient gradient: "<< Gradient << "." << endl; break;
				case THRUST_COEFFICIENT :
					if (iDV == 0) Gradient_file << "Thrust coeff. grad. using cont. adj."<< endl;
					cout << "Thrust coefficient gradient: "<< Gradient << "." << endl; break;
				case TORQUE_COEFFICIENT :
					if (iDV == 0) Gradient_file << "Torque coeff. grad. using cont. adj."<< endl;
					cout << "Torque coefficient gradient: "<< Gradient << "." << endl; break;
				case FIGURE_OF_MERIT :
					if (iDV == 0) Gradient_file << "Rotor Figure of Merit grad. using cont. adj."<< endl;
					cout << "Rotor Figure of Merit gradient: "<< Gradient << "." << endl; break;
				case FREE_SURFACE :
					if (iDV == 0) Gradient_file << "Free-Surface grad. using cont. adj."<< endl;
					cout << "Free-surface gradient: "<< Gradient << "." << endl; break;
        case HEAT_LOAD :
					if (iDV == 0) Gradient_file << "Integrated surface heat flux. using cont. adj."<< endl;
					cout << "Heat load gradient: "<< Gradient << "." << endl; break;
          
			}
			
			Gradient_file << Gradient << endl;
			
			cout <<"-------------------------------------------------------------------------" << endl;
			      
    }
		
    /*--- End the line for the current DV in the geometric Jacobian file ---*/
    if (size == SINGLE_NODE) Jacobian_file << endl;
	}
	
	if (rank == MASTER_NODE)
		Gradient_file.close();
  
  if (size == SINGLE_NODE)
    Jacobian_file.close();
	
	delete [] UpdatePoint;
	
#ifndef NO_MPI
	/*--- Finalize MPI parallelization ---*/
	MPI::Finalize();
#endif
	
	/*--- End solver ---*/
	if (rank == MASTER_NODE) 
	  cout << endl <<"------------------------- Exit Success (SU2_GPC) ------------------------" << endl << endl;
	
	return EXIT_SUCCESS;
	
}
示例#5
0
文件: SU2_CFD.cpp 项目: jilott/SU2
int main(int argc, char *argv[]) {
  bool StopCalc = false;
  unsigned long StartTime, StopTime, TimeUsed = 0, ExtIter = 0;
  unsigned short iMesh, iZone, iSol, nZone, nDim;
  ofstream ConvHist_file;
  int rank = MASTER_NODE;
  
#ifndef NO_MPI
  /*--- MPI initialization, and buffer setting ---*/
  void *buffer, *old_buffer;
  int size, bufsize;
  bufsize = MAX_MPI_BUFFER;
  buffer = new char[bufsize];
  MPI::Init(argc, argv);
  MPI::Attach_buffer(buffer, bufsize);
  rank = MPI::COMM_WORLD.Get_rank();
  size = MPI::COMM_WORLD.Get_size();
#ifdef TIME
  /*--- Set up a timer for parallel performance benchmarking ---*/
  double start, finish, time;
  MPI::COMM_WORLD.Barrier();
  start = MPI::Wtime();
#endif
#endif
  
  /*--- Create pointers to all of the classes that may be used throughout
   the SU2_CFD code. In general, the pointers are instantiated down a
   heirarchy over all zones, multigrid levels, equation sets, and equation
   terms as described in the comments below. ---*/
  
  COutput *output                       = NULL;
  CIntegration ***integration_container = NULL;
  CGeometry ***geometry_container       = NULL;
  CSolver ****solver_container          = NULL;
  CNumerics *****numerics_container     = NULL;
  CConfig **config_container            = NULL;
  CSurfaceMovement **surface_movement   = NULL;
  CVolumetricMovement **grid_movement   = NULL;
  CFreeFormDefBox*** FFDBox             = NULL;
  
  /*--- Load in the number of zones and spatial dimensions in the mesh file (If no config
   file is specified, default.cfg is used) ---*/
  
  char config_file_name[200];
  if (argc == 2){ strcpy(config_file_name,argv[1]); }
  else{ strcpy(config_file_name, "default.cfg"); }
  
  /*--- Read the name and format of the input mesh file ---*/
  
  CConfig *config = NULL;
  config = new CConfig(config_file_name);
  
  /*--- Get the number of zones and dimensions from the numerical grid
   (required for variables allocation) ---*/
  
  nZone = GetnZone(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);
  nDim  = GetnDim(config->GetMesh_FileName(), config->GetMesh_FileFormat());
  
  /*--- Definition and of the containers for all possible zones. ---*/
  
  solver_container      = new CSolver***[nZone];
  integration_container = new CIntegration**[nZone];
  numerics_container    = new CNumerics****[nZone];
  config_container      = new CConfig*[nZone];
  geometry_container    = new CGeometry **[nZone];
  surface_movement      = new CSurfaceMovement *[nZone];
  grid_movement         = new CVolumetricMovement *[nZone];
  FFDBox                = new CFreeFormDefBox**[nZone];
  
  for (iZone = 0; iZone < nZone; iZone++) {
    solver_container[iZone]       = NULL;
    integration_container[iZone]  = NULL;
    numerics_container[iZone]     = NULL;
    config_container[iZone]       = NULL;
    geometry_container[iZone]     = NULL;
    surface_movement[iZone]       = NULL;
    grid_movement[iZone]          = NULL;
    FFDBox[iZone]                 = NULL;
  }
  
  /*--- Loop over all zones to initialize the various classes. In most
   cases, nZone is equal to one. This represents the solution of a partial
   differential equation on a single block, unstructured mesh. ---*/
  
  for (iZone = 0; iZone < nZone; iZone++) {
    
    /*--- Definition of the configuration option class for all zones. In this
     constructor, the input configuration file is parsed and all options are
     read and stored. ---*/
    
    config_container[iZone] = new CConfig(config_file_name, SU2_CFD, iZone, nZone, VERB_HIGH);
    
#ifndef NO_MPI
    /*--- Change the name of the input-output files for a parallel computation ---*/
    config_container[iZone]->SetFileNameDomain(rank+1);
#endif
    
    /*--- Perform the non-dimensionalization for the flow equations using the
     specified reference values. ---*/
    
    config_container[iZone]->SetNondimensionalization(nDim, iZone);
    
    /*--- Definition of the geometry class. Within this constructor, the
     mesh file is read and the primal grid is stored (node coords, connectivity,
     & boundary markers. MESH_0 is the index of the finest mesh. ---*/
    
    geometry_container[iZone] = new CGeometry *[config_container[iZone]->GetMGLevels()+1];
    geometry_container[iZone][MESH_0] = new CPhysicalGeometry(config_container[iZone],
                                                              iZone+1, nZone);
    
  }
  
  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Geometry Preprocessing ------------------------" << endl;
  
  /*--- Preprocessing of the geometry for all zones. In this routine, the edge-
   based data structure is constructed, i.e. node and cell neighbors are
   identified and linked, face areas and volumes of the dual mesh cells are
   computed, and the multigrid levels are created using an agglomeration procedure. ---*/
  
  Geometrical_Preprocessing(geometry_container, config_container, nZone);
  
#ifndef NO_MPI
  /*--- Synchronization point after the geometrical definition subroutine ---*/
  MPI::COMM_WORLD.Barrier();
#endif
  
  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Solver Preprocessing --------------------------" << endl;
  
  for (iZone = 0; iZone < nZone; iZone++) {
    
    /*--- Definition of the solver class: solver_container[#ZONES][#MG_GRIDS][#EQ_SYSTEMS].
     The solver classes are specific to a particular set of governing equations,
     and they contain the subroutines with instructions for computing each spatial
     term of the PDE, i.e. loops over the edges to compute convective and viscous
     fluxes, loops over the nodes to compute source terms, and routines for
     imposing various boundary condition type for the PDE. ---*/
    
    solver_container[iZone] = new CSolver** [config_container[iZone]->GetMGLevels()+1];
    for (iMesh = 0; iMesh <= config_container[iZone]->GetMGLevels(); iMesh++)
      solver_container[iZone][iMesh] = NULL;
    
    for (iMesh = 0; iMesh <= config_container[iZone]->GetMGLevels(); iMesh++) {
      solver_container[iZone][iMesh] = new CSolver* [MAX_SOLS];
      for (iSol = 0; iSol < MAX_SOLS; iSol++)
        solver_container[iZone][iMesh][iSol] = NULL;
    }
    Solver_Preprocessing(solver_container[iZone], geometry_container[iZone],
                         config_container[iZone], iZone);
    
#ifndef NO_MPI
    /*--- Synchronization point after the solution preprocessing subroutine ---*/
    MPI::COMM_WORLD.Barrier();
#endif
    
    if (rank == MASTER_NODE)
      cout << endl <<"----------------- Integration and Numerics Preprocessing ----------------" << endl;
    
    /*--- Definition of the integration class: integration_container[#ZONES][#EQ_SYSTEMS].
     The integration class orchestrates the execution of the spatial integration
     subroutines contained in the solver class (including multigrid) for computing
     the residual at each node, R(U) and then integrates the equations to a
     steady state or time-accurately. ---*/
    
    integration_container[iZone] = new CIntegration*[MAX_SOLS];
    Integration_Preprocessing(integration_container[iZone], geometry_container[iZone],
                              config_container[iZone], iZone);
    
#ifndef NO_MPI
    /*--- Synchronization point after the integration definition subroutine ---*/
    MPI::COMM_WORLD.Barrier();
#endif
    
    /*--- Definition of the numerical method class:
     numerics_container[#ZONES][#MG_GRIDS][#EQ_SYSTEMS][#EQ_TERMS].
     The numerics class contains the implementation of the numerical methods for
     evaluating convective or viscous fluxes between any two nodes in the edge-based
     data structure (centered, upwind, galerkin), as well as any source terms
     (piecewise constant reconstruction) evaluated in each dual mesh volume. ---*/
    
    numerics_container[iZone] = new CNumerics***[config_container[iZone]->GetMGLevels()+1];
    Numerics_Preprocessing(numerics_container[iZone], solver_container[iZone],
                           geometry_container[iZone], config_container[iZone], iZone);
    
#ifndef NO_MPI
    /*--- Synchronization point after the solver definition subroutine ---*/
    MPI::COMM_WORLD.Barrier();
#endif
    
    /*--- Computation of wall distances for turbulence modeling ---*/
    
    if ( (config_container[iZone]->GetKind_Solver() == RANS)     ||
        (config_container[iZone]->GetKind_Solver() == ADJ_RANS)    )
      geometry_container[iZone][MESH_0]->ComputeWall_Distance(config_container[iZone]);
    
    /*--- Computation of positive surface area in the z-plane which is used for
     the calculation of force coefficient (non-dimensionalization). ---*/
    
    geometry_container[iZone][MESH_0]->SetPositive_ZArea(config_container[iZone]);
    
    /*--- Set the near-field and interface boundary conditions, if necessary. ---*/
    
    for (iMesh = 0; iMesh <= config_container[iZone]->GetMGLevels(); iMesh++) {
      geometry_container[iZone][iMesh]->MatchNearField(config_container[iZone]);
      geometry_container[iZone][iMesh]->MatchInterface(config_container[iZone]);
    }
    
    /*--- Instantiate the geometry movement classes for the solution of unsteady
     flows on dynamic meshes, including rigid mesh transformations, dynamically
     deforming meshes, and time-spectral preprocessing. ---*/
    
    if (config_container[iZone]->GetGrid_Movement()) {
      if (rank == MASTER_NODE)
        cout << "Setting dynamic mesh structure." << endl;
      grid_movement[iZone] = new CVolumetricMovement(geometry_container[iZone][MESH_0]);
      FFDBox[iZone] = new CFreeFormDefBox*[MAX_NUMBER_FFD];
      surface_movement[iZone] = new CSurfaceMovement();
      surface_movement[iZone]->CopyBoundary(geometry_container[iZone][MESH_0], config_container[iZone]);
      if (config_container[iZone]->GetUnsteady_Simulation() == TIME_SPECTRAL)
        SetGrid_Movement(geometry_container[iZone], surface_movement[iZone], grid_movement[iZone],
                         FFDBox[iZone], solver_container[iZone], config_container[iZone], iZone, 0);
    }
    
  }
  
  /*--- For the time-spectral solver, set the grid node velocities. ---*/
  
  if (config_container[ZONE_0]->GetUnsteady_Simulation() == TIME_SPECTRAL)
    SetTimeSpectral_Velocities(geometry_container, config_container, nZone);
  
  /*--- Coupling between zones (limited to two zones at the moment) ---*/
  
  if (nZone == 2) {
    if (rank == MASTER_NODE)
      cout << endl <<"--------------------- Setting Coupling Between Zones --------------------" << endl;
    geometry_container[ZONE_0][MESH_0]->MatchZone(config_container[ZONE_0], geometry_container[ZONE_1][MESH_0],
                                                  config_container[ZONE_1], ZONE_0, nZone);
    geometry_container[ZONE_1][MESH_0]->MatchZone(config_container[ZONE_1], geometry_container[ZONE_0][MESH_0],
                                                  config_container[ZONE_0], ZONE_1, nZone);
  }
  
  /*--- Definition of the output class (one for all zones). The output class
   manages the writing of all restart, volume solution, surface solution,
   surface comma-separated value, and convergence history files (both in serial
   and in parallel). ---*/
  
  output = new COutput();
  
  /*--- Open the convergence history file ---*/
  
  if (rank == MASTER_NODE)
    output->SetHistory_Header(&ConvHist_file, config_container[ZONE_0]);
  
  /*--- Check for an unsteady restart. Update ExtIter if necessary. ---*/
  if (config_container[ZONE_0]->GetWrt_Unsteady() && config_container[ZONE_0]->GetRestart())
    ExtIter = config_container[ZONE_0]->GetUnst_RestartIter();
  
  /*--- Main external loop of the solver. Within this loop, each iteration ---*/
  
  if (rank == MASTER_NODE)
    cout << endl <<"------------------------------ Begin Solver -----------------------------" << endl;
  
  while (ExtIter < config_container[ZONE_0]->GetnExtIter()) {
    
    /*--- Set a timer for each iteration. Store the current iteration and
     update  the value of the CFL number (if there is CFL ramping specified)
     in the config class. ---*/
    
    StartTime = clock();
    for (iZone = 0; iZone < nZone; iZone++) {
      config_container[iZone]->SetExtIter(ExtIter);
      config_container[iZone]->UpdateCFL(ExtIter);
    }
    
    /*--- Perform a single iteration of the chosen PDE solver. ---*/
    
    switch (config_container[ZONE_0]->GetKind_Solver()) {
        
      case EULER: case NAVIER_STOKES: case RANS:
        MeanFlowIteration(output, integration_container, geometry_container,
                          solver_container, numerics_container, config_container,
                          surface_movement, grid_movement, FFDBox);
        break;
        
      case TNE2_EULER: case TNE2_NAVIER_STOKES:
        TNE2Iteration(output, integration_container,
                      geometry_container, solver_container,
                      numerics_container, config_container,
                      surface_movement, grid_movement, FFDBox);
        break;
        
      case FLUID_STRUCTURE_EULER: case FLUID_STRUCTURE_NAVIER_STOKES:
        FluidStructureIteration(output, integration_container, geometry_container,
                                solver_container, numerics_container, config_container,
                                surface_movement, grid_movement, FFDBox);
        break;
        
      case WAVE_EQUATION:
        WaveIteration(output, integration_container, geometry_container,
                      solver_container, numerics_container, config_container,
                      surface_movement, grid_movement, FFDBox);
        break;
        
      case HEAT_EQUATION:
        HeatIteration(output, integration_container, geometry_container,
                      solver_container, numerics_container, config_container,
                      surface_movement, grid_movement, FFDBox);
        break;
        
      case POISSON_EQUATION:
        PoissonIteration(output, integration_container, geometry_container,
                         solver_container, numerics_container, config_container,
                         surface_movement, grid_movement, FFDBox);
        break;
        
      case LINEAR_ELASTICITY:
        FEAIteration(output, integration_container, geometry_container,
                     solver_container, numerics_container, config_container,
                     surface_movement, grid_movement, FFDBox);
        break;
        
      case ADJ_EULER: case ADJ_NAVIER_STOKES: case ADJ_RANS:
        AdjMeanFlowIteration(output, integration_container, geometry_container,
                             solver_container, numerics_container, config_container,
                             surface_movement, grid_movement, FFDBox);
        break;
        
      case ADJ_TNE2_EULER: case ADJ_TNE2_NAVIER_STOKES:
        AdjTNE2Iteration(output, integration_container, geometry_container,
                         solver_container, numerics_container, config_container,
                         surface_movement, grid_movement, FFDBox);
        break;
    }
    
    
    /*--- Synchronization point after a single solver iteration. Compute the
     wall clock time required. ---*/
    
#ifndef NO_MPI
    MPI::COMM_WORLD.Barrier();
#endif
    StopTime = clock(); TimeUsed += (StopTime - StartTime);
    
    /*--- For specific applications, evaluate and plot the equivalent area or flow rate. ---*/
    
    if ((config_container[ZONE_0]->GetKind_Solver() == EULER) &&
        (config_container[ZONE_0]->GetEquivArea() == YES)) {
      output->SetEquivalentArea(solver_container[ZONE_0][MESH_0][FLOW_SOL],
                                geometry_container[ZONE_0][MESH_0], config_container[ZONE_0], ExtIter);
    }
    
    /*--- Update the convergence history file (serial and parallel computations). ---*/
    
    output->SetConvergence_History(&ConvHist_file, geometry_container, solver_container,
                                   config_container, integration_container, false, TimeUsed, ZONE_0);
    
    /*--- Check whether the current simulation has reached the specified
     convergence criteria, and set StopCalc to true, if so. ---*/
    
    switch (config_container[ZONE_0]->GetKind_Solver()) {
      case EULER: case NAVIER_STOKES: case RANS:
        StopCalc = integration_container[ZONE_0][FLOW_SOL]->GetConvergence(); break;
      case TNE2_EULER: case TNE2_NAVIER_STOKES:
        StopCalc = integration_container[ZONE_0][TNE2_SOL]->GetConvergence(); break;
      case WAVE_EQUATION:
        StopCalc = integration_container[ZONE_0][WAVE_SOL]->GetConvergence(); break;
      case HEAT_EQUATION:
        StopCalc = integration_container[ZONE_0][HEAT_SOL]->GetConvergence(); break;
      case LINEAR_ELASTICITY:
        StopCalc = integration_container[ZONE_0][FEA_SOL]->GetConvergence(); break;
      case ADJ_EULER: case ADJ_NAVIER_STOKES: case ADJ_RANS:
        StopCalc = integration_container[ZONE_0][ADJFLOW_SOL]->GetConvergence(); break;
      case ADJ_TNE2_EULER: case ADJ_TNE2_NAVIER_STOKES:
        StopCalc = integration_container[ZONE_0][ADJTNE2_SOL]->GetConvergence(); break;
    }
    
    /*--- Solution output. Determine whether a solution needs to be written
     after the current iteration, and if so, execute the output file writing
     routines. ---*/
    
    if ((ExtIter+1 == config_container[ZONE_0]->GetnExtIter()) ||
        ((ExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq() == 0) && (ExtIter != 0) &&
         !((config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
           (config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_2ND))) ||
        (StopCalc) ||
        (((config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
          (config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_2ND)) &&
         ((ExtIter == 0) || (ExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0)))) {
          
          /*--- Low-fidelity simulations (using a coarser multigrid level
           approximation to the solution) require an interpolation back to the
           finest grid. ---*/
          
          if (config_container[ZONE_0]->GetLowFidelitySim()) {
            integration_container[ZONE_0][FLOW_SOL]->SetProlongated_Solution(RUNTIME_FLOW_SYS, solver_container[ZONE_0][MESH_0], solver_container[ZONE_0][MESH_1], geometry_container[ZONE_0][MESH_0], geometry_container[ZONE_0][MESH_1], config_container[ZONE_0]);
            integration_container[ZONE_0][FLOW_SOL]->Smooth_Solution(RUNTIME_FLOW_SYS, solver_container[ZONE_0][MESH_0], geometry_container[ZONE_0][MESH_0], 3, 1.25, config_container[ZONE_0]);
            solver_container[ZONE_0][MESH_0][config_container[ZONE_0]->GetContainerPosition(RUNTIME_FLOW_SYS)]->Set_MPI_Solution(geometry_container[ZONE_0][MESH_0], config_container[ZONE_0]);
            solver_container[ZONE_0][MESH_0][config_container[ZONE_0]->GetContainerPosition(RUNTIME_FLOW_SYS)]->Preprocessing(geometry_container[ZONE_0][MESH_0], solver_container[ZONE_0][MESH_0], config_container[ZONE_0], MESH_0, 0, RUNTIME_FLOW_SYS);
          }
          
          /*--- Execute the routine for writing restart, volume solution,
           surface solution, and surface comma-separated value files. ---*/
          
          output->SetResult_Files(solver_container, geometry_container, config_container, ExtIter, nZone);
          
        }
    
    /*--- If the convergence criteria has been met, terminate the simulation. ---*/
    
    if (StopCalc) break;
    
    ExtIter++;
    
  }
  
  /*--- Close the convergence history file. ---*/
  
  if (rank == MASTER_NODE) {
    ConvHist_file.close();
    cout << endl <<"History file, closed." << endl;
  }
  /*
  if (config->GetKind_Solver() == RANS){
    if (config->GetKind_Turb_Model() == ML){
      // Tell the ML code to stop running
      string mlWriteFilename = config->GetML_Turb_Model_Write();
      ofstream mlWrite;
      mlWrite.open(mlWriteFilename.c_str());
      mlWrite << int(-1) << flush;
      mlWrite.close();
    }
  }
   */
  
  /*--- Solver class deallocation ---*/
  //  for (iZone = 0; iZone < nZone; iZone++) {
  //    for (iMesh = 0; iMesh <= config_container[iZone]->GetMGLevels(); iMesh++) {
  //      for (iSol = 0; iSol < MAX_SOLS; iSol++) {
  //        if (solver_container[iZone][iMesh][iSol] != NULL) {
  //          delete solver_container[iZone][iMesh][iSol];
  //        }
  //      }
  //      delete solver_container[iZone][iMesh];
  //    }
  //    delete solver_container[iZone];
  //  }
  //  delete [] solver_container;
  //  if (rank == MASTER_NODE) cout <<"Solution container, deallocated." << endl;
  
  /*--- Geometry class deallocation ---*/
  //  for (iZone = 0; iZone < nZone; iZone++) {
  //    for (iMesh = 0; iMesh <= config_container[iZone]->GetMGLevels(); iMesh++) {
  //      delete geometry_container[iZone][iMesh];
  //    }
  //    delete geometry_container[iZone];
  //  }
  //  delete [] geometry_container;
  //  cout <<"Geometry container, deallocated." << endl;
  
  /*--- Integration class deallocation ---*/
  //  cout <<"Integration container, deallocated." << endl;
  
#ifndef NO_MPI
  /*--- Compute/print the total time for parallel performance benchmarking. ---*/
#ifdef TIME
  MPI::COMM_WORLD.Barrier();
  finish = MPI::Wtime();
  time = finish-start;
  if (rank == MASTER_NODE) {
    cout << "\nCompleted in " << fixed << time << " seconds on "<< size;
    if (size == 1) cout << " core.\n" << endl;
    else cout << " cores.\n" << endl;
  }
#endif
  /*--- Finalize MPI parallelization ---*/
  old_buffer = buffer;
  MPI::Detach_buffer(old_buffer);
  //	delete [] buffer;
  MPI::Finalize();
#endif
  
  /*--- Exit the solver cleanly ---*/
  
  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Exit Success (SU2_CFD) ------------------------" << endl << endl;
  
  return EXIT_SUCCESS;
}
示例#6
0
文件: SU2_UMC.cpp 项目: khairy/SU2
int main(int argc, char *argv[]) {
		  
  /*--- Local variables ---*/
  unsigned short mode, nZone = 1;
  char grid_filename[200];

  int rank = MASTER_NODE;
#ifndef NO_MPI
  /*--- MPI initialization, and buffer setting ---*/
#ifdef WINDOWS
  MPI_Init(&argc,&argv);
  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
#else
  MPI::Init(argc,argv);
  rank = MPI::COMM_WORLD.Get_rank();
#endif
#endif
	
  /*--- Declare pointers to class objects ---*/
  CConfig *config = NULL;
  CBoundaryGeometry *boundary = NULL;
  
  /*--- Instatiate an object of the config class
        based on the name of the config file given ---*/
  strcpy(grid_filename, argv[1]);
  config = new CConfig(grid_filename, SU2_GDC, ZONE_0, nZone, 
                         VERB_HIGH);

  /*--- Instantiate an object of the boundary-geometry class ---*/
  boundary = new CBoundaryGeometry(config, 
                                   config->GetMesh_FileName(), 
                                   config->GetMesh_FileFormat());
  
  /*--- determine the mode of operation ---*/
  mode = atoi(argv[2]);
  cout << endl;
  
  switch (mode) {
  
    case 1:
      cout << "\t ------------------------------------ \t" << endl;
      cout << "\t *** AIRFOIL-SECTION-CUTTING MODE *** \t" << endl;
      cout << "\t ------------------------------------ \t" << endl;
      
      /*--- if they exist, delete old versions of files "span," 
            "tracked_points," "Airfoil_Sections.plt," and
            "coordinates.csv" ---*/
      cout << endl;
      clean_up("span");
      clean_up("tracked_points");
      clean_up("Airfoil_Sections.plt");
      clean_up("coordinates.csv");
      
      /*--- Make the sectional cuts along the surfaces of interest and
            write the files "span," "tracked points," and 
            "Airfoil_Sections.plt" to the current directory ---*/
      Make_Sectional_Cuts(config, boundary);
  
      /*--- find the coordinates of the sections and 
            print to the "coordinate.csv" file ---*/
      Tracked_Points_to_Coords(boundary);
      
      break;
      
    case 2:
      cout << "\t ------------------------------------------ \t" << endl;
      cout << "\t *** SECTIONAL-FORCES MODE (SU2->UMARC) *** \t" << endl;
      cout << "\t ------------------------------------------ \t" << endl;

      break;
      
    case 3:
      cout << "\t --------------------------------------------------- \t" << endl;
      cout << "\t *** DEFORMATION-COMMUNICATION MODE (UMARC->SU2) *** \t" << endl;
      cout << "\t --------------------------------------------------- \t" << endl;

      break;
      
    default:
      cout << "\t -------------------------------------------- \t" << endl;
      cout << "\t *** ERROR! PLEASE RUN IN MODE 1, 2, OR 3 *** \t" << endl;
      cout << "\t -------------------------------------------- \t" << endl;
      return EXIT_SUCCESS;
  }
                                   
  /*--- Delete dynamically allocated memory ---*/
	if (config != NULL) {delete config;}
	if (boundary != NULL) {delete boundary;}
	
	/*--- End routine ---*/
	cout << endl <<"------------------------- Exit Success (SU2_UMC) ------------------------" << endl << endl;
  
	return EXIT_SUCCESS;
	
}
示例#7
0
文件: SU2_UMC.cpp 项目: ZJLi2013/SU2
int main(int argc, char *argv[]) {
		  
  /*--- Local variables ---*/
  unsigned short mode, nZone = 1;
  char grid_filename[200];
  bool complete;

  int rank = MASTER_NODE;
#ifndef NO_MPI
  /*--- MPI initialization, and buffer setting ---*/
#ifdef WINDOWS
  MPI_Init(&argc,&argv);
  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
#else
  MPI::Init(argc,argv);
  rank = MPI::COMM_WORLD.Get_rank();
#endif
#endif

  /*--- Declare pointers to class objects ---*/
  CConfig *config = NULL;
  CBoundaryGeometry *boundary = NULL;
 
  /*--- Instatiate an object of the config class
        based on the name of the config file given ---*/
  strcpy(grid_filename, argv[1]);
  config = new CConfig(grid_filename, SU2_GDC, ZONE_0, nZone, 
                         0, VERB_HIGH);

  /*--- Instantiate an object of the boundary-geometry class ---*/
  boundary = new CBoundaryGeometry(config, 
                                   config->GetMesh_FileName(), 
                                   config->GetMesh_FileFormat());
  
  /*--- determine the mode of operation ---*/
  if (argc < 3) {
    if (argc == 2) {
      cout << "\t ------------------------------------------ \t" << endl;
      cout << "\t *** ERROR! PLEASE ENTER A RUNNING MODE *** \t" << endl;
      cout << "\t ------------------------------------------ \t" << endl;
      return EXIT_SUCCESS;
    }
    if (argc == 1) {
      cout << "\t -------------------------------------------------- \t" << endl;
      cout << "\t *** ERROR! PLEASE ENTER A CONFIG FILE AND MODE *** \t" << endl;
      cout << "\t -------------------------------------------------- \t" << endl;
      return EXIT_SUCCESS;
    }
  }
  mode = atoi(argv[2]);
  cout << endl;
  
  switch (mode) {
  
    case 1:
      cout << "\t ------------------------------------ \t" << endl;
      cout << "\t *** AIRFOIL-SECTION-CUTTING MODE *** \t" << endl;
      cout << "\t ------------------------------------ \t" << endl;
      
      /*--- if they exist, delete old versions of files "span," 
            "tracked_points," "Airfoil_Sections.plt," and 
            "coordinates.csv" ---*/
      cout << endl;
      clean_up("span");
      clean_up("tracked_points");
      clean_up("Airfoil_Sections.plt");
      clean_up("coordinates.csv");
      
      /*--- make the sectional cuts along the surfaces of interest and
            write the files "span," "tracked_points," and 
            "Airfoil_Sections.plt" to the current directory ---*/
      Make_Sectional_Cuts(config, boundary);
  
      /*--- find the coordinates of the sections and 
            print to the "coordinate.csv" file ---*/
      Tracked_Points_to_Coords(boundary);
      
      break;
      
    case 2:
      cout << "\t ------------------------------------------ \t" << endl;
      cout << "\t *** SECTIONAL-FORCES MODE (SU2->UMARC) *** \t" << endl;
      cout << "\t ------------------------------------------ \t" << endl;
      
      /*--- recompute the coordinates and rewrite "coordinates.csv" 
            file, just in case the geometry has been deformed since 
            running mode 1. N.B. The original cuts can still be found
            in "Airfoil_Sections.plt" ---*/
      cout << endl;
      clean_up("coordinates.csv");
      Tracked_Points_to_Coords(boundary);
      
      /*--- read the new coordinates, find the corresponding values 
            of pressure from "surface_flow.csv," and write the 
            sectional-forces files cl, cd, and cm ---*/
      complete = Compute_Sectional_Forces();
     

 
      
      
      if (complete == false) {
        cout << endl << "Sectional forces have not been computed properly." << endl;
        return EXIT_SUCCESS;
      }
      
      break;
      
    case 3:
      cout << "\t --------------------------------------------------- \t" << endl;
      cout << "\t *** DEFORMATION-COMMUNICATION MODE (UMARC->SU2) *** \t" << endl;
      cout << "\t --------------------------------------------------- \t" << endl;

      break;
      
    default:
      cout << "\t -------------------------------------------- \t" << endl;
      cout << "\t *** ERROR! PLEASE RUN IN MODE 1, 2, OR 3 *** \t" << endl;
      cout << "\t -------------------------------------------- \t" << endl;
      return EXIT_SUCCESS;
  }
                                   
  /*--- Delete dynamically allocated memory ---*/
	if (config != NULL) delete config;
	if (boundary != NULL) delete boundary;
	
	/*--- End routine ---*/
	cout << endl <<"------------------------- Exit Success (SU2_UMC) ------------------------" << endl << endl;
  
	return EXIT_SUCCESS;
	
}
示例#8
0
int main(int argc, char *argv[]) {
  
  /*--- Local variables ---*/
	unsigned short iDV, nZone = 1, iFFDBox, iPlane, nPlane = 5, iVar;
	double ObjectiveFunc[100], ObjectiveFunc_New[100], Gradient[100], delta_eps, MinPlane, MaxPlane, Plane_P0[5][3], Plane_Normal[5][3];
  vector<double> Xcoord_Airfoil[5], Ycoord_Airfoil[5], Zcoord_Airfoil[5];
  
	char *cstr;
	ofstream Gradient_file, ObjFunc_file;
	int rank = MASTER_NODE;
  
  /*--- Initialization ---*/
  for (iVar = 0; iVar < 100; iVar++) {
    ObjectiveFunc[iVar] = 0.0;
    ObjectiveFunc_New[iVar] = 0.0;
    Gradient[iVar] = 0.0;
  }
  
#ifndef NO_MPI
	/*--- MPI initialization, and buffer setting ---*/
	MPI::Init(argc,argv);
	rank = MPI::COMM_WORLD.Get_rank();
#endif
	
	/*--- Pointer to different structures that will be used throughout the entire code ---*/
	CFreeFormDefBox** FFDBox = NULL;
	CConfig *config = NULL;
	CGeometry *boundary = NULL;
	CSurfaceMovement *surface_mov = NULL;
	
	/*--- Definition of the Class for the definition of the problem ---*/
	if (argc == 2) config = new CConfig(argv[1], SU2_GDC, ZONE_0, nZone, VERB_HIGH);
	else {
		char grid_file[200];
		strcpy (grid_file, "default.cfg");
		config = new CConfig(grid_file, SU2_GDC, ZONE_0, nZone, VERB_HIGH);
	}
	
#ifndef NO_MPI
	/*--- Change the name of the input-output files for the
	 parallel computation ---*/
	config->SetFileNameDomain(rank+1);
#endif
	
	/*--- Definition of the Class for the boundary of the geometry ---*/
	boundary = new CBoundaryGeometry(config, config->GetMesh_FileName(), config->GetMesh_FileFormat());
  
	if (rank == MASTER_NODE)
		cout << endl <<"----------------------- Preprocessing computations ----------------------" << endl;
	
  /*--- Boundary geometry preprocessing ---*/
	if (rank == MASTER_NODE) cout << "Identify vertices." <<endl;
	boundary->SetVertex();
	
	/*--- Create the control volume structures ---*/
	if (rank == MASTER_NODE) cout << "Set boundary control volume structure." << endl;
	boundary->SetBoundControlVolume(config, ALLOCATE);
	
	/*--- Create plane structure ---*/
  if (rank == MASTER_NODE) cout << "Set plane structure." << endl;
  if (boundary->GetnDim() == 2) {
    nPlane = 1;
    Plane_Normal[0][0] = 0.0;   Plane_P0[0][0] = 0.0;
    Plane_Normal[0][1] = 1.0;   Plane_P0[0][1] = 0.0;
    Plane_Normal[0][2] = 0.0;   Plane_P0[0][2] = 0.0;
  }
  else if (boundary->GetnDim() == 3) {
    nPlane = 5; MinPlane = config->GetSection_Limit(0); MaxPlane = config->GetSection_Limit(1);
    for (iPlane = 0; iPlane < nPlane; iPlane++) {
      Plane_Normal[iPlane][0] = 0.0;    Plane_P0[iPlane][0] = 0.0;
      Plane_Normal[iPlane][1] = 1.0;    Plane_P0[iPlane][1] = MinPlane + iPlane*(MaxPlane - MinPlane)/double(nPlane-1);
      Plane_Normal[iPlane][2] = 0.0;    Plane_P0[iPlane][2] = 0.0;
    }
  }

  /*--- Create airfoil section structure ---*/
  if (rank == MASTER_NODE) cout << "Set airfoil section structure." << endl;
  for (iPlane = 0; iPlane < nPlane; iPlane++) {
    boundary->ComputeAirfoil_Section(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, config,
                                     Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], true);
  }
  
  if (rank == MASTER_NODE)
    cout << endl <<"-------------------- Objective function evaluation ----------------------" << endl;

  if (rank == MASTER_NODE) {
    
    /*--- Evaluate objective function ---*/
    for (iPlane = 0; iPlane < nPlane; iPlane++) {

      if (Xcoord_Airfoil[iPlane].size() != 0) {
        
        cout << "\nSection " << (iPlane+1) << ". Plane (yCoord): " << Plane_P0[iPlane][1] << "." << endl;
        
        ObjectiveFunc[iPlane]           = boundary->Compute_MaxThickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], true);
        ObjectiveFunc[1*nPlane+iPlane]  = boundary->Compute_Thickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, 0.250000, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], true);
        ObjectiveFunc[2*nPlane+iPlane]  = boundary->Compute_Thickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, 0.333333, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], true);
        ObjectiveFunc[3*nPlane+iPlane]  = boundary->Compute_Thickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, 0.500000, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], true);
        ObjectiveFunc[4*nPlane+iPlane]  = boundary->Compute_Thickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, 0.666666, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], true);
        ObjectiveFunc[5*nPlane+iPlane]  = boundary->Compute_Thickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, 0.750000, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], true);
        ObjectiveFunc[6*nPlane+iPlane]  = boundary->Compute_Area(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], true);
        ObjectiveFunc[7*nPlane+iPlane]  = boundary->Compute_AoA(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], true);
        ObjectiveFunc[8*nPlane+iPlane]  = boundary->Compute_Chord(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], true);
        
        cout << "Maximum thickness: "   << ObjectiveFunc[iPlane] << "." << endl;
        cout << "1/4 chord thickness: " << ObjectiveFunc[1*nPlane+iPlane] << "." << endl;
        cout << "1/3 chord thickness: " << ObjectiveFunc[2*nPlane+iPlane] << "." << endl;
        cout << "1/2 chord thickness: " << ObjectiveFunc[3*nPlane+iPlane] << "." << endl;
        cout << "2/3 chord thickness: " << ObjectiveFunc[4*nPlane+iPlane] << "." << endl;
        cout << "3/4 chord thickness: " << ObjectiveFunc[5*nPlane+iPlane] << "." << endl;
        cout << "Area: "                << ObjectiveFunc[6*nPlane+iPlane] << "." << endl;
        cout << "Angle of attack: "     << ObjectiveFunc[7*nPlane+iPlane] << "." << endl;
        cout << "Chord: "               << ObjectiveFunc[8*nPlane+iPlane] << "." << endl;
        
      }
      
    }
    
    /*--- Write the objective function in a external file ---*/
		cstr = new char [config->GetObjFunc_Value_FileName().size()+1];
		strcpy (cstr, config->GetObjFunc_Value_FileName().c_str());
		ObjFunc_file.open(cstr, ios::out);
    ObjFunc_file << "TITLE = \"SU2_GDC Simulation\"" << endl;
    
    if (boundary->GetnDim() == 2) {
      ObjFunc_file << "VARIABLES = \"MAX_THICKNESS\",\"1/4_THICKNESS\",\"1/3_THICKNESS\",\"1/2_THICKNESS\",\"2/3_THICKNESS\",\"3/4_THICKNESS\",\"AREA\",\"AOA\",\"CHORD\"" << endl;
    }
    else if (boundary->GetnDim() == 3) {
      ObjFunc_file << "VARIABLES = ";
      for (iPlane = 0; iPlane < nPlane; iPlane++) ObjFunc_file << "\"MAX_THICKNESS_SEC"<< (iPlane+1) << "\", ";
      for (iPlane = 0; iPlane < nPlane; iPlane++) ObjFunc_file << "\"1/4_THICKNESS_SEC"<< (iPlane+1) << "\", ";
      for (iPlane = 0; iPlane < nPlane; iPlane++) ObjFunc_file << "\"1/3_THICKNESS_SEC"<< (iPlane+1) << "\", ";
      for (iPlane = 0; iPlane < nPlane; iPlane++) ObjFunc_file << "\"1/2_THICKNESS_SEC"<< (iPlane+1) << "\", ";
      for (iPlane = 0; iPlane < nPlane; iPlane++) ObjFunc_file << "\"2/3_THICKNESS_SEC"<< (iPlane+1) << "\", ";
      for (iPlane = 0; iPlane < nPlane; iPlane++) ObjFunc_file << "\"3/4_THICKNESS_SEC"<< (iPlane+1) << "\", ";
      for (iPlane = 0; iPlane < nPlane; iPlane++) ObjFunc_file << "\"AREA_SEC"<< (iPlane+1) << "\", ";
      for (iPlane = 0; iPlane < nPlane; iPlane++) ObjFunc_file << "\"AOA_SEC"<< (iPlane+1) << "\", ";
      for (iPlane = 0; iPlane < nPlane-1; iPlane++) ObjFunc_file << "\"CHORD_SEC"<< (iPlane+1) << "\", ";
      ObjFunc_file << "\"CHORD_SEC"<< (nPlane) << "\"" << endl;
    }
    
    ObjFunc_file << "ZONE T= \"Geometrical variables (value)\"" << endl;
    
    for (iPlane = 0; iPlane < nPlane*9-1; iPlane++)
      ObjFunc_file << ObjectiveFunc[iPlane] <<", ";
    ObjFunc_file << ObjectiveFunc[nPlane*9-1] << endl;
    
    ObjFunc_file.close();
    
	}
	
	if (config->GetGeometryMode() == GRADIENT) {
		
		/*--- Definition of the Class for surface deformation ---*/
		surface_mov = new CSurfaceMovement();
		
		/*--- Definition of the FFD deformation class ---*/
		FFDBox = new CFreeFormDefBox*[MAX_NUMBER_FFD];
		
		if (rank == MASTER_NODE)
			cout << endl <<"------------- Gradient evaluation using finite differences --------------" << endl;

		/*--- Write the gradient in a external file ---*/
		if (rank == MASTER_NODE) {
			cstr = new char [config->GetObjFunc_Grad_FileName().size()+1];
			strcpy (cstr, config->GetObjFunc_Grad_FileName().c_str());
			Gradient_file.open(cstr, ios::out);
		}
		
		for (iDV = 0; iDV < config->GetnDV(); iDV++) {
			
			/*--- Bump deformation for 2D problems ---*/
			if (boundary->GetnDim() == 2) {
				
        if (rank == MASTER_NODE)
          cout << "Perform 2D deformation of the surface." << endl;
        
        switch ( config->GetDesign_Variable(iDV) ) {
          case HICKS_HENNE : surface_mov->SetHicksHenne(boundary, config, iDV, true); break;
          case DISPLACEMENT : surface_mov->SetDisplacement(boundary, config, iDV, true); break;
          case ROTATION : surface_mov->SetRotation(boundary, config, iDV, true); break;
          case NACA_4DIGITS : surface_mov->SetNACA_4Digits(boundary, config); break;
          case PARABOLIC : surface_mov->SetParabolic(boundary, config); break;
        }
				
			}
			
			/*--- Free Form deformation for 3D problems ---*/
			else if (boundary->GetnDim() == 3) {
        
        /*--- Read the FFD information in the first iteration ---*/
        if (iDV == 0) {
          
          if (rank == MASTER_NODE) cout << "Read the FFD information from mesh file." << endl;
          
          /*--- Read the FFD information from the grid file ---*/
          surface_mov->ReadFFDInfo(boundary, config, FFDBox, config->GetMesh_FileName(), true);
          
          /*--- If the FFDBox was not defined in the input file ---*/
          if (!surface_mov->GetFFDBoxDefinition() && (rank == MASTER_NODE)) {
            cout << "The input grid doesn't have the entire FFD information!" << endl;
            cout << "Press any key to exit..." << endl;
            cin.get();
          }
          
          if (rank == MASTER_NODE)
            cout <<"-------------------------------------------------------------------------" << endl;
          
        }
        
        if (rank == MASTER_NODE) {
          cout << endl << "Design variable number "<< iDV <<"." << endl;
          cout << "Perform 3D deformation of the surface." << endl;
        }
        
        /*--- Apply the control point change ---*/
        for (iFFDBox = 0; iFFDBox < surface_mov->GetnFFDBox(); iFFDBox++) {
          
          switch ( config->GetDesign_Variable(iDV) ) {
            case FFD_CONTROL_POINT : surface_mov->SetFFDCPChange(boundary, config, FFDBox[iFFDBox], iFFDBox, iDV, true); break;
            case FFD_DIHEDRAL_ANGLE : surface_mov->SetFFDDihedralAngle(boundary, config, FFDBox[iFFDBox], iFFDBox, iDV, true); break;
            case FFD_TWIST_ANGLE : surface_mov->SetFFDTwistAngle(boundary, config, FFDBox[iFFDBox], iFFDBox, iDV, true); break;
            case FFD_ROTATION : surface_mov->SetFFDRotation(boundary, config, FFDBox[iFFDBox], iFFDBox, iDV, true); break;
            case FFD_CAMBER : surface_mov->SetFFDCamber(boundary, config, FFDBox[iFFDBox], iFFDBox, iDV, true); break;
            case FFD_THICKNESS : surface_mov->SetFFDThickness(boundary, config, FFDBox[iFFDBox], iFFDBox, iDV, true); break;
            case FFD_VOLUME : surface_mov->SetFFDVolume(boundary, config, FFDBox[iFFDBox], iFFDBox, iDV, true); break;
          }
          
          /*--- Recompute cartesian coordinates using the new control points position ---*/
          surface_mov->SetCartesianCoord(boundary, config, FFDBox[iFFDBox], iFFDBox);
          
        }
        
 			}
      
      /*--- Create airfoil structure ---*/
      for (iPlane = 0; iPlane < nPlane; iPlane++) {
        boundary->ComputeAirfoil_Section(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, config, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], false);
      }
      
			/*--- Compute gradient ---*/
			if (rank == MASTER_NODE) {
        
        delta_eps = config->GetDV_Value(iDV);
        
        if (delta_eps == 0) {
          cout << "The finite difference steps is zero!!" << endl;
          cout << "Press any key to exit..." << endl;
          cin.get();
#ifdef NO_MPI
          exit(1);
#else
          MPI::COMM_WORLD.Abort(1);
          MPI::Finalize();
#endif
        }

        for (iPlane = 0; iPlane < nPlane; iPlane++) {
          
          if (Xcoord_Airfoil[iPlane].size() != 0) {
            
            cout << "\nSection " << (iPlane+1) << ". Plane (yCoord): " << Plane_P0[iPlane][1] << "." << endl;
            
            ObjectiveFunc_New[iPlane] = boundary->Compute_MaxThickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], false);
            Gradient[iPlane] = (ObjectiveFunc_New[iPlane] - ObjectiveFunc[iPlane]) / delta_eps;
            
            ObjectiveFunc_New[1*nPlane + iPlane] = boundary->Compute_Thickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, 0.250000, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], false);
            Gradient[1*nPlane + iPlane] = (ObjectiveFunc_New[1*nPlane + iPlane] - ObjectiveFunc[1*nPlane + iPlane]) / delta_eps;
            
            ObjectiveFunc_New[2*nPlane + iPlane] = boundary->Compute_Thickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, 0.333333, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], false);
            Gradient[2*nPlane + iPlane] = (ObjectiveFunc_New[2*nPlane + iPlane] - ObjectiveFunc[2*nPlane + iPlane]) / delta_eps;
            
            ObjectiveFunc_New[3*nPlane + iPlane] = boundary->Compute_Thickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, 0.500000, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], false);
            Gradient[3*nPlane + iPlane] = (ObjectiveFunc_New[3*nPlane + iPlane] - ObjectiveFunc[3*nPlane + iPlane]) / delta_eps;
            
            ObjectiveFunc_New[4*nPlane + iPlane] = boundary->Compute_Thickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, 0.666666, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], false);
            Gradient[4*nPlane + iPlane] = (ObjectiveFunc_New[4*nPlane + iPlane] - ObjectiveFunc[4*nPlane + iPlane]) / delta_eps;
            
            ObjectiveFunc_New[5*nPlane + iPlane] = boundary->Compute_Thickness(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, 0.750000, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], false);
            Gradient[5*nPlane + iPlane] = (ObjectiveFunc_New[5*nPlane + iPlane] - ObjectiveFunc[5*nPlane + iPlane]) / delta_eps;
            
            ObjectiveFunc_New[6*nPlane + iPlane] = boundary->Compute_Area(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], false);
            Gradient[6*nPlane + iPlane] = (ObjectiveFunc_New[6*nPlane + iPlane] - ObjectiveFunc[6*nPlane + iPlane]) / delta_eps;
            
            ObjectiveFunc_New[7*nPlane + iPlane] = boundary->Compute_AoA(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], false);
            Gradient[7*nPlane + iPlane] = (ObjectiveFunc_New[7*nPlane + iPlane] - ObjectiveFunc[7*nPlane + iPlane]) / delta_eps;
            
            ObjectiveFunc_New[8*nPlane + iPlane] = boundary->Compute_Chord(Plane_P0[iPlane], Plane_Normal[iPlane], iPlane, Xcoord_Airfoil[iPlane], Ycoord_Airfoil[iPlane], Zcoord_Airfoil[iPlane], false);
            Gradient[8*nPlane + iPlane] = (ObjectiveFunc_New[8*nPlane + iPlane] - ObjectiveFunc[8*nPlane + iPlane]) / delta_eps;
            
            cout << "Maximum thickness gradient: "    << Gradient[iPlane] << "." << endl;
            cout << "1/4 chord thickness gradient: "  << Gradient[1*nPlane + iPlane] << "." << endl;
            cout << "1/3 chord thickness gradient: "  << Gradient[2*nPlane + iPlane] << "." << endl;
            cout << "1/2 chord thickness gradient: "  << Gradient[3*nPlane + iPlane] << "." << endl;
            cout << "2/3 chord thickness gradient: "  << Gradient[4*nPlane + iPlane] << "." << endl;
            cout << "3/4 chord thickness gradient: "  << Gradient[5*nPlane + iPlane] << "." << endl;
            cout << "Area gradient: "                 << Gradient[6*nPlane + iPlane] << "." << endl;
            cout << "Angle of attack gradient: "      << Gradient[7*nPlane + iPlane] << "." << endl;
            cout << "Chord gradient: "                << Gradient[8*nPlane + iPlane] << "." << endl;
            
          }
          
        }
 				
        if (iDV == 0) {
          Gradient_file << "TITLE = \"SU2_GDC Simulation\"" << endl;

          if (boundary->GetnDim() == 2) {
            Gradient_file << "VARIABLES = \"DESIGN_VARIABLE\",\"MAX_THICKNESS\",\"1/4_THICKNESS\",\"1/3_THICKNESS\",\"1/2_THICKNESS\",\"2/3_THICKNESS\",\"3/4_THICKNESS\",\"AREA\",\"AOA\",\"CHORD\"" << endl;
          }
          else if (boundary->GetnDim() == 3) {
            Gradient_file << "VARIABLES = \"DESIGN_VARIABLE\",";
            for (iPlane = 0; iPlane < nPlane; iPlane++) Gradient_file << "\"MAX_THICKNESS_SEC"<< (iPlane+1) << "\", ";
            for (iPlane = 0; iPlane < nPlane; iPlane++) Gradient_file << "\"1/4_THICKNESS_SEC"<< (iPlane+1) << "\", ";
            for (iPlane = 0; iPlane < nPlane; iPlane++) Gradient_file << "\"1/3_THICKNESS_SEC"<< (iPlane+1) << "\", ";
            for (iPlane = 0; iPlane < nPlane; iPlane++) Gradient_file << "\"1/2_THICKNESS_SEC"<< (iPlane+1) << "\", ";
            for (iPlane = 0; iPlane < nPlane; iPlane++) Gradient_file << "\"2/3_THICKNESS_SEC"<< (iPlane+1) << "\", ";
            for (iPlane = 0; iPlane < nPlane; iPlane++) Gradient_file << "\"3/4_THICKNESS_SEC"<< (iPlane+1) << "\", ";
            for (iPlane = 0; iPlane < nPlane; iPlane++) Gradient_file << "\"AREA_SEC"<< (iPlane+1) << "\", ";
            for (iPlane = 0; iPlane < nPlane; iPlane++) Gradient_file << "\"AOA_SEC"<< (iPlane+1) << "\", ";
            for (iPlane = 0; iPlane < nPlane-1; iPlane++) Gradient_file << "\"CHORD_SEC"<< (iPlane+1) << "\", ";
            Gradient_file << "\"CHORD_SEC"<< (nPlane) << "\"" << endl;
          }
          
          Gradient_file << "ZONE T= \"Geometrical variables (gradient)\"" << endl;
          
        }
        
        Gradient_file << (iDV) <<", ";
        for (iPlane = 0; iPlane < nPlane*9-1; iPlane++)
          Gradient_file << Gradient[iPlane] <<", ";
        Gradient_file << Gradient[nPlane*9-1] << endl;
        
				if (iDV != (config->GetnDV()-1)) cout <<"-------------------------------------------------------------------------" << endl;
				
			}

		}
		
		if (rank == MASTER_NODE)
			Gradient_file.close();
    
	}
	
	
#ifndef NO_MPI
	/*--- Finalize MPI parallelization ---*/
	MPI::Finalize();
#endif
	
	/*--- End solver ---*/
	if (rank == MASTER_NODE)
		cout << endl <<"------------------------- Exit Success (SU2_GDC) ------------------------" << endl << endl;
  
	return EXIT_SUCCESS;
	
}
示例#9
0
文件: SU2_MSH.cpp 项目: drewkett/SU2
int main(int argc, char *argv[]) {
	
	/*--- Variable definitions ---*/
  
  unsigned short iZone, nZone = SINGLE_ZONE;
  su2double StartTime = 0.0, StopTime = 0.0, UsedTime = 0.0;
  char config_file_name[MAX_STRING_SIZE];
  char file_name[MAX_STRING_SIZE];
  int rank, size;
  string str;
	bool periodic = false;
  
  /*--- MPI initialization ---*/
  
#ifdef HAVE_MPI
  SU2_MPI::Init(&argc,&argv);
  SU2_MPI::Comm MPICommunicator(MPI_COMM_WORLD);
#else
  SU2_Comm MPICommunicator(0);
#endif

  rank = SU2_MPI::GetRank();
  size = SU2_MPI::GetSize();
	
  /*--- Pointer to different structures that will be used throughout the entire code ---*/
  
  CConfig **config_container         = NULL;
  CGeometry **geometry_container     = NULL;
  
  /*--- Load in the number of zones and spatial dimensions in the mesh file (if no config
   file is specified, default.cfg is used) ---*/
  
  if (argc == 2) { strcpy(config_file_name,argv[1]); }
  else { strcpy(config_file_name, "default.cfg"); }
  
	  /*--- Read the name and format of the input mesh file to get from the mesh
   file the number of zones and dimensions from the numerical grid (required
   for variables allocation)  ---*/

  CConfig *config = NULL;
  config = new CConfig(config_file_name, SU2_DEF);

  nZone    = CConfig::GetnZone(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);
  periodic = CConfig::GetPeriodic(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);

  /*--- Definition of the containers per zones ---*/
  
  config_container = new CConfig*[nZone];
  geometry_container = new CGeometry*[nZone];
  
  for (iZone = 0; iZone < nZone; iZone++) {
    config_container[iZone]       = NULL;
    geometry_container[iZone]     = NULL;
  }
  
  /*--- Loop over all zones to initialize the various classes. In most
   cases, nZone is equal to one. This represents the solution of a partial
   differential equation on a single block, unstructured mesh. ---*/
  
  for (iZone = 0; iZone < nZone; iZone++) {
    
    /*--- Definition of the configuration option class for all zones. In this
     constructor, the input configuration file is parsed and all options are
     read and stored. ---*/
    
    config_container[iZone] = new CConfig(config_file_name, SU2_MSH, iZone, nZone, 0, VERB_HIGH);
    config_container[iZone]->SetMPICommunicator(MPICommunicator);
    
    /*--- Definition of the geometry class to store the primal grid in the partitioning process. ---*/
    
    CGeometry *geometry_aux = NULL;
    
    /*--- All ranks process the grid and call ParMETIS for partitioning ---*/
    
    geometry_aux = new CPhysicalGeometry(config_container[iZone], iZone, nZone);
    
    /*--- Color the initial grid and set the send-receive domains (ParMETIS) ---*/
    
    geometry_aux->SetColorGrid_Parallel(config_container[iZone]);
    
    /*--- Until we finish the new periodic BC implementation, use the old
     partitioning routines for cases with periodic BCs. The old routines 
     will be entirely removed eventually in favor of the new methods. ---*/

    if (periodic) {
      geometry_container[iZone] = new CPhysicalGeometry(geometry_aux, config_container[iZone]);
    } else {
      geometry_container[iZone] = new CPhysicalGeometry(geometry_aux, config_container[iZone], periodic);
    }
    
    /*--- Deallocate the memory of geometry_aux ---*/
    
    delete geometry_aux;
    
    /*--- Add the Send/Receive boundaries ---*/
    
    geometry_container[iZone]->SetSendReceive(config_container[iZone]);
    
    /*--- Add the Send/Receive boundaries ---*/
    
    geometry_container[iZone]->SetBoundaries(config_container[iZone]);
    
  }
  
  /*--- Set up a timer for performance benchmarking (preprocessing time is included) ---*/
  
#ifdef HAVE_MPI
  StartTime = MPI_Wtime();
#else
  StartTime = su2double(clock())/su2double(CLOCKS_PER_SEC);
#endif
  
	cout << endl <<"----------------------- Preprocessing computations ----------------------" << endl;
	
	/*--- Compute elements surrounding points, points surrounding points, and elements surronding elements ---*/
  
	cout << "Setting local point and element connectivity." <<endl;
	geometry_container[ZONE_0]->SetPoint_Connectivity(); geometry_container[ZONE_0]->SetElement_Connectivity();
	
	/*--- Check the orientation before computing geometrical quantities ---*/
  geometry_container[ZONE_0]->SetBoundVolume();
  if (config_container[ZONE_0]->GetReorientElements()) {
		cout << "Check numerical grid orientation." <<endl;
		geometry_container[ZONE_0]->Check_IntElem_Orientation(config_container[ZONE_0]); geometry_container[ZONE_0]->Check_BoundElem_Orientation(config_container[ZONE_0]);
  }
	
	/*--- Create the edge structure ---*/
  
	cout << "Identify faces, edges and vertices." <<endl;
	geometry_container[ZONE_0]->SetFaces(); geometry_container[ZONE_0]->SetEdges(); geometry_container[ZONE_0]->SetVertex(config_container[ZONE_0]); geometry_container[ZONE_0]->SetCoord_CG();
	
	/*--- Create the control volume structures ---*/
  
	cout << "Set control volume structure." << endl;
	geometry_container[ZONE_0]->SetControlVolume(config_container[ZONE_0], ALLOCATE); geometry_container[ZONE_0]->SetBoundControlVolume(config_container[ZONE_0], ALLOCATE);

	
	if ((config_container[ZONE_0]->GetKind_Adaptation() != NONE) && (config_container[ZONE_0]->GetKind_Adaptation() != PERIODIC)) {
		
		cout << endl <<"--------------------- Start numerical grid adaptation -------------------" << endl;
		
		/*-- Definition of the Class for grid adaptation ---*/
    
		CGridAdaptation *grid_adaptation;
		grid_adaptation = new CGridAdaptation(geometry_container[ZONE_0], config_container[ZONE_0]);
		
		/*--- Read the flow solution and/or the adjoint solution
		 and choose the elements to adapt ---*/
    
		if ((config_container[ZONE_0]->GetKind_Adaptation() != FULL)
				&& (config_container[ZONE_0]->GetKind_Adaptation() != WAKE) && (config_container[ZONE_0]->GetKind_Adaptation() != SMOOTHING) && (config_container[ZONE_0]->GetKind_Adaptation() != SUPERSONIC_SHOCK))
			grid_adaptation->GetFlowSolution(geometry_container[ZONE_0], config_container[ZONE_0]);
		
		switch (config_container[ZONE_0]->GetKind_Adaptation()) {
			case NONE:
				break;
			case SMOOTHING:
				config_container[ZONE_0]->SetSmoothNumGrid(true);
				grid_adaptation->SetNo_Refinement(geometry_container[ZONE_0], 1);
				break;
			case FULL:
				grid_adaptation->SetComplete_Refinement(geometry_container[ZONE_0], 1);
				break;
			case WAKE:
				grid_adaptation->SetWake_Refinement(geometry_container[ZONE_0], 1);
				break;
			case SUPERSONIC_SHOCK:
				grid_adaptation->SetSupShock_Refinement(geometry_container[ZONE_0], config_container[ZONE_0]);
				break;
			case FULL_FLOW:
				grid_adaptation->SetComplete_Refinement(geometry_container[ZONE_0], 1);
				break;
			case FULL_ADJOINT:
				grid_adaptation->GetAdjSolution(geometry_container[ZONE_0], config_container[ZONE_0]);
				grid_adaptation->SetComplete_Refinement(geometry_container[ZONE_0], 1);
				break;
			case GRAD_FLOW:
				grid_adaptation->SetIndicator_Flow(geometry_container[ZONE_0], config_container[ZONE_0], 1);
				break;
			case GRAD_ADJOINT:
				grid_adaptation->GetAdjSolution(geometry_container[ZONE_0], config_container[ZONE_0]);
				grid_adaptation->SetIndicator_Adj(geometry_container[ZONE_0], config_container[ZONE_0], 1);
				break;
			case GRAD_FLOW_ADJ:
				grid_adaptation->GetAdjSolution(geometry_container[ZONE_0], config_container[ZONE_0]);
				grid_adaptation->SetIndicator_FlowAdj(geometry_container[ZONE_0], config_container[ZONE_0]);
				break;
			case COMPUTABLE:
				grid_adaptation->GetAdjSolution(geometry_container[ZONE_0], config_container[ZONE_0]);
				grid_adaptation->GetFlowResidual(geometry_container[ZONE_0], config_container[ZONE_0]);
				grid_adaptation->SetIndicator_Computable(geometry_container[ZONE_0], config_container[ZONE_0]);
				break;
			case REMAINING:
        SU2_MPI::Error("Adaptation method not implemented.", CURRENT_FUNCTION);
				break;
			default :
				cout << "The adaptation is not defined" << endl;
		}
		
		/*--- Perform an homothetic adaptation of the grid ---*/
    
		CPhysicalGeometry *geo_adapt; geo_adapt = new CPhysicalGeometry;
		
		cout << "Homothetic grid adaptation" << endl;
		if (geometry_container[ZONE_0]->GetnDim() == 2) grid_adaptation->SetHomothetic_Adaptation2D(geometry_container[ZONE_0], geo_adapt, config_container[ZONE_0]);
		if (geometry_container[ZONE_0]->GetnDim() == 3) grid_adaptation->SetHomothetic_Adaptation3D(geometry_container[ZONE_0], geo_adapt, config_container[ZONE_0]);
    
		/*--- Smooth the numerical grid coordinates ---*/
    
		if (config_container[ZONE_0]->GetSmoothNumGrid()) {
			cout << "Preprocessing for doing the implicit smoothing." << endl;
			geo_adapt->SetPoint_Connectivity(); geo_adapt->SetElement_Connectivity();
			geo_adapt->SetBoundVolume();
			if (config_container[ZONE_0]->GetReorientElements()) {
				geo_adapt->Check_IntElem_Orientation(config_container[ZONE_0]); geo_adapt->Check_BoundElem_Orientation(config_container[ZONE_0]);
			}
			geo_adapt->SetEdges(); geo_adapt->SetVertex(config_container[ZONE_0]);
			cout << "Implicit smoothing of the numerical grid coordinates." << endl;
			geo_adapt->SetCoord_Smoothing(5, 1.5, config_container[ZONE_0]);
		}
		
		/*--- Original and adapted grid ---*/
    strcpy (file_name, "original_grid.dat");
    geometry_container[ZONE_0]->SetTecPlot(file_name, true);
    strcpy (file_name, "original_surface.dat");
    geometry_container[ZONE_0]->SetBoundTecPlot(file_name, true, config_container[ZONE_0]);
    
		/*--- Write the adapted grid sensor ---*/
    
    strcpy (file_name, "adapted_grid.dat");
    geo_adapt->SetTecPlot(file_name, true);
    strcpy (file_name, "adapted_surface.dat");
    geo_adapt->SetBoundTecPlot(file_name, true, config_container[ZONE_0]);
		
		/*--- Write the new adapted grid, including the modified boundaries surfaces ---*/
    
		geo_adapt->SetMeshFile(config_container[ZONE_0], config_container[ZONE_0]->GetMesh_Out_FileName());
    
    
		/*--- Write the restart file ---*/
    
		if ((config_container[ZONE_0]->GetKind_Adaptation() != SMOOTHING) && (config_container[ZONE_0]->GetKind_Adaptation() != FULL) &&
				(config_container[ZONE_0]->GetKind_Adaptation() != WAKE) &&
				(config_container[ZONE_0]->GetKind_Adaptation() != SUPERSONIC_SHOCK))
			grid_adaptation->SetRestart_FlowSolution(config_container[ZONE_0], geo_adapt, config_container[ZONE_0]->GetRestart_FlowFileName());
		
		if ((config_container[ZONE_0]->GetKind_Adaptation() == GRAD_FLOW_ADJ) || (config_container[ZONE_0]->GetKind_Adaptation() == GRAD_ADJOINT)
				|| (config_container[ZONE_0]->GetKind_Adaptation() == FULL_ADJOINT) || (config_container[ZONE_0]->GetKind_Adaptation() == COMPUTABLE) ||
				(config_container[ZONE_0]->GetKind_Adaptation() == REMAINING))
			grid_adaptation->SetRestart_AdjSolution(config_container[ZONE_0], geo_adapt, config_container[ZONE_0]->GetRestart_AdjFileName());
		
	}
	else {
    
    if (config_container[ZONE_0]->GetKind_Adaptation() == PERIODIC) {
      
      cout << endl <<"-------------------- Setting the periodic boundaries --------------------" << endl;
      
      /*--- Set periodic boundary conditions ---*/
      
      geometry_container[ZONE_0]->SetPeriodicBoundary(config_container[ZONE_0]);
      
      /*--- Original grid for debugging purposes ---*/
      
      strcpy (file_name, "periodic_original.dat"); geometry_container[ZONE_0]->SetTecPlot(file_name, true);
      
      /*--- Create a new grid with the right periodic boundary ---*/
      
      CGeometry *periodic; periodic = new CPeriodicGeometry(geometry_container[ZONE_0], config_container[ZONE_0]);
      periodic->SetPeriodicBoundary(geometry_container[ZONE_0], config_container[ZONE_0]);
      periodic->SetMeshFile(geometry_container[ZONE_0], config_container[ZONE_0], config_container[ZONE_0]->GetMesh_Out_FileName());
      
      /*--- Output of the grid for debuging purposes ---*/
      
      strcpy (file_name, "periodic_halo.dat"); periodic->SetTecPlot(file_name, true);
      
    }
    
    if (config_container[ZONE_0]->GetKind_Adaptation() == NONE) {
      strcpy (file_name, "original_grid.dat");
      geometry_container[ZONE_0]->SetTecPlot(file_name, true);
      geometry_container[ZONE_0]->SetMeshFile(config_container[ZONE_0], config_container[ZONE_0]->GetMesh_Out_FileName());
    }
    
	}
  
  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Solver Postprocessing -------------------------" << endl;
  
  if (geometry_container != NULL) {
    for (iZone = 0; iZone < nZone; iZone++) {
      if (geometry_container[iZone] != NULL) {
        delete geometry_container[iZone];
      }
    }
    delete [] geometry_container;
  }
  if (rank == MASTER_NODE) cout << "Deleted CGeometry container." << endl;
  
  
  if (config_container != NULL) {
    for (iZone = 0; iZone < nZone; iZone++) {
      if (config_container[iZone] != NULL) {
        delete config_container[iZone];
      }
    }
    delete [] config_container;
  }
  if (rank == MASTER_NODE) cout << "Deleted CConfig container." << endl;
  
  delete config;
  config = NULL;

  /*--- Synchronization point after a single solver iteration. Compute the
   wall clock time required. ---*/
  
#ifdef HAVE_MPI
  StopTime = MPI_Wtime();
#else
  StopTime = su2double(clock())/su2double(CLOCKS_PER_SEC);
#endif
  
  /*--- Compute/print the total time for performance benchmarking. ---*/
  
  UsedTime = StopTime-StartTime;
  if (rank == MASTER_NODE) {
    cout << "\nCompleted in " << fixed << UsedTime << " seconds on "<< size;
    if (size == 1) cout << " core." << endl; else cout << " cores." << endl;
  }
  
  /*--- Exit the solver cleanly ---*/
  
	cout << endl <<"------------------------- Exit Success (SU2_MSH) ------------------------" << endl << endl;
  
  /*--- Finalize MPI parallelization ---*/
  
#ifdef HAVE_MPI
  SU2_MPI::Finalize();
#endif
  
  return EXIT_SUCCESS;
  
}
示例#10
0
int main(int argc, char *argv[]) {
  
  bool StopCalc = false;
  double StartTime = 0.0, StopTime = 0.0, UsedTime = 0.0;
  unsigned long ExtIter = 0;
  unsigned short iMesh, iZone, iSol, nZone, nDim;
  char config_file_name[MAX_STRING_SIZE];
  char runtime_file_name[MAX_STRING_SIZE];
  ofstream ConvHist_file;
  int rank = MASTER_NODE;
  int size = SINGLE_NODE;
  
  /*--- MPI initialization, and buffer setting ---*/
  
#ifdef HAVE_MPI
  int *bptr, bl;
  MPI_Init(&argc, &argv);
  MPI_Buffer_attach( malloc(BUFSIZE), BUFSIZE );
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &size);
#endif
  
  /*--- Create pointers to all of the classes that may be used throughout
   the SU2_CFD code. In general, the pointers are instantiated down a
   heirarchy over all zones, multigrid levels, equation sets, and equation
   terms as described in the comments below. ---*/
  
  COutput *output                       = NULL;
  CIntegration ***integration_container = NULL;
  CGeometry ***geometry_container       = NULL;
  CSolver ****solver_container          = NULL;
  CNumerics *****numerics_container     = NULL;
  CConfig **config_container            = NULL;
  CSurfaceMovement **surface_movement   = NULL;
  CVolumetricMovement **grid_movement   = NULL;
  CFreeFormDefBox*** FFDBox             = NULL;
  
  /*--- Load in the number of zones and spatial dimensions in the mesh file (If no config
   file is specified, default.cfg is used) ---*/
  
  if (argc == 2) { strcpy(config_file_name, argv[1]); }
  else { strcpy(config_file_name, "default.cfg"); }
  
  /*--- Read the name and format of the input mesh file to get from the mesh
   file the number of zones and dimensions from the numerical grid (required
   for variables allocation)  ---*/
  
  CConfig *config = NULL;
  config = new CConfig(config_file_name, SU2_CFD);
  
  nZone = GetnZone(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);
  nDim  = GetnDim(config->GetMesh_FileName(), config->GetMesh_FileFormat());
  
  /*--- Definition and of the containers for all possible zones. ---*/
  
  solver_container      = new CSolver***[nZone];
  integration_container = new CIntegration**[nZone];
  numerics_container    = new CNumerics****[nZone];
  config_container      = new CConfig*[nZone];
  geometry_container    = new CGeometry**[nZone];
  surface_movement      = new CSurfaceMovement*[nZone];
  grid_movement         = new CVolumetricMovement*[nZone];
  FFDBox                = new CFreeFormDefBox**[nZone];
  
  for (iZone = 0; iZone < nZone; iZone++) {
    solver_container[iZone]       = NULL;
    integration_container[iZone]  = NULL;
    numerics_container[iZone]     = NULL;
    config_container[iZone]       = NULL;
    geometry_container[iZone]     = NULL;
    surface_movement[iZone]       = NULL;
    grid_movement[iZone]          = NULL;
    FFDBox[iZone]                 = NULL;
  }
  
  /*--- Loop over all zones to initialize the various classes. In most
   cases, nZone is equal to one. This represents the solution of a partial
   differential equation on a single block, unstructured mesh. ---*/
  
  for (iZone = 0; iZone < nZone; iZone++) {
    
    /*--- Definition of the configuration option class for all zones. In this
     constructor, the input configuration file is parsed and all options are
     read and stored. ---*/
    
    config_container[iZone] = new CConfig(config_file_name, SU2_CFD, iZone, nZone, nDim, VERB_HIGH);
    
    
    /*--- Definition of the geometry class to store the primal grid in the
     partitioning process. ---*/
    
    CGeometry *geometry_aux = NULL;
    
    /*--- All ranks process the grid and call ParMETIS for partitioning ---*/
    
    geometry_aux = new CPhysicalGeometry(config_container[iZone], iZone, nZone);
    
    /*--- Color the initial grid and set the send-receive domains (ParMETIS) ---*/
    
    geometry_aux->SetColorGrid_Parallel(config_container[iZone]);
    
    /*--- Allocate the memory of the current domain, and divide the grid 
     between the ranks. ---*/
    
    geometry_container[iZone] = new CGeometry *[config_container[iZone]->GetnMGLevels()+1];
    geometry_container[iZone][MESH_0] = new CPhysicalGeometry(geometry_aux, config_container[iZone], 1);
    
    /*--- Deallocate the memory of geometry_aux ---*/
    
    delete geometry_aux;
    
    /*--- Add the Send/Receive boundaries ---*/
    
    geometry_container[iZone][MESH_0]->SetSendReceive(config_container[iZone]);
    
    /*--- Add the Send/Receive boundaries ---*/
    
    geometry_container[iZone][MESH_0]->SetBoundaries(config_container[iZone]);
    
  }
  
  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Geometry Preprocessing ------------------------" << endl;
  
  /*--- Preprocessing of the geometry for all zones. In this routine, the edge-
   based data structure is constructed, i.e. node and cell neighbors are
   identified and linked, face areas and volumes of the dual mesh cells are
   computed, and the multigrid levels are created using an agglomeration procedure. ---*/
  
  Geometrical_Preprocessing(geometry_container, config_container, nZone);
  
  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Solver Preprocessing --------------------------" << endl;
  
  for (iZone = 0; iZone < nZone; iZone++) {
    
    /*--- Computation of wall distances for turbulence modeling ---*/
    
    if ( (config_container[iZone]->GetKind_Solver() == RANS) ||
        (config_container[iZone]->GetKind_Solver() == ADJ_RANS) )
      geometry_container[iZone][MESH_0]->ComputeWall_Distance(config_container[iZone]);
    
    /*--- Computation of positive surface area in the z-plane which is used for
     the calculation of force coefficient (non-dimensionalization). ---*/
    
    geometry_container[iZone][MESH_0]->SetPositive_ZArea(config_container[iZone]);
    
    /*--- Set the near-field, interface and actuator disk boundary conditions, if necessary. ---*/
    
    for (iMesh = 0; iMesh <= config_container[iZone]->GetnMGLevels(); iMesh++) {
      geometry_container[iZone][iMesh]->MatchNearField(config_container[iZone]);
      geometry_container[iZone][iMesh]->MatchInterface(config_container[iZone]);
      geometry_container[iZone][iMesh]->MatchActuator_Disk(config_container[iZone]);
    }
    
    /*--- Definition of the solver class: solver_container[#ZONES][#MG_GRIDS][#EQ_SYSTEMS].
     The solver classes are specific to a particular set of governing equations,
     and they contain the subroutines with instructions for computing each spatial
     term of the PDE, i.e. loops over the edges to compute convective and viscous
     fluxes, loops over the nodes to compute source terms, and routines for
     imposing various boundary condition type for the PDE. ---*/
    
    solver_container[iZone] = new CSolver** [config_container[iZone]->GetnMGLevels()+1];
    for (iMesh = 0; iMesh <= config_container[iZone]->GetnMGLevels(); iMesh++)
      solver_container[iZone][iMesh] = NULL;
    
    for (iMesh = 0; iMesh <= config_container[iZone]->GetnMGLevels(); iMesh++) {
      solver_container[iZone][iMesh] = new CSolver* [MAX_SOLS];
      for (iSol = 0; iSol < MAX_SOLS; iSol++)
        solver_container[iZone][iMesh][iSol] = NULL;
    }
    Solver_Preprocessing(solver_container[iZone], geometry_container[iZone],
                         config_container[iZone], iZone);
    
    if (rank == MASTER_NODE)
      cout << endl <<"----------------- Integration and Numerics Preprocessing ----------------" << endl;
    
    /*--- Definition of the integration class: integration_container[#ZONES][#EQ_SYSTEMS].
     The integration class orchestrates the execution of the spatial integration
     subroutines contained in the solver class (including multigrid) for computing
     the residual at each node, R(U) and then integrates the equations to a
     steady state or time-accurately. ---*/
    
    integration_container[iZone] = new CIntegration*[MAX_SOLS];
    Integration_Preprocessing(integration_container[iZone], geometry_container[iZone],
                              config_container[iZone], iZone);
    
    if (rank == MASTER_NODE) cout << "Integration Preprocessing." << endl;
    
    /*--- Definition of the numerical method class:
     numerics_container[#ZONES][#MG_GRIDS][#EQ_SYSTEMS][#EQ_TERMS].
     The numerics class contains the implementation of the numerical methods for
     evaluating convective or viscous fluxes between any two nodes in the edge-based
     data structure (centered, upwind, galerkin), as well as any source terms
     (piecewise constant reconstruction) evaluated in each dual mesh volume. ---*/
    
    numerics_container[iZone] = new CNumerics***[config_container[iZone]->GetnMGLevels()+1];
    Numerics_Preprocessing(numerics_container[iZone], solver_container[iZone],
                           geometry_container[iZone], config_container[iZone], iZone);
    
    if (rank == MASTER_NODE) cout << "Numerics Preprocessing." << endl;
    
    /*--- Instantiate the geometry movement classes for the solution of unsteady
     flows on dynamic meshes, including rigid mesh transformations, dynamically
     deforming meshes, and time-spectral preprocessing. ---*/
    
    if (config_container[iZone]->GetGrid_Movement()) {
      if (rank == MASTER_NODE)
        cout << "Setting dynamic mesh structure." << endl;
      grid_movement[iZone] = new CVolumetricMovement(geometry_container[iZone][MESH_0]);
      FFDBox[iZone] = new CFreeFormDefBox*[MAX_NUMBER_FFD];
      surface_movement[iZone] = new CSurfaceMovement();
      surface_movement[iZone]->CopyBoundary(geometry_container[iZone][MESH_0], config_container[iZone]);
      if (config_container[iZone]->GetUnsteady_Simulation() == TIME_SPECTRAL)
        SetGrid_Movement(geometry_container[iZone], surface_movement[iZone], grid_movement[iZone],
                         FFDBox[iZone], solver_container[iZone], config_container[iZone], iZone, 0, 0);
    }
    
  }
  
  /*--- For the time-spectral solver, set the grid node velocities. ---*/
  
  if (config_container[ZONE_0]->GetUnsteady_Simulation() == TIME_SPECTRAL)
    SetTimeSpectral_Velocities(geometry_container, config_container, nZone);
  
  /*--- Coupling between zones (limited to two zones at the moment) ---*/
  
  if (nZone == 2) {
    if (rank == MASTER_NODE)
      cout << endl <<"--------------------- Setting Coupling Between Zones --------------------" << endl;
    geometry_container[ZONE_0][MESH_0]->MatchZone(config_container[ZONE_0], geometry_container[ZONE_1][MESH_0],
                                                  config_container[ZONE_1], ZONE_0, nZone);
    geometry_container[ZONE_1][MESH_0]->MatchZone(config_container[ZONE_1], geometry_container[ZONE_0][MESH_0],
                                                  config_container[ZONE_0], ZONE_1, nZone);
  }
  
  /*--- Definition of the output class (one for all zones). The output class
   manages the writing of all restart, volume solution, surface solution,
   surface comma-separated value, and convergence history files (both in serial
   and in parallel). ---*/
  
  output = new COutput();
  
  /*--- Open the convergence history file ---*/
  
  if (rank == MASTER_NODE)
    output->SetConvHistory_Header(&ConvHist_file, config_container[ZONE_0]);
  
  /*--- Check for an unsteady restart. Update ExtIter if necessary. ---*/
  if (config_container[ZONE_0]->GetWrt_Unsteady() && config_container[ZONE_0]->GetRestart())
    ExtIter = config_container[ZONE_0]->GetUnst_RestartIter();
  
  /*--- Main external loop of the solver. Within this loop, each iteration ---*/
  
  if (rank == MASTER_NODE)
    cout << endl <<"------------------------------ Begin Solver -----------------------------" << endl;
  
  /*--- Set up a timer for performance benchmarking (preprocessing time is not included) ---*/
  
#ifndef HAVE_MPI
  StartTime = double(clock())/double(CLOCKS_PER_SEC);
#else
  StartTime = MPI_Wtime();
#endif
  
  while (ExtIter < config_container[ZONE_0]->GetnExtIter()) {
    
    /*--- Set the value of the external iteration. ---*/
    
    config_container[ZONE_0]->SetExtIter(ExtIter);
    
    /*--- Read the target pressure ---*/
    
    if (config_container[ZONE_0]->GetInvDesign_Cp() == YES)
      output->SetCp_InverseDesign(solver_container[ZONE_0][MESH_0][FLOW_SOL],
                                  geometry_container[ZONE_0][MESH_0], config_container[ZONE_0], ExtIter);
    
    /*--- Read the target heat flux ---*/
    
    if (config_container[ZONE_0]->GetInvDesign_HeatFlux() == YES)
      output->SetHeat_InverseDesign(solver_container[ZONE_0][MESH_0][FLOW_SOL],
                                    geometry_container[ZONE_0][MESH_0], config_container[ZONE_0], ExtIter);
    
    /*--- Perform a single iteration of the chosen PDE solver. ---*/
    
    switch (config_container[ZONE_0]->GetKind_Solver()) {
        
      case EULER: case NAVIER_STOKES: case RANS:
        MeanFlowIteration(output, integration_container, geometry_container,
                          solver_container, numerics_container, config_container,
                          surface_movement, grid_movement, FFDBox);
        break;
        
      case TNE2_EULER: case TNE2_NAVIER_STOKES:
        TNE2Iteration(output, integration_container,
                      geometry_container, solver_container,
                      numerics_container, config_container,
                      surface_movement, grid_movement, FFDBox);
        break;
        
      case FLUID_STRUCTURE_EULER: case FLUID_STRUCTURE_NAVIER_STOKES:
        FluidStructureIteration(output, integration_container, geometry_container,
                                solver_container, numerics_container, config_container,
                                surface_movement, grid_movement, FFDBox);
        break;
        
      case WAVE_EQUATION:
        WaveIteration(output, integration_container, geometry_container,
                      solver_container, numerics_container, config_container,
                      surface_movement, grid_movement, FFDBox);
        break;
        
      case HEAT_EQUATION:
        HeatIteration(output, integration_container, geometry_container,
                      solver_container, numerics_container, config_container,
                      surface_movement, grid_movement, FFDBox);
        break;
        
      case POISSON_EQUATION:
        PoissonIteration(output, integration_container, geometry_container,
                         solver_container, numerics_container, config_container,
                         surface_movement, grid_movement, FFDBox);
        break;
        
      case LINEAR_ELASTICITY:
        FEAIteration(output, integration_container, geometry_container,
                     solver_container, numerics_container, config_container,
                     surface_movement, grid_movement, FFDBox);
        break;
        
      case ADJ_EULER: case ADJ_NAVIER_STOKES: case ADJ_RANS:
        AdjMeanFlowIteration(output, integration_container, geometry_container,
                             solver_container, numerics_container, config_container,
                             surface_movement, grid_movement, FFDBox);
        break;
        
      case ADJ_TNE2_EULER: case ADJ_TNE2_NAVIER_STOKES:
        AdjTNE2Iteration(output, integration_container, geometry_container,
                         solver_container, numerics_container, config_container,
                         surface_movement, grid_movement, FFDBox);
        break;
    }
    
    
    /*--- Synchronization point after a single solver iteration. Compute the
     wall clock time required. ---*/
    
#ifndef HAVE_MPI
    StopTime = double(clock())/double(CLOCKS_PER_SEC);
#else
    StopTime = MPI_Wtime();
#endif
    
    UsedTime = (StopTime - StartTime);
    
    /*--- For specific applications, evaluate and plot the equivalent area. ---*/
    
    if (config_container[ZONE_0]->GetEquivArea() == YES) {
      output->SetEquivalentArea(solver_container[ZONE_0][MESH_0][FLOW_SOL],
                                geometry_container[ZONE_0][MESH_0], config_container[ZONE_0], ExtIter);
    }
    
    /*--- Check if there is any change in the runtime parameters ---*/
    
    CConfig *runtime = NULL;
    strcpy(runtime_file_name, "runtime.dat");
    runtime = new CConfig(runtime_file_name, config_container[ZONE_0]);
    
    /*--- Update the convergence history file (serial and parallel computations). ---*/
    
    output->SetConvHistory_Body(&ConvHist_file, geometry_container, solver_container,
                                config_container, integration_container, false, UsedTime, ZONE_0);
    
    /*--- Evaluate the new CFL number (adaptive). ---*/
    
    if (config_container[ZONE_0]->GetCFL_Adapt() == YES) {
      output->SetCFL_Number(solver_container, config_container, ZONE_0);
    }
    
    /*--- Check whether the current simulation has reached the specified
     convergence criteria, and set StopCalc to true, if so. ---*/
    
    switch (config_container[ZONE_0]->GetKind_Solver()) {
      case EULER: case NAVIER_STOKES: case RANS:
        StopCalc = integration_container[ZONE_0][FLOW_SOL]->GetConvergence(); break;
      case TNE2_EULER: case TNE2_NAVIER_STOKES:
        StopCalc = integration_container[ZONE_0][TNE2_SOL]->GetConvergence(); break;
      case WAVE_EQUATION:
        StopCalc = integration_container[ZONE_0][WAVE_SOL]->GetConvergence(); break;
      case HEAT_EQUATION:
        StopCalc = integration_container[ZONE_0][HEAT_SOL]->GetConvergence(); break;
      case LINEAR_ELASTICITY:
        StopCalc = integration_container[ZONE_0][FEA_SOL]->GetConvergence(); break;
      case ADJ_EULER: case ADJ_NAVIER_STOKES: case ADJ_RANS:
        StopCalc = integration_container[ZONE_0][ADJFLOW_SOL]->GetConvergence(); break;
      case ADJ_TNE2_EULER: case ADJ_TNE2_NAVIER_STOKES:
        StopCalc = integration_container[ZONE_0][ADJTNE2_SOL]->GetConvergence(); break;
    }
    
    /*--- Solution output. Determine whether a solution needs to be written
     after the current iteration, and if so, execute the output file writing
     routines. ---*/
    
    if ((ExtIter+1 >= config_container[ZONE_0]->GetnExtIter()) ||
        ((ExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq() == 0) && (ExtIter != 0) &&
         !((config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
           (config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_2ND))) ||
        (StopCalc) ||
        (((config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
          (config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_2ND)) &&
         ((ExtIter == 0) || (ExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0)))) {
          
          /*--- Low-fidelity simulations (using a coarser multigrid level
           approximation to the solution) require an interpolation back to the
           finest grid. ---*/
          
          if (config_container[ZONE_0]->GetLowFidelitySim()) {
            integration_container[ZONE_0][FLOW_SOL]->SetProlongated_Solution(RUNTIME_FLOW_SYS, solver_container[ZONE_0][MESH_0][FLOW_SOL], solver_container[ZONE_0][MESH_1][FLOW_SOL], geometry_container[ZONE_0][MESH_0], geometry_container[ZONE_0][MESH_1], config_container[ZONE_0]);
            integration_container[ZONE_0][FLOW_SOL]->Smooth_Solution(RUNTIME_FLOW_SYS, solver_container[ZONE_0][MESH_0][FLOW_SOL], geometry_container[ZONE_0][MESH_0], 3, 1.25, config_container[ZONE_0]);
            solver_container[ZONE_0][MESH_0][config_container[ZONE_0]->GetContainerPosition(RUNTIME_FLOW_SYS)]->Set_MPI_Solution(geometry_container[ZONE_0][MESH_0], config_container[ZONE_0]);
            solver_container[ZONE_0][MESH_0][config_container[ZONE_0]->GetContainerPosition(RUNTIME_FLOW_SYS)]->Preprocessing(geometry_container[ZONE_0][MESH_0], solver_container[ZONE_0][MESH_0], config_container[ZONE_0], MESH_0, 0, RUNTIME_FLOW_SYS, false);
          }
          
          if (rank == MASTER_NODE) cout << endl << "-------------------------- File Output Summary --------------------------";
          
          /*--- Execute the routine for writing restart, volume solution,
           surface solution, and surface comma-separated value files. ---*/
          
          output->SetResult_Files(solver_container, geometry_container, config_container, ExtIter, nZone);
          
          /*--- Output a file with the forces breakdown. ---*/
          
          output->SetForces_Breakdown(geometry_container, solver_container,
                                      config_container, integration_container, ZONE_0);
          
          /*--- Compute the forces at different sections. ---*/
          
          if (config_container[ZONE_0]->GetPlot_Section_Forces()) {
            output->SetForceSections(solver_container[ZONE_0][MESH_0][FLOW_SOL],
                                     geometry_container[ZONE_0][MESH_0], config_container[ZONE_0], ExtIter);
          }
          
          if (rank == MASTER_NODE) cout << "-------------------------------------------------------------------------" << endl << endl;
          
        }
    
    /*--- If the convergence criteria has been met, terminate the simulation. ---*/
    
    if (StopCalc) break;
    
    ExtIter++;
    
  }
  
  /*--- Output some information to the console. ---*/
  
  if (rank == MASTER_NODE) {
    
    /*--- Print out the number of non-physical points and reconstructions ---*/
    
    if (config_container[ZONE_0]->GetNonphysical_Points() > 0)
      cout << "Warning: there are " << config_container[ZONE_0]->GetNonphysical_Points() << " non-physical points in the solution." << endl;
    if (config_container[ZONE_0]->GetNonphysical_Reconstr() > 0)
      cout << "Warning: " << config_container[ZONE_0]->GetNonphysical_Reconstr() << " reconstructed states for upwinding are non-physical." << endl;
    
    /*--- Close the convergence history file. ---*/
    
    ConvHist_file.close();
    cout << "History file, closed." << endl;
  }
  
  //  /*--- Deallocate config container ---*/
  //
  //  for (iZone = 0; iZone < nZone; iZone++) {
  //    if (config_container[iZone] != NULL) {
  //      delete config_container[iZone];
  //    }
  //  }
  //  if (config_container != NULL) delete[] config_container;
  
  
  /*--- Synchronization point after a single solver iteration. Compute the
   wall clock time required. ---*/
  
#ifndef HAVE_MPI
  StopTime = double(clock())/double(CLOCKS_PER_SEC);
#else
  StopTime = MPI_Wtime();
#endif
  
  /*--- Compute/print the total time for performance benchmarking. ---*/
  
  UsedTime = StopTime-StartTime;
  if (rank == MASTER_NODE) {
    cout << "\nCompleted in " << fixed << UsedTime << " seconds on "<< size;
    if (size == 1) cout << " core." << endl; else cout << " cores." << endl;
  }
  
  /*--- Exit the solver cleanly ---*/
  
  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Exit Success (SU2_CFD) ------------------------" << endl << endl;
  
#ifdef HAVE_MPI
  /*--- Finalize MPI parallelization ---*/
  MPI_Buffer_detach(&bptr, &bl);
  MPI_Finalize();
#endif
  
  return EXIT_SUCCESS;
  
}
示例#11
0
文件: SU2_SOL.cpp 项目: su2code/SU2
int main(int argc, char *argv[]) {

  unsigned short iZone, nZone = SINGLE_ZONE, iInst;
  su2double StartTime = 0.0, StopTime = 0.0, UsedTime = 0.0;
  ofstream ConvHist_file;
  char config_file_name[MAX_STRING_SIZE];
  int rank = MASTER_NODE;
  int size = SINGLE_NODE;
  bool fem_solver = false;
  bool periodic = false;
  bool multizone = false;

  /*--- MPI initialization ---*/

#ifdef HAVE_MPI
  SU2_MPI::Init(&argc,&argv);
  SU2_MPI::Comm MPICommunicator(MPI_COMM_WORLD);
#else
  SU2_Comm MPICommunicator(0);
#endif

  rank = SU2_MPI::GetRank();
  size = SU2_MPI::GetSize();

  /*--- Pointer to different structures that will be used throughout the entire code ---*/

  COutput *output                 = NULL;
  CGeometry ***geometry_container = NULL;
  CSolver ***solver_container     = NULL;
  CConfig **config_container      = NULL;
  CConfig *driver_config          = NULL;
  unsigned short *nInst           = NULL;

  /*--- Load in the number of zones and spatial dimensions in the mesh file (if no config
   file is specified, default.cfg is used) ---*/

  if (argc == 2 || argc == 3) { strcpy(config_file_name,argv[1]); }
  else { strcpy(config_file_name, "default.cfg"); }

  CConfig *config = NULL;
  config = new CConfig(config_file_name, SU2_SOL);

  if (config->GetKind_Solver() == MULTIZONE) nZone  = config->GetnConfigFiles();
  else nZone  = CConfig::GetnZone(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);
  periodic = CConfig::GetPeriodic(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);

  /*--- Definition of the containers per zones ---*/

  solver_container = new CSolver**[nZone];
  config_container = new CConfig*[nZone];
  geometry_container = new CGeometry**[nZone];
  nInst = new unsigned short[nZone];
  driver_config = NULL;

  for (iZone = 0; iZone < nZone; iZone++) {
    solver_container[iZone]       = NULL;
    config_container[iZone]       = NULL;
    geometry_container[iZone]     = NULL;
    nInst[iZone]                  = 1;
  }

  /*--- Initialize the configuration of the driver ---*/
  driver_config = new CConfig(config_file_name, SU2_SOL, ZONE_0, nZone, 0, VERB_NONE);

  /*--- Initialize a char to store the zone filename ---*/
  char zone_file_name[MAX_STRING_SIZE];

  /*--- Store a boolean for multizone problems ---*/
  multizone = (driver_config->GetKind_Solver() == MULTIZONE);

  /*--- Loop over all zones to initialize the various classes. In most
   cases, nZone is equal to one. This represents the solution of a partial
   differential equation on a single block, unstructured mesh. ---*/

  for (iZone = 0; iZone < nZone; iZone++) {

    /*--- Definition of the configuration option class for all zones. In this
     constructor, the input configuration file is parsed and all options are
     read and stored. ---*/

    if (multizone){
      strcpy(zone_file_name, driver_config->GetConfigFilename(iZone).c_str());
      config_container[iZone] = new CConfig(zone_file_name, SU2_SOL, iZone, nZone, 0, VERB_HIGH);
    }
    else{
      config_container[iZone] = new CConfig(config_file_name, SU2_SOL, iZone, nZone, 0, VERB_HIGH);
    }
    config_container[iZone]->SetMPICommunicator(MPICommunicator);

  }

  /*--- Set the multizone part of the problem. ---*/
  if (driver_config->GetKind_Solver() == MULTIZONE){
    for (iZone = 0; iZone < nZone; iZone++) {
      /*--- Set the interface markers for multizone ---*/
      config_container[iZone]->SetMultizone(driver_config, config_container);
    }
  }

  /*--- Read the geometry for each zone ---*/
  for (iZone = 0; iZone < nZone; iZone++) {

    /*--- Determine whether or not the FEM solver is used, which decides the
     type of geometry classes that are instantiated. ---*/
    fem_solver = ((config_container[iZone]->GetKind_Solver() == FEM_EULER)          ||
                  (config_container[iZone]->GetKind_Solver() == FEM_NAVIER_STOKES)  ||
                  (config_container[iZone]->GetKind_Solver() == FEM_RANS)           ||
                  (config_container[iZone]->GetKind_Solver() == FEM_LES)            ||
                  (config_container[iZone]->GetKind_Solver() == DISC_ADJ_FEM_EULER) ||
                  (config_container[iZone]->GetKind_Solver() == DISC_ADJ_FEM_NS)    ||
                  (config_container[iZone]->GetKind_Solver() == DISC_ADJ_FEM_RANS));

    /*--- Read the number of instances for each zone ---*/

    nInst[iZone] = config_container[iZone]->GetnTimeInstances();

    geometry_container[iZone] = new CGeometry*[nInst[iZone]];
    solver_container[iZone] = new CSolver*[nInst[iZone]];

    for (iInst = 0; iInst < nInst[iZone]; iInst++){

      /*--- Allocate solver. ---*/
      solver_container[iZone][iInst] = NULL;

      config_container[iZone]->SetiInst(iInst);

      /*--- Definition of the geometry class to store the primal grid in the partitioning process. ---*/

      CGeometry *geometry_aux = NULL;

      /*--- All ranks process the grid and call ParMETIS for partitioning ---*/

      geometry_aux = new CPhysicalGeometry(config_container[iZone], iZone, nZone);

      /*--- Color the initial grid and set the send-receive domains (ParMETIS) ---*/

      if ( fem_solver ) geometry_aux->SetColorFEMGrid_Parallel(config_container[iZone]);
      else              geometry_aux->SetColorGrid_Parallel(config_container[iZone]);

      /*--- Allocate the memory of the current domain, and
     divide the grid between the nodes ---*/

      geometry_container[iZone][iInst] = NULL;

      /*--- Until we finish the new periodic BC implementation, use the old
       partitioning routines for cases with periodic BCs. The old routines 
       will be entirely removed eventually in favor of the new methods. ---*/

      if( fem_solver ) {
        switch( config_container[iZone]->GetKind_FEM_Flow() ) {
          case DG: {
            geometry_container[iZone][iInst] = new CMeshFEM_DG(geometry_aux, config_container[iZone]);
            break;
          }
        }
      }
      else {
        if (periodic) {
          geometry_container[iZone][iInst] = new CPhysicalGeometry(geometry_aux, config_container[iZone]);
        } else {
          geometry_container[iZone][iInst] = new CPhysicalGeometry(geometry_aux, config_container[iZone], periodic);
        }
      }

      /*--- Deallocate the memory of geometry_aux ---*/

      delete geometry_aux;

      /*--- Add the Send/Receive boundaries ---*/

      geometry_container[iZone][iInst]->SetSendReceive(config_container[iZone]);

      /*--- Add the Send/Receive boundaries ---*/

      geometry_container[iZone][iInst]->SetBoundaries(config_container[iZone]);

      /*--- Create the vertex structure (required for MPI) ---*/

      if (rank == MASTER_NODE) cout << "Identify vertices." <<endl;
      geometry_container[iZone][iInst]->SetVertex(config_container[iZone]);

      /*--- Store the global to local mapping after preprocessing. ---*/

      if (rank == MASTER_NODE) cout << "Storing a mapping from global to local point index." << endl;
      geometry_container[iZone][iInst]->SetGlobal_to_Local_Point();

      /* Test for a fem solver, because some more work must be done. */

      if (fem_solver) {

        /*--- Carry out a dynamic cast to CMeshFEM_DG, such that it is not needed to
         define all virtual functions in the base class CGeometry. ---*/
        CMeshFEM_DG *DGMesh = dynamic_cast<CMeshFEM_DG *>(geometry_container[iZone][iInst]);

        /*--- Determine the standard elements for the volume elements. ---*/
        if (rank == MASTER_NODE) cout << "Creating standard volume elements." << endl;
        DGMesh->CreateStandardVolumeElements(config_container[iZone]);

        /*--- Create the face information needed to compute the contour integral
         for the elements in the Discontinuous Galerkin formulation. ---*/
        if (rank == MASTER_NODE) cout << "Creating face information." << endl;
        DGMesh->CreateFaces(config_container[iZone]);
      }
    }

  }

  /*--- Determine whether the simulation is a FSI simulation ---*/

  bool fsi = config_container[ZONE_0]->GetFSI_Simulation();

  /*--- Set up a timer for performance benchmarking (preprocessing time is included) ---*/

#ifdef HAVE_MPI
  StartTime = MPI_Wtime();
#else
  StartTime = su2double(clock())/su2double(CLOCKS_PER_SEC);
#endif

  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Solution Postprocessing -----------------------" << endl;
  
	/*--- Definition of the output class (one for all the zones) ---*/
	output = new COutput(config_container[ZONE_0]);
  
  /*---  Check whether this is an FSI, fluid unsteady, harmonic balance or structural dynamic simulation and call the
   solution merging routines accordingly.---*/

  if (multizone){

    bool TimeDomain = driver_config->GetTime_Domain();

    if (TimeDomain){

      su2double Physical_dt, Physical_t;
      unsigned long TimeIter = 0;
      bool StopCalc = false;

      /*--- Physical time step ---*/
      Physical_dt = driver_config->GetTime_Step();

      /*--- Check for an unsteady restart. Update TimeIter if necessary. ---*/
      if (driver_config->GetRestart()){
        TimeIter = driver_config->GetRestart_Iter();
      }

      /*--- Instantiate the solvers for each zone. ---*/
      for (iZone = 0; iZone < nZone; iZone++){
        config_container[iZone]->SetiInst(INST_0);
        config_container[iZone]->SetExtIter(TimeIter);
        solver_container[iZone][INST_0] = new CBaselineSolver(geometry_container[iZone][INST_0], config_container[iZone]);
      }

      /*--- Loop over the whole time domain ---*/
      while (TimeIter < driver_config->GetnTime_Iter()) {

        /*--- Check if the maximum time has been surpassed. ---*/
        Physical_t  = (TimeIter+1)*Physical_dt;
        if (Physical_t >=  driver_config->GetMax_Time())
          StopCalc = true;

        if ((TimeIter+1 == driver_config->GetnTime_Iter()) || // The last time iteration
            (StopCalc) || // We have surpassed the requested time
            ((TimeIter == 0) || (TimeIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0)) // The iteration has been requested
          ){

          /*--- Load the restart for all the zones. ---*/
          for (iZone = 0; iZone < nZone; iZone++){

            /*--- Set the current iteration number in the config class. ---*/
            config_container[iZone]->SetExtIter(TimeIter);
            /*--- So far, only enabled for single-instance problems ---*/
            config_container[iZone]->SetiInst(INST_0);
            solver_container[iZone][INST_0]->LoadRestart(geometry_container[iZone], &solver_container[iZone], config_container[iZone], SU2_TYPE::Int(MESH_0), true);
          }

          if (rank == MASTER_NODE) cout << "Writing the volume solution for time step " << TimeIter << ", t = " << Physical_t << " s ." << endl;
          output->SetBaselineResult_Files(solver_container, geometry_container, config_container, TimeIter, nZone);
        }

        TimeIter++;
        if (StopCalc) break;
      }
    }
    else {

      /*--- Steady simulation: merge the solution files for each zone. ---*/
      for (iZone = 0; iZone < nZone; iZone++) {
        config_container[iZone]->SetiInst(INST_0);
        /*--- Definition of the solution class ---*/
        solver_container[iZone][INST_0] = new CBaselineSolver(geometry_container[iZone][INST_0], config_container[iZone]);
        solver_container[iZone][INST_0]->LoadRestart(geometry_container[iZone], &solver_container[iZone], config_container[iZone], SU2_TYPE::Int(MESH_0), true);
      }
      output->SetBaselineResult_Files(solver_container, geometry_container, config_container, 0, nZone);
    }

  }
  else if (fsi){

    if (nZone < 2){
      SU2_MPI::Error("For multizone computations, please add the number of zones as a second argument for SU2_SOL.", CURRENT_FUNCTION);
    }

    su2double Physical_dt, Physical_t;
    unsigned long iExtIter = 0, iExtIterFlow = 0, iExtIterFEM = 0;
    bool StopCalc = false;
    bool SolutionInstantiatedFlow = false, SolutionInstantiatedFEM = false;

    /*--- Check for an unsteady restart. Update ExtIter if necessary. ---*/
    if (config_container[ZONE_0]->GetRestart()){
      iExtIterFlow = config_container[ZONE_0]->GetUnst_RestartIter();
      iExtIterFEM = config_container[ZONE_1]->GetDyn_RestartIter();
      if (iExtIterFlow != iExtIterFEM) {
        SU2_MPI::Error("For multizone computations, please add the number of zones as a second argument for SU2_SOL.", CURRENT_FUNCTION);
      }
      else {
        iExtIter = iExtIterFlow;
      }
    }


    while (iExtIter < config_container[ZONE_0]->GetnExtIter()) {

      /*--- Check several conditions in order to merge the correct time step files. ---*/

      Physical_dt = config_container[ZONE_0]->GetDelta_UnstTime();
      Physical_t  = (iExtIter+1)*Physical_dt;
      if (Physical_t >=  config_container[ZONE_0]->GetTotal_UnstTime())
        StopCalc = true;

      if (
          ((iExtIter+1 == config_container[ZONE_0]->GetnExtIter()) ||
           ((iExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq() == 0) && (iExtIter != 0) &&
            !((config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
              (config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_2ND))) ||
           (StopCalc) ||
           (((config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
             (config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_2ND)) &&
            ((iExtIter == 0) || (iExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0))))

          &&

          ((iExtIter+1 == config_container[ZONE_1]->GetnExtIter()) ||
           (StopCalc) ||
           ((config_container[ZONE_1]->GetDynamic_Analysis() == DYNAMIC) &&
            ((iExtIter == 0) || (iExtIter % config_container[ZONE_1]->GetWrt_Sol_Freq_DualTime() == 0))))

          ){

        /*--- Set the current iteration number in the config class. ---*/
        config_container[ZONE_0]->SetExtIter(iExtIter);
        config_container[ZONE_1]->SetExtIter(iExtIter);

        /*--- Read in the restart file for this time step ---*/

        /*--- For the fluid zone (ZONE_0) ---*/
        /*--- Either instantiate the solution class or load a restart file. ---*/
        if (SolutionInstantiatedFlow == false &&
            (iExtIter == 0 || ((config_container[ZONE_0]->GetRestart() && (SU2_TYPE::Int(iExtIter) == config_container[ZONE_0]->GetUnst_RestartIter())) ||
                               iExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0 ||
                               iExtIter+1 == config_container[ZONE_0]->GetnExtIter()))) {
          solver_container[ZONE_0][INST_0] = new CBaselineSolver(geometry_container[ZONE_0][INST_0], config_container[ZONE_0]);
          SolutionInstantiatedFlow = true;
        }
          solver_container[ZONE_0][INST_0]->LoadRestart_FSI(geometry_container[ZONE_0][INST_0], config_container[ZONE_0], SU2_TYPE::Int(MESH_0));


        /*--- For the structural zone (ZONE_1) ---*/
        /*--- Either instantiate the solution class or load a restart file. ---*/
        /*--- Either instantiate the solution class or load a restart file. ---*/
        if (SolutionInstantiatedFEM == false &&
            (iExtIter == 0 || ((config_container[ZONE_1]->GetRestart() && (SU2_TYPE::Int(iExtIter) == config_container[ZONE_1]->GetDyn_RestartIter())) ||
                               iExtIter % config_container[ZONE_1]->GetWrt_Sol_Freq_DualTime() == 0 ||
                               iExtIter+1 == config_container[ZONE_1]->GetnExtIter()))) {
          solver_container[ZONE_1][INST_0] = new CBaselineSolver(geometry_container[ZONE_1][INST_0], config_container[ZONE_1]);
          SolutionInstantiatedFEM = true;
        }
          solver_container[ZONE_1][INST_0]->LoadRestart_FSI(geometry_container[ZONE_1][INST_0], config_container[ZONE_1], SU2_TYPE::Int(MESH_0));

        if (rank == MASTER_NODE) cout << "Writing the volume solution for time step " << iExtIter << "." << endl;
        output->SetBaselineResult_Files(solver_container, geometry_container, config_container, iExtIter, nZone);
      }

      iExtIter++;
      if (StopCalc) break;
    }

  } else if (fem_solver) {

    if (config_container[ZONE_0]->GetWrt_Unsteady()) {

      /*--- Unsteady DG simulation: merge all unsteady time steps. First,
       find the frequency and total number of files to write. ---*/

      su2double Physical_dt, Physical_t;
      unsigned long iExtIter = 0;
      bool StopCalc = false;
      bool *SolutionInstantiated = new bool[nZone];

      for (iZone = 0; iZone < nZone; iZone++)
        SolutionInstantiated[iZone] = false;

      /*--- Check for an unsteady restart. Update ExtIter if necessary. ---*/
      if (config_container[ZONE_0]->GetWrt_Unsteady() && config_container[ZONE_0]->GetRestart())
        iExtIter = config_container[ZONE_0]->GetUnst_RestartIter();

      while (iExtIter < config_container[ZONE_0]->GetnExtIter()) {

        /*--- Check several conditions in order to merge the correct time step files. ---*/
        Physical_dt = config_container[ZONE_0]->GetDelta_UnstTime();
        Physical_t  = (iExtIter+1)*Physical_dt;
        if (Physical_t >=  config_container[ZONE_0]->GetTotal_UnstTime())
          StopCalc = true;

        if ((iExtIter+1 == config_container[ZONE_0]->GetnExtIter()) ||
            ((iExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq() == 0) && (iExtIter != 0) &&
             !(config_container[ZONE_0]->GetUnsteady_Simulation() == TIME_STEPPING)) ||
            (StopCalc) ||
            ((config_container[ZONE_0]->GetUnsteady_Simulation() == TIME_STEPPING) &&
             ((iExtIter == 0) || (iExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0)))) {

              /*--- Read in the restart file for this time step ---*/
              for (iZone = 0; iZone < nZone; iZone++) {

                /*--- Set the current iteration number in the config class. ---*/
                config_container[iZone]->SetExtIter(iExtIter);

                /*--- Either instantiate the solution class or load a restart file. ---*/
                if (SolutionInstantiated[iZone] == false &&
                    (iExtIter == 0 ||
                     (config_container[ZONE_0]->GetRestart() && ((long)iExtIter == config_container[ZONE_0]->GetUnst_RestartIter() ||
                                                                                  iExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0 ||
                                                                                  iExtIter+1 == config_container[ZONE_0]->GetnExtIter())))) {

                  solver_container[iZone][INST_0] = new CBaselineSolver_FEM(geometry_container[iZone][INST_0], config_container[iZone]);
                  SolutionInstantiated[iZone] = true;
                }
                solver_container[iZone][INST_0]->LoadRestart(&geometry_container[iZone][INST_0], &solver_container[iZone],
                                                             config_container[iZone], (int)iExtIter, true);
              }

              if (rank == MASTER_NODE)
                cout << "Writing the volume solution for time step " << iExtIter << "." << endl;
              output->SetBaselineResult_Files_FEM(solver_container, geometry_container, config_container, iExtIter, nZone);
            }
        
        iExtIter++;
        if (StopCalc) break;
      }
      
    } else {

    /*--- Steady simulation: merge the single solution file. ---*/

    for (iZone = 0; iZone < nZone; iZone++) {
      /*--- Definition of the solution class ---*/

      solver_container[iZone][INST_0] = new CBaselineSolver_FEM(geometry_container[iZone][INST_0], config_container[iZone]);
      solver_container[iZone][INST_0]->LoadRestart(&geometry_container[iZone][INST_0], &solver_container[iZone], config_container[iZone], SU2_TYPE::Int(MESH_0), true);
    }

    output->SetBaselineResult_Files_FEM(solver_container, geometry_container, config_container, 0, nZone);
    }

  }
  else {

    if (config_container[ZONE_0]->GetWrt_Unsteady()) {

      /*--- Unsteady simulation: merge all unsteady time steps. First,
       find the frequency and total number of files to write. ---*/

      su2double Physical_dt, Physical_t;
      unsigned long iExtIter = 0;
      bool StopCalc = false;
      bool *SolutionInstantiated = new bool[nZone];

      for (iZone = 0; iZone < nZone; iZone++)
        SolutionInstantiated[iZone] = false;

      /*--- Check for an unsteady restart. Update ExtIter if necessary. ---*/
      if (config_container[ZONE_0]->GetWrt_Unsteady() && config_container[ZONE_0]->GetRestart())
        iExtIter = config_container[ZONE_0]->GetUnst_RestartIter();

      while (iExtIter < config_container[ZONE_0]->GetnExtIter()) {

        /*--- Check several conditions in order to merge the correct time step files. ---*/
        Physical_dt = config_container[ZONE_0]->GetDelta_UnstTime();
        Physical_t  = (iExtIter+1)*Physical_dt;
        if (Physical_t >=  config_container[ZONE_0]->GetTotal_UnstTime())
          StopCalc = true;

        if ((iExtIter+1 == config_container[ZONE_0]->GetnExtIter()) ||
            ((iExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq() == 0) && (iExtIter != 0) &&
             !((config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
               (config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_2ND))) ||
            (StopCalc) ||
            (((config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
              (config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_2ND)) &&
             ((iExtIter == 0) || (iExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0)))) {



              /*--- Read in the restart file for this time step ---*/
              for (iZone = 0; iZone < nZone; iZone++) {

                /*--- Set the current iteration number in the config class. ---*/
                config_container[iZone]->SetExtIter(iExtIter);

                /*--- Either instantiate the solution class or load a restart file. ---*/
                if (SolutionInstantiated[iZone] == false &&
                    (iExtIter == 0 || (config_container[ZONE_0]->GetRestart() && ((long)iExtIter == config_container[ZONE_0]->GetUnst_RestartIter() ||
                                                                                  iExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0 ||
                                                                                  iExtIter+1 == config_container[ZONE_0]->GetnExtIter())))) {
                  solver_container[iZone][INST_0] = new CBaselineSolver(geometry_container[iZone][INST_0], config_container[iZone]);
                  SolutionInstantiated[iZone] = true;
                }
                  config_container[iZone]->SetiInst(INST_0);
                  solver_container[iZone][INST_0]->LoadRestart(geometry_container[iZone], &solver_container[iZone], config_container[iZone], SU2_TYPE::Int(MESH_0), true);
              }

              if (rank == MASTER_NODE)
                cout << "Writing the volume solution for time step " << iExtIter << "." << endl;
              output->SetBaselineResult_Files(solver_container, geometry_container, config_container, iExtIter, nZone);
            }

        iExtIter++;
        if (StopCalc) break;
      }

    }

    else if (config_container[ZONE_0]->GetUnsteady_Simulation() == HARMONIC_BALANCE) {

      /*--- Read in the restart file for this time step ---*/
      for (iZone = 0; iZone < nZone; iZone++) {

        for (iInst = 0; iInst < nInst[iZone]; iInst++){

          config_container[iZone]->SetiInst(iInst);

          /*--- Either instantiate the solution class or load a restart file. ---*/
          solver_container[iZone][iInst] = new CBaselineSolver(geometry_container[iZone][iInst], config_container[iZone]);
          solver_container[iZone][iInst]->LoadRestart(geometry_container[iZone], &solver_container[iZone], config_container[iZone], SU2_TYPE::Int(MESH_0), true);

          /*--- Print progress in solution writing to the screen. ---*/
          if (rank == MASTER_NODE) {
            cout << "Storing the volume solution for time instance " << iInst << "." << endl;
          }

        }

      }

      output->SetBaselineResult_Files(solver_container, geometry_container, config_container, iZone, nZone);
    }

    else if (config_container[ZONE_0]->GetWrt_Dynamic()){

      /*--- Dynamic simulation: merge all unsteady time steps. First,
       find the frequency and total number of files to write. ---*/

      su2double Physical_dt, Physical_t;
      unsigned long iExtIter = 0;
      bool StopCalc = false;
      bool SolutionInstantiated = false;



      /*--- Check for an dynamic restart (structural analysis). Update ExtIter if necessary. ---*/
      if (config_container[ZONE_0]->GetKind_Solver() == FEM_ELASTICITY &&
          config_container[ZONE_0]->GetWrt_Dynamic() && config_container[ZONE_0]->GetRestart())
        iExtIter = config_container[ZONE_0]->GetDyn_RestartIter();

      while (iExtIter < config_container[ZONE_0]->GetnExtIter()) {

        /*--- Check several conditions in order to merge the correct time step files. ---*/
        /*--- If the solver is structural, the total and delta_t are obtained from different functions. ---*/

        Physical_dt = config_container[ZONE_0]->GetDelta_DynTime();
        Physical_t  = (iExtIter+1)*Physical_dt;
        if (Physical_t >=  config_container[ZONE_0]->GetTotal_DynTime())
          StopCalc = true;

        if ((iExtIter+1 == config_container[ZONE_0]->GetnExtIter()) ||
            (StopCalc) ||
            ((config_container[ZONE_0]->GetDynamic_Analysis() == DYNAMIC) &&
             ((iExtIter == 0) || (iExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0)))) {

              /*--- Set the current iteration number in the config class. ---*/
              config_container[ZONE_0]->SetExtIter(iExtIter);

              /*--- Read in the restart file for this time step ---*/
              for (iZone = 0; iZone < nZone; iZone++) {

                /*--- Either instantiate the solution class or load a restart file. ---*/
                if (SolutionInstantiated == false &&
                    (iExtIter == 0 || ((config_container[ZONE_0]->GetRestart() && (SU2_TYPE::Int(iExtIter) == config_container[ZONE_0]->GetDyn_RestartIter())) ||
                                       iExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0 ||
                                       iExtIter+1 == config_container[ZONE_0]->GetnExtIter()))) {
                  solver_container[iZone][INST_0] = new CBaselineSolver(geometry_container[iZone][INST_0], config_container[iZone]);
                  SolutionInstantiated = true;
                }
                config_container[iZone]->SetiInst(INST_0);
                solver_container[iZone][INST_0]->LoadRestart(geometry_container[iZone], &solver_container[iZone], config_container[iZone], SU2_TYPE::Int(MESH_0), true);
              }

              if (rank == MASTER_NODE)
                cout << "Writing the volume solution for time step " << iExtIter << "." << endl;
              output->SetBaselineResult_Files(solver_container, geometry_container, config_container, iExtIter, nZone);
            }
        
        iExtIter++;
        if (StopCalc) break;
      }
      
		  }
    
    else {

      /*--- Steady simulation: merge the single solution file. ---*/

      for (iZone = 0; iZone < nZone; iZone++) {
        config_container[iZone]->SetiInst(INST_0);
        /*--- Definition of the solution class ---*/
        solver_container[iZone][INST_0] = new CBaselineSolver(geometry_container[iZone][INST_0], config_container[iZone]);
        solver_container[iZone][INST_0]->LoadRestart(geometry_container[iZone], &solver_container[iZone], config_container[iZone], SU2_TYPE::Int(MESH_0), true);
      }

      output->SetBaselineResult_Files(solver_container, geometry_container, config_container, 0, nZone);

		  }
    
  }
  
  delete config;
  config = NULL;

  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Solver Postprocessing -------------------------" << endl;
  
  if (geometry_container != NULL) {
    for (iZone = 0; iZone < nZone; iZone++) {
      for (iInst = 0; iInst < nInst[iZone]; iInst++){
        if (geometry_container[iZone][iInst] != NULL) {
          delete geometry_container[iZone][iInst];
        }
      }
      if (geometry_container[iZone] != NULL)
        delete geometry_container[iZone];
    }
    delete [] geometry_container;
  }
  if (rank == MASTER_NODE) cout << "Deleted CGeometry container." << endl;
  
  if (solver_container != NULL) {
    for (iZone = 0; iZone < nZone; iZone++) {
      for (iInst = 0; iInst < nInst[iZone]; iInst++){
        if (solver_container[iZone][iInst] != NULL) {
          delete solver_container[iZone][iInst];
        }
      }
      if (solver_container[iZone] != NULL)
        delete solver_container[iZone];
    }
    delete [] solver_container;
  }
  if (rank == MASTER_NODE) cout << "Deleted CSolver class." << endl;
  
  if (config_container != NULL) {
    for (iZone = 0; iZone < nZone; iZone++) {
      if (config_container[iZone] != NULL) {
        delete config_container[iZone];
      }
    }
    delete [] config_container;
  }
  if (rank == MASTER_NODE) cout << "Deleted CConfig container." << endl;
  
  if (output != NULL) delete output;
  if (rank == MASTER_NODE) cout << "Deleted COutput class." << endl;
  
  /*--- Synchronization point after a single solver iteration. Compute the
   wall clock time required. ---*/
  
#ifdef HAVE_MPI
  StopTime = MPI_Wtime();
#else
  StopTime = su2double(clock())/su2double(CLOCKS_PER_SEC);
#endif
  
  /*--- Compute/print the total time for performance benchmarking. ---*/
  
  UsedTime = StopTime-StartTime;
  if (rank == MASTER_NODE) {
    cout << "\nCompleted in " << fixed << UsedTime << " seconds on "<< size;
    if (size == 1) cout << " core." << endl; else cout << " cores." << endl;
  }
  
  /*--- Exit the solver cleanly ---*/
  
  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Exit Success (SU2_SOL) ------------------------" << endl << endl;
  
  /*--- Finalize MPI parallelization ---*/
  
#ifdef HAVE_MPI
  SU2_MPI::Finalize();
#endif
  
  return EXIT_SUCCESS;
}
示例#12
0
文件: SU2_SOL.cpp 项目: drewkett/SU2
int main(int argc, char *argv[]) {

  unsigned short iZone, nZone = SINGLE_ZONE;
  su2double StartTime = 0.0, StopTime = 0.0, UsedTime = 0.0;
  ofstream ConvHist_file;
  char config_file_name[MAX_STRING_SIZE];
  int rank = MASTER_NODE;
  int size = SINGLE_NODE;
  bool periodic = false;

  /*--- MPI initialization ---*/

#ifdef HAVE_MPI
  SU2_MPI::Init(&argc,&argv);
  SU2_MPI::Comm MPICommunicator(MPI_COMM_WORLD);
#else
  SU2_Comm MPICommunicator(0);
#endif

  rank = SU2_MPI::GetRank();
  size = SU2_MPI::GetSize();

  /*--- Pointer to different structures that will be used throughout the entire code ---*/

  COutput *output                = NULL;
  CGeometry **geometry_container = NULL;
  CSolver **solver_container     = NULL;
  CConfig **config_container     = NULL;

  /*--- Load in the number of zones and spatial dimensions in the mesh file (if no config
   file is specified, default.cfg is used) ---*/

  if (argc == 2 || argc == 3) { strcpy(config_file_name,argv[1]); }
  else { strcpy(config_file_name, "default.cfg"); }

  CConfig *config = NULL;
  config = new CConfig(config_file_name, SU2_SOL);

  nZone    = CConfig::GetnZone(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);
  periodic = CConfig::GetPeriodic(config->GetMesh_FileName(), config->GetMesh_FileFormat(), config);

  /*--- Definition of the containers per zones ---*/

  solver_container = new CSolver*[nZone];
  config_container = new CConfig*[nZone];
  geometry_container = new CGeometry*[nZone];

  for (iZone = 0; iZone < nZone; iZone++) {
    solver_container[iZone]       = NULL;
    config_container[iZone]       = NULL;
    geometry_container[iZone]     = NULL;
  }

  /*--- Loop over all zones to initialize the various classes. In most
   cases, nZone is equal to one. This represents the solution of a partial
   differential equation on a single block, unstructured mesh. ---*/

  for (iZone = 0; iZone < nZone; iZone++) {

    /*--- Definition of the configuration option class for all zones. In this
     constructor, the input configuration file is parsed and all options are
     read and stored. ---*/

    config_container[iZone] = new CConfig(config_file_name, SU2_SOL, iZone, nZone, 0, VERB_HIGH);
    config_container[iZone]->SetMPICommunicator(MPICommunicator);

    /*--- Definition of the geometry class to store the primal grid in the partitioning process. ---*/

    CGeometry *geometry_aux = NULL;

    /*--- All ranks process the grid and call ParMETIS for partitioning ---*/

    geometry_aux = new CPhysicalGeometry(config_container[iZone], iZone, nZone);

    /*--- Color the initial grid and set the send-receive domains (ParMETIS) ---*/

    geometry_aux->SetColorGrid_Parallel(config_container[iZone]);

    /*--- Until we finish the new periodic BC implementation, use the old
     partitioning routines for cases with periodic BCs. The old routines 
     will be entirely removed eventually in favor of the new methods. ---*/

    if (periodic) {
      geometry_container[iZone] = new CPhysicalGeometry(geometry_aux, config_container[iZone]);
    } else {
      geometry_container[iZone] = new CPhysicalGeometry(geometry_aux, config_container[iZone], periodic);
    }

    /*--- Deallocate the memory of geometry_aux ---*/

    delete geometry_aux;

    /*--- Add the Send/Receive boundaries ---*/

    geometry_container[iZone]->SetSendReceive(config_container[iZone]);

    /*--- Add the Send/Receive boundaries ---*/

    geometry_container[iZone]->SetBoundaries(config_container[iZone]);

    /*--- Create the vertex structure (required for MPI) ---*/

    if (rank == MASTER_NODE) cout << "Identify vertices." <<endl;
    geometry_container[iZone]->SetVertex(config_container[iZone]);

    /*--- Store the global to local mapping after preprocessing. ---*/

    if (rank == MASTER_NODE) cout << "Storing a mapping from global to local point index." << endl;
    geometry_container[iZone]->SetGlobal_to_Local_Point();

  }

  /*--- Determine whether the simulation is a FSI simulation ---*/

  bool fsi = config_container[ZONE_0]->GetFSI_Simulation();

  /*--- Set up a timer for performance benchmarking (preprocessing time is included) ---*/

#ifdef HAVE_MPI
  StartTime = MPI_Wtime();
#else
  StartTime = su2double(clock())/su2double(CLOCKS_PER_SEC);
#endif

  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Solution Postprocessing -----------------------" << endl;
  
	/*--- Definition of the output class (one for all the zones) ---*/
	output = new COutput(config_container[ZONE_0]);
  
  /*---  Check whether this is an FSI, fluid unsteady, harmonic balance or structural dynamic simulation and call the
   solution merging routines accordingly.---*/

  if (fsi){

    if (nZone < 2){
      SU2_MPI::Error("For multizone computations, please add the number of zones as a second argument for SU2_SOL.", CURRENT_FUNCTION);
    }

    su2double Physical_dt, Physical_t;
    unsigned long iExtIter = 0, iExtIterFlow = 0, iExtIterFEM = 0;
    bool StopCalc = false;
    bool SolutionInstantiatedFlow = false, SolutionInstantiatedFEM = false;

    /*--- Check for an unsteady restart. Update ExtIter if necessary. ---*/
    if (config_container[ZONE_0]->GetRestart()){
      iExtIterFlow = config_container[ZONE_0]->GetUnst_RestartIter();
      iExtIterFEM = config_container[ZONE_1]->GetDyn_RestartIter();
      if (iExtIterFlow != iExtIterFEM) {
        SU2_MPI::Error("For multizone computations, please add the number of zones as a second argument for SU2_SOL.", CURRENT_FUNCTION);
      }
      else {
        iExtIter = iExtIterFlow;
      }
    }


    while (iExtIter < config_container[ZONE_0]->GetnExtIter()) {

      /*--- Check several conditions in order to merge the correct time step files. ---*/

      Physical_dt = config_container[ZONE_0]->GetDelta_UnstTime();
      Physical_t  = (iExtIter+1)*Physical_dt;
      if (Physical_t >=  config_container[ZONE_0]->GetTotal_UnstTime())
        StopCalc = true;

      if (
          ((iExtIter+1 == config_container[ZONE_0]->GetnExtIter()) ||
           ((iExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq() == 0) && (iExtIter != 0) &&
            !((config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
              (config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_2ND))) ||
           (StopCalc) ||
           (((config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
             (config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_2ND)) &&
            ((iExtIter == 0) || (iExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0))))

          &&

          ((iExtIter+1 == config_container[ZONE_1]->GetnExtIter()) ||
           (StopCalc) ||
           ((config_container[ZONE_1]->GetDynamic_Analysis() == DYNAMIC) &&
            ((iExtIter == 0) || (iExtIter % config_container[ZONE_1]->GetWrt_Sol_Freq_DualTime() == 0))))

          ){

        /*--- Set the current iteration number in the config class. ---*/
        config_container[ZONE_0]->SetExtIter(iExtIter);
        config_container[ZONE_1]->SetExtIter(iExtIter);

        /*--- Read in the restart file for this time step ---*/

        /*--- For the fluid zone (ZONE_0) ---*/
        /*--- Either instantiate the solution class or load a restart file. ---*/
        if (SolutionInstantiatedFlow == false &&
            (iExtIter == 0 || ((config_container[ZONE_0]->GetRestart() && (SU2_TYPE::Int(iExtIter) == config_container[ZONE_0]->GetUnst_RestartIter())) ||
                               iExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0 ||
                               iExtIter+1 == config_container[ZONE_0]->GetnExtIter()))) {
          solver_container[ZONE_0] = new CBaselineSolver(geometry_container[ZONE_0], config_container[ZONE_0]);
          SolutionInstantiatedFlow = true;
        }
          solver_container[ZONE_0]->LoadRestart_FSI(geometry_container[ZONE_0], &solver_container, config_container[ZONE_0], SU2_TYPE::Int(MESH_0));


        /*--- For the structural zone (ZONE_1) ---*/
        /*--- Either instantiate the solution class or load a restart file. ---*/
        /*--- Either instantiate the solution class or load a restart file. ---*/
        if (SolutionInstantiatedFEM == false &&
            (iExtIter == 0 || ((config_container[ZONE_1]->GetRestart() && (SU2_TYPE::Int(iExtIter) == config_container[ZONE_1]->GetDyn_RestartIter())) ||
                               iExtIter % config_container[ZONE_1]->GetWrt_Sol_Freq_DualTime() == 0 ||
                               iExtIter+1 == config_container[ZONE_1]->GetnExtIter()))) {
          solver_container[ZONE_1] = new CBaselineSolver(geometry_container[ZONE_1], config_container[ZONE_1]);
          SolutionInstantiatedFEM = true;
        }
          solver_container[ZONE_1]->LoadRestart_FSI(geometry_container[ZONE_1], &solver_container, config_container[ZONE_1], SU2_TYPE::Int(MESH_0));

        if (rank == MASTER_NODE) cout << "Writing the volume solution for time step " << iExtIter << "." << endl;
        output->SetBaselineResult_Files(solver_container, geometry_container, config_container, iExtIter, nZone);
      }

      iExtIter++;
      if (StopCalc) break;
    }

  }
  else {

    if (config_container[ZONE_0]->GetWrt_Unsteady()) {

      /*--- Unsteady simulation: merge all unsteady time steps. First,
       find the frequency and total number of files to write. ---*/

      su2double Physical_dt, Physical_t;
      unsigned long iExtIter = 0;
      bool StopCalc = false;
      bool *SolutionInstantiated = new bool[nZone];

      for (iZone = 0; iZone < nZone; iZone++)
        SolutionInstantiated[iZone] = false;

      /*--- Check for an unsteady restart. Update ExtIter if necessary. ---*/
      if (config_container[ZONE_0]->GetWrt_Unsteady() && config_container[ZONE_0]->GetRestart())
        iExtIter = config_container[ZONE_0]->GetUnst_RestartIter();

      while (iExtIter < config_container[ZONE_0]->GetnExtIter()) {

        /*--- Check several conditions in order to merge the correct time step files. ---*/
        Physical_dt = config_container[ZONE_0]->GetDelta_UnstTime();
        Physical_t  = (iExtIter+1)*Physical_dt;
        if (Physical_t >=  config_container[ZONE_0]->GetTotal_UnstTime())
          StopCalc = true;

        if ((iExtIter+1 == config_container[ZONE_0]->GetnExtIter()) ||
            ((iExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq() == 0) && (iExtIter != 0) &&
             !((config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
               (config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_2ND))) ||
            (StopCalc) ||
            (((config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_1ST) ||
              (config_container[ZONE_0]->GetUnsteady_Simulation() == DT_STEPPING_2ND)) &&
             ((iExtIter == 0) || (iExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0)))) {



              /*--- Read in the restart file for this time step ---*/
              for (iZone = 0; iZone < nZone; iZone++) {

                /*--- Set the current iteration number in the config class. ---*/
                config_container[iZone]->SetExtIter(iExtIter);

                /*--- Either instantiate the solution class or load a restart file. ---*/
                if (SolutionInstantiated[iZone] == false &&
                    (iExtIter == 0 || (config_container[ZONE_0]->GetRestart() && ((long)iExtIter == config_container[ZONE_0]->GetUnst_RestartIter() ||
                                                                                  iExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0 ||
                                                                                  iExtIter+1 == config_container[ZONE_0]->GetnExtIter())))) {
                  solver_container[iZone] = new CBaselineSolver(geometry_container[iZone], config_container[iZone]);
                  SolutionInstantiated[iZone] = true;
                }
                  solver_container[iZone]->LoadRestart(geometry_container, &solver_container, config_container[iZone], SU2_TYPE::Int(MESH_0), true);
              }

              if (rank == MASTER_NODE)
                cout << "Writing the volume solution for time step " << iExtIter << "." << endl;
              output->SetBaselineResult_Files(solver_container, geometry_container, config_container, iExtIter, nZone);
            }

        iExtIter++;
        if (StopCalc) break;
      }

    }

    else if (config_container[ZONE_0]->GetUnsteady_Simulation() == HARMONIC_BALANCE) {

      /*--- Read in the restart file for this time step ---*/
      for (iZone = 0; iZone < nZone; iZone++) {

        /*--- Either instantiate the solution class or load a restart file. ---*/
        solver_container[iZone] = new CBaselineSolver(geometry_container[iZone], config_container[iZone]);
        solver_container[iZone]->LoadRestart(geometry_container, &solver_container, config_container[iZone], SU2_TYPE::Int(MESH_0), true);

        /*--- Print progress in solution writing to the screen. ---*/
        if (rank == MASTER_NODE) {
          cout << "Storing the volume solution for time instance " << iZone << "." << endl;
        }

      }

      output->SetBaselineResult_Files(solver_container, geometry_container, config_container, iZone, nZone);
    }

    else if (config_container[ZONE_0]->GetWrt_Dynamic()){

      /*--- Dynamic simulation: merge all unsteady time steps. First,
       find the frequency and total number of files to write. ---*/

      su2double Physical_dt, Physical_t;
      unsigned long iExtIter = 0;
      bool StopCalc = false;
      bool SolutionInstantiated = false;



      /*--- Check for an dynamic restart (structural analysis). Update ExtIter if necessary. ---*/
      if (config_container[ZONE_0]->GetKind_Solver() == FEM_ELASTICITY &&
          config_container[ZONE_0]->GetWrt_Dynamic() && config_container[ZONE_0]->GetRestart())
        iExtIter = config_container[ZONE_0]->GetDyn_RestartIter();

      while (iExtIter < config_container[ZONE_0]->GetnExtIter()) {

        /*--- Check several conditions in order to merge the correct time step files. ---*/
        /*--- If the solver is structural, the total and delta_t are obtained from different functions. ---*/

        Physical_dt = config_container[ZONE_0]->GetDelta_DynTime();
        Physical_t  = (iExtIter+1)*Physical_dt;
        if (Physical_t >=  config_container[ZONE_0]->GetTotal_DynTime())
          StopCalc = true;

        if ((iExtIter+1 == config_container[ZONE_0]->GetnExtIter()) ||
            (StopCalc) ||
            ((config_container[ZONE_0]->GetDynamic_Analysis() == DYNAMIC) &&
             ((iExtIter == 0) || (iExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0)))) {

              /*--- Set the current iteration number in the config class. ---*/
              config_container[ZONE_0]->SetExtIter(iExtIter);

              /*--- Read in the restart file for this time step ---*/
              for (iZone = 0; iZone < nZone; iZone++) {

                /*--- Either instantiate the solution class or load a restart file. ---*/
                if (SolutionInstantiated == false &&
                    (iExtIter == 0 || ((config_container[ZONE_0]->GetRestart() && (SU2_TYPE::Int(iExtIter) == config_container[ZONE_0]->GetDyn_RestartIter())) ||
                                       iExtIter % config_container[ZONE_0]->GetWrt_Sol_Freq_DualTime() == 0 ||
                                       iExtIter+1 == config_container[ZONE_0]->GetnExtIter()))) {
                  solver_container[iZone] = new CBaselineSolver(geometry_container[iZone], config_container[iZone]);
                  SolutionInstantiated = true;
                }
                  solver_container[iZone]->LoadRestart(geometry_container, &solver_container, config_container[iZone], SU2_TYPE::Int(MESH_0), true);
              }

              if (rank == MASTER_NODE)
                cout << "Writing the volume solution for time step " << iExtIter << "." << endl;
              output->SetBaselineResult_Files(solver_container, geometry_container, config_container, iExtIter, nZone);
            }
        
        iExtIter++;
        if (StopCalc) break;
      }
      
		  }
    
    else {

      /*--- Steady simulation: merge the single solution file. ---*/

      for (iZone = 0; iZone < nZone; iZone++) {
        /*--- Definition of the solution class ---*/
        solver_container[iZone] = new CBaselineSolver(geometry_container[iZone], config_container[iZone]);
        solver_container[iZone]->LoadRestart(geometry_container, &solver_container, config_container[iZone], SU2_TYPE::Int(MESH_0), true);
      }

      output->SetBaselineResult_Files(solver_container, geometry_container, config_container, 0, nZone);

		  }
    
  }
  
  delete config;
  config = NULL;

  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Solver Postprocessing -------------------------" << endl;
  
  if (geometry_container != NULL) {
    for (iZone = 0; iZone < nZone; iZone++) {
      if (geometry_container[iZone] != NULL) {
        delete geometry_container[iZone];
      }
    }
    delete [] geometry_container;
  }
  if (rank == MASTER_NODE) cout << "Deleted CGeometry container." << endl;
  
  if (solver_container != NULL) {
    for (iZone = 0; iZone < nZone; iZone++) {
      if (solver_container[iZone] != NULL) {
        delete solver_container[iZone];
      }
    }
    delete [] solver_container;
  }
  if (rank == MASTER_NODE) cout << "Deleted CSolver class." << endl;
  
  if (config_container != NULL) {
    for (iZone = 0; iZone < nZone; iZone++) {
      if (config_container[iZone] != NULL) {
        delete config_container[iZone];
      }
    }
    delete [] config_container;
  }
  if (rank == MASTER_NODE) cout << "Deleted CConfig container." << endl;
  
  if (output != NULL) delete output;
  if (rank == MASTER_NODE) cout << "Deleted COutput class." << endl;
  
  /*--- Synchronization point after a single solver iteration. Compute the
   wall clock time required. ---*/
  
#ifdef HAVE_MPI
  StopTime = MPI_Wtime();
#else
  StopTime = su2double(clock())/su2double(CLOCKS_PER_SEC);
#endif
  
  /*--- Compute/print the total time for performance benchmarking. ---*/
  
  UsedTime = StopTime-StartTime;
  if (rank == MASTER_NODE) {
    cout << "\nCompleted in " << fixed << UsedTime << " seconds on "<< size;
    if (size == 1) cout << " core." << endl; else cout << " cores." << endl;
  }
  
  /*--- Exit the solver cleanly ---*/
  
  if (rank == MASTER_NODE)
    cout << endl <<"------------------------- Exit Success (SU2_SOL) ------------------------" << endl << endl;
  
  /*--- Finalize MPI parallelization ---*/
  
#ifdef HAVE_MPI
  SU2_MPI::Finalize();
#endif
  
  return EXIT_SUCCESS;
}