Esempio n. 1
0
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;
	
}