Ejemplo n.º 1
0
void Get_dXdB(std::string path, Real* dxdb, Mesh<Real>* m, Int beta)
{
  std::ifstream fin;
  std::stringstream ss;

  Int i, b;

  PObj<Real>* p = m->p;
  Int rank = p->GetRank();
  Int np = p->GetNp();

  Int rankRead, npRead, nnodeRead;
  Int nnode = m->GetNumNodes();

  ss.clear();
  ss << rank;

  //read points to move from file and dxdb for them
  std::string Filename = path + "-DxDb." + (ss.str()) + ".dat";
  fin.open(Filename.c_str());
  if(!fin.is_open()){
    std::cerr << "WARNING: opening file failed --> " << Filename << std::endl;
    return;
  }
  
  //read in header to check for mismatched process numbers
  fin >> npRead;
  fin >> rankRead;
  fin >> nnodeRead;

  //check that the state is sane
  if(npRead != np){
    std::cerr << "WARNING: Get_dXdB() Mesh movement sensitivities were run with a " 
	      << "nonmatching number of processes, files not synced!" << std::endl;
  }
  if(rankRead != rank){
    std::cerr << "WARNING: Get_dXdB() Mesh movement sensitivities opened with wrong rank!"
       << std::endl;
  }
  if(nnodeRead != nnode){
    std::cerr << "WARNING: Get_dXdB() Mesh movement sensitivities opened with wrong number "
	      << "of nodes!" << std::endl;
  }


  //read in globalnodes for each beta up until we have read
  //the beta we are looking for
  for(b = 0; b <= beta; b++){
    for(i = 0; i < nnode*3; i++){
      fin >> dxdb[i];
    }
  }

  fin.close();

  return;
}
Ejemplo n.º 2
0
void Compute_dQdBeta_CTSE(Real* dQdB, SolutionSpace<Real>& space, Int beta)
{
  RCmplx perturb(0.0, 1.0e-11);

  Mesh<Real>* rm = space.m;

  SolutionSpace<RCmplx> cspace(space);
  Mesh<RCmplx>* cm = cspace.m;
  PObj<RCmplx>* cp = cspace.p;
  EqnSet<RCmplx>* ceqnset = cspace.eqnset;

  std::vector<SolutionSpaceBase<RCmplx>*> cSolSpaces;
  cSolSpaces.push_back(&cspace);

  SolutionOrdering<RCmplx> operations;
  std::string name = cspace.name;
  operations.Insert("Iterate " + name);
  operations.Finalize(cSolSpaces);

  Int cnnode = cm->GetNumNodes();

  Real* dxdb = new Real[cnnode*3];

  Get_dXdB(space.param->path+space.param->spacename, dxdb, rm, beta);

  //perturb complex part by dxdb*perturb
  for(Int i = 0; i < cnnode; i++){
    for(Int j = 0; j < 3; j++){
      cm->xyz[i*3 + j] += dxdb[i*3 + j]*perturb;
    }
  }
  //update xyz coords
  cp->UpdateXYZ(cm->xyz);
  //calculate metrics with new grid positions
  cm->CalcMetrics();
  
  //create a temporary operations vector with just a single space iterator on it
  //run solver
  Solve(cSolSpaces, operations);

  for(Int i = 0; i < cnnode; i++){
    for(Int j = 0; j < ceqnset->neqn; j++){
      dQdB[i*ceqnset->neqn + j] = 
	imag(cspace.q[i*(ceqnset->neqn+ceqnset->nauxvars) + j]) / imag(perturb);
    }
  }
  
  delete [] dxdb;

  return;
}
Ejemplo n.º 3
0
Real Compute_dObjdX_dXdBeta(SolutionSpace<Real>& space, Int beta)
{
  RCmplx perturb (0.0, 1.0e-11);

  Real dObjdBeta;
  RCmplx Obj;

  Mesh<Real>* m = space.m;
  EqnSet<Real>* eqnset = space.eqnset;
  Param<Real>* param = space.param;
  BoundaryConditions<Real>* bc = space.bc;

  SolutionSpace<RCmplx> cspace(space);
  Mesh<RCmplx>* cm = cspace.m;
  PObj<RCmplx>* cp = cspace.p;
  EqnSet<RCmplx>* ceqnset = cspace.eqnset;

  Int nnode = m->GetNumNodes();
  Int cnnode = cm->GetNumNodes();

  Real* dxdb = new Real[nnode*3];

  Get_dXdB(space.param->path+space.param->spacename, dxdb, m, beta);

  //perturb complex part by dxdb*perturb
  for(Int i = 0; i < cnnode; i++){
    for(Int j = 0; j < 3; j++){
      cm->xyz[i*3 + j] += dxdb[i*3 + j]*perturb;
    }
  }
  //update xyz coords
  cp->UpdateXYZ(cm->xyz);
  //calculate metrics with new grid positions
  cm->CalcMetrics();

  ComputeSurfaceAreas(&cspace, 0);
  Obj = Compute_Obj_Function(cspace);

  dObjdBeta = imag(Obj) / imag(perturb);
  
  delete [] dxdb;

  return dObjdBeta;
}
Ejemplo n.º 4
0
Real Compute_dObjdQ_dQdBeta(Real* dQdB, SolutionSpace<Real>& space)
{
  RCmplx perturb (0.0, 1.0e-11);
  RCmplx Obj;

  EqnSet<Real>* eqnset = space.eqnset;
  Mesh<Real>* m = space.m;
  Param<Real>* param = space.param;
  BoundaryConditions<Real>* bc = space.bc;

  SolutionSpace<RCmplx> cspace(space);
  Mesh<RCmplx>* cm = cspace.m;
  PObj<RCmplx>* cp = cspace.p;
  EqnSet<RCmplx>* ceqnset = cspace.eqnset;

  Int cnnode = cm->GetNumNodes();

  Real dObjdBeta;
  Int i, j;
  Int neqn = eqnset->neqn;
  Int nauxvars = eqnset->nauxvars;

  //replace all Q values in mesh by dQdB*perturb and compute cost function
  for(i = 0; i < cnnode; i++){
    for(j = 0; j < neqn; j++){
      cspace.q[i*(neqn+nauxvars) + j] += dQdB[i*neqn + j]*perturb;
    }
    ceqnset->ComputeAuxiliaryVariables(&cspace.q[i*(neqn+nauxvars)]);
  }
  cp->UpdateGeneralVectors(cspace.q, neqn+nauxvars);
  UpdateBCs(&cspace);
  cp->UpdateGeneralVectors(cspace.q, neqn+nauxvars);

  ComputeSurfaceAreas(&cspace, 0);
  Obj = Compute_Obj_Function(cspace);
  
  dObjdBeta = imag(Obj)/imag(perturb);

  return dObjdBeta;
}
Ejemplo n.º 5
0
void Compute_dXdB(SolutionSpace<Real>& space)
{
  Mesh<Real>* m = space.m;
  BoundaryConditions<Real>* bc = space.bc;

  RCmplx h (0.0, 1.0e-11);

  Int i, j;

  Int nnode = m->GetNumNodes();
  Int gnode = m->GetNumParallelNodes();
  Int nbnode = m->GetNumBoundaryNodes();

  Int beta;

  //this contains dxdb dydx and dzdb
  Real* dxdb = new Real[nnode*3];
  RCmplx* dxdbSurfC = new RCmplx[nnode*3];

  Mesh<RCmplx> cm(*m);
  PObj<RCmplx> cp;
  cm.SetParallelPointer(&cp);
  cp.BuildCommMaps(&cm);
  //check for parallel comm sanity
  cp.CheckSanityCoords(cm.xyz);

  Int cnnode = cm.GetNumNodes();
  
  std::cout << "\n\nCOMPUTING dX/dB\n" << std::endl;

  std::string fullpath = space.param->path + space.param->spacename;
  Int ndv = GetNdvDesignFile(fullpath);
  std::cout << "\n\nFOUND " << ndv << " design variables\n" << std::endl;

  std::ofstream fout;
  std::stringstream ss;
  ss.clear();
  ss.str("");
  ss << cp.GetRank();
  std::string dxdbFilename = space.param->path+space.param->spacename + "-DxDb." + (ss.str()) + ".dat";
  fout.open(dxdbFilename.c_str());
  fout << std::setprecision(16);

  Int np = m->p->GetNp();
  Int rank = m->p->GetRank();
  fout << np << " " << rank << " " << cnnode << std::endl;

  for(beta = 0; beta < ndv; beta++){
    std::cout << "PERTURBING BETA: " << beta << std::endl;
    Compute_dXdB_Surface(space.param->path + space.param->spacename, m, bc, dxdb, beta);
    //perturb points by h * dxdb_surface
    for(i = 0; i < nnode; i++){
      for(j = 0; j < 3; j++){
	dxdbSurfC[i*3 + j] = dxdb[i*3 + j]*h;
      }
    }      
    Int smoothingPasses = 1000;
    MoveMeshLinearElastic(&cm, bc, dxdbSurfC, smoothingPasses);
  
    //compute dxdb
    for(i = 0; i < cnnode*3; i++){
      dxdb[i] = imag(cm.xyz[i])/imag(h);
    }
    //write dxdb dxdb dzdb to file
    for(i = 0; i < cnnode; i++){
      for(j = 0; j < 3; j++){
	fout << dxdb[i*3 + j] << " " ;
      }
      fout << std::endl;
    }
    //reset xyz coords for next pass
    for(i = 0; i < nnode*3; i++){
      cm.xyz[i] = m->xyz[i];
    }
    cp.UpdateXYZ(cm.xyz);

  }

  fout.close();

  delete [] dxdb;
  delete [] dxdbSurfC;

  return;
}
Ejemplo n.º 6
0
void Compute_dObjdQ(Real* dIdQ, SolutionSpace<Real>& space)
{
  RCmplx perturb (0.0, 1.0e-11);
  Int i, j;

  EqnSet<Real>* eqnset = space.eqnset;
  Mesh<Real>* rm = space.m;
  Param<Real>* param = space.param;
  BoundaryConditions<Real>* bc = space.bc;

  Int node;

  Int nnode = rm->GetNumNodes();
  Int gnode = rm->GetNumParallelNodes();
  Int nbnode = rm->GetNumBoundaryNodes();
  Int neqn = eqnset->neqn;
  Int nvars = neqn + eqnset->nauxvars;
  MPI_Datatype mpit = MPI_GetType(nnode);

  //get global number of nodes since processes need to be synced
  //build lookup maps from local to global id
  Int* globalToLocal;
  Int* localToGlobal;
  Int globalNodes = space.p->BuildGlobalMaps(&localToGlobal, &globalToLocal);

  RCmplx Obj;

  std::cout << "\n\nCOMPUTING dI/dQ\n\n" << std::endl;

  SolutionSpace<RCmplx> cspace(space);
  Mesh<RCmplx>* cm = cspace.m;
  PObj<RCmplx>* cp = cspace.p;
  EqnSet<RCmplx>* ceqnset = cspace.eqnset;

  //init dIdQ
  MemBlank(dIdQ, neqn*nnode);

  //compute surface areas once to ensure they are valid
  ComputeSurfaceAreas(&cspace, 0);

  for(i = 0; i < globalNodes; i++){
    node = globalToLocal[i];
    for(j = 0; j < neqn; j++){
      //perturb q value if node is local to process
      if(node >= 0){
	cspace.q[node*nvars + j] += perturb;
	ceqnset->ComputeAuxiliaryVariables(&cspace.q[node*nvars + 0]);
      }
      //compute perturbed objective function
      //no need for a call to compute_surface_areas here since we aren't changing them
      cp->UpdateGeneralVectors(cspace.q, nvars);
      Obj = Compute_Obj_Function(cspace);
      if(node >= 0){
	if(node < nnode){
	  dIdQ[node*neqn + j] = imag(Obj) / imag(perturb);
	}
	//reset q value
	cspace.q[node*nvars + j] = space.q[node*nvars + j];
	//compute aux vars one last time for all values reset to original
	ceqnset->ComputeAuxiliaryVariables(&cspace.q[node*nvars + 0]);
      }
    }
  }

  delete [] localToGlobal;
  delete [] globalToLocal;

  return;
}
Ejemplo n.º 7
0
void Compute_dQdBeta_FD(Real* dQdB, SolutionSpace<Real>& space, Int beta)
{
  Real perturb = 1.0e-8;
  
  Int i ,j;
  EqnSet<Real>* eqnset = space.eqnset;
  Param<Real>* param = space.param;
  Mesh<Real>* m = space.m;
  PObj<Real>* p = space.p;

  Int nnode = m->GetNumNodes();

  std::vector<SolutionSpaceBase<Real>*> solSpaces;
  solSpaces.push_back(&space);

  //create a temporary operations vector with just a single space iterator on it
  SolutionOrdering<Real> operations;
  std::string name = space.name;
  operations.Insert("Iterate " + name);
  operations.Finalize(solSpaces);

  //compute dq/db with finite difference
  Real* dQdB_up = new Real[nnode*eqnset->neqn];
  Real* dQdB_down = new Real[nnode*eqnset->neqn];
  Real* Qorig = new Real[nnode*eqnset->neqn];

  for(i = 0; i < nnode; i++){
    for(j = 0; j < eqnset->neqn; j++){
      Qorig[i*eqnset->neqn + j] = space.q[i*(eqnset->neqn+eqnset->nauxvars) + j];
    }
  }

  Real* dxdb = new Real[nnode*3];

  Get_dXdB(space.param->path+space.param->spacename, dxdb, m, beta);

  //perturb by dxdb*perturb UP
  for(Int i = 0; i < nnode; i++){
    for(Int j = 0; j < 3; j++){
      m->xyz[i*3 + j] += dxdb[i*3 + j]*perturb;
    }
  }
  //update xyz coords
  p->UpdateXYZ(m->xyz);
  //recalculate metrics
  m->CalcMetrics();

  //perturb any parameters as required for sensitivities
  Perturb_Param(beta, *param, 1);
  //reset any interesting field which might depend on perturbations
  space.RefreshForParam();

  Solve(solSpaces, operations);
  for(i = 0; i < nnode; i++){
    for(j = 0; j < eqnset->neqn; j++){
      dQdB_up[i*eqnset->neqn + j] = space.q[i*(eqnset->neqn+eqnset->nauxvars) + j];
    }
  }

  //perturb by dxdb*perturb DOWN
  for(Int i = 0; i < nnode; i++){
    for(Int j = 0; j < 3; j++){
      m->xyz[i*3 + j] -= 2.0*dxdb[i*3 + j]*perturb;
    }
  }
  //update xyz coords
  p->UpdateXYZ(m->xyz);
  //recalculate metrics
  m->CalcMetrics();

  //perturb any parameters as required for sensitivities
  //back to original and then down
  Perturb_Param(beta, *param, -1);
  Perturb_Param(beta, *param, -1);
  //reset any interesting field which might depend on perturbations
  space.RefreshForParam();

  Solve(solSpaces, operations);
  for(i = 0; i < nnode; i++){
    for(j = 0; j < eqnset->neqn; j++){
      dQdB_down[i*eqnset->neqn + j] = space.q[i*(eqnset->neqn+eqnset->nauxvars) + j];
    }
  }

  //compute differences
  for(i = 0; i < nnode; i++){
    for(j = 0; j < eqnset->neqn; j++){
      //up
      dQdB_up[i*eqnset->neqn + j] -= Qorig[i*eqnset->neqn + j];
      dQdB_up[i*eqnset->neqn + j] /= perturb;
      //down
      dQdB_down[i*eqnset->neqn + j] -= Qorig[i*eqnset->neqn + j];
      dQdB_down[i*eqnset->neqn + j] /= -perturb;
    }
  }

  //average for central difference
  for(i = 0; i < nnode; i++){
    for(j = 0; j < eqnset->neqn; j++){
      dQdB[i*eqnset->neqn + j] = 
	(dQdB_up[i*eqnset->neqn + j] + dQdB_down[i*eqnset->neqn + j]) / 2.0;
    }
  }

  //reset metrics in case we need them
  for(Int i = 0; i < nnode; i++){
    for(Int j = 0; j < 3; j++){
      m->xyz[i*3 + j] += dxdb[i*3 + j]*perturb;
    }
  }
  //update xyz coords
  p->UpdateXYZ(m->xyz);
  m->CalcMetrics();

  //go back to original value
  Perturb_Param(beta, *param, 1);
  //reset any interesting field which might depend on perturbations
  space.RefreshForParam();
  //the gaussian source is sometimes used to modify boundary velocities, etc.
  //pre-compute it for bc call
  if(space.param->gaussianSource){
    space.gaussian->ApplyToResidual();
  }

  //update boundary conditions
  UpdateBCs(&space);

  //reset Qorig in case we need it
  for(i = 0; i < nnode; i++){
    for(j = 0; j < eqnset->neqn; j++){
      space.q[i*(eqnset->neqn+eqnset->nauxvars) + j] = Qorig[i*eqnset->neqn + j];
      eqnset->ComputeAuxiliaryVariables(&space.q[i*(eqnset->neqn+eqnset->nauxvars)]);
    }
  }

  delete [] Qorig;
  delete [] dQdB_up;
  delete [] dQdB_down;
  delete [] dxdb;

  return;
}
Ejemplo n.º 8
0
void Compute_dRdBeta_CTSE(Real* dRdB, SolutionSpace<Real>& space, Int beta)
{
  RCmplx perturb (0.0, 1.0e-11);

  Mesh<Real>* rm = space.m;

  Int nnode = rm->GetNumNodes();
  Int gnode = rm->GetNumParallelNodes();
  Int nbnode = rm->GetNumBoundaryNodes();

  std::ifstream fin;

  SolutionSpace<RCmplx> cspace(space);
  Mesh<RCmplx>* cm = cspace.m;
  PObj<RCmplx>* cp = cspace.p;
  EqnSet<RCmplx>* ceqnset = cspace.eqnset;
  Param<RCmplx>* param = cspace.param;
  
  Int cnnode = cm->GetNumNodes();
  Int cgnode = cm->GetNumParallelNodes();
  Int cnbnode = cm->GetNumBoundaryNodes();

  RCmplx* q = cspace.q;

  Int neqn = ceqnset->neqn;
  Int nvars = neqn + ceqnset->nauxvars;

  Real* dxdb = new Real[nnode*3];

  Get_dXdB(space.param->path + space.param->spacename, dxdb, rm, beta);

  //perturb complex part by dxdb*perturb
  for(Int i = 0; i < nnode; i++){
    for(Int j = 0; j < 3; j++){
      cm->xyz[i*3 + j] += dxdb[i*3 + j]*perturb;
    }
  }
  //update xyz coords
  cp->UpdateXYZ(cm->xyz);
  //calculate metrics with new grid positions
  cm->CalcMetrics();
  //compute gradient coefficients once
  ComputeNodeLSQCoefficients(&cspace);

  //perturb any parameters which we are getting sensitivities for
  Perturb_Param(beta, *cspace.param);
  //reset any interesting field which might depend on perturbations
  cspace.RefreshForParam();
  
  //the gaussian source is sometimes used to modify boundary velocities, etc.
  //pre-compute it for bc call
  if(cspace.param->gaussianSource){
    cspace.gaussian->ApplyToResidual();
  }

  //update boundary conditions
  cspace.p->UpdateGeneralVectors(q, nvars);
  UpdateBCs(&cspace);
  cspace.p->UpdateGeneralVectors(q, nvars);

  //now, compute gradients and limiters
  if(param->sorder > 1 || param->viscous){
    for(Int i = 0; i < (cnnode+cnbnode+cgnode); i++){
      ceqnset->NativeToExtrapolated(&q[i*nvars]);
    }
    cspace.grad->Compute();
    cspace.limiter->Compute(&cspace);
    for(Int i = 0; i < (cnnode+cnbnode+cgnode); i++){
      ceqnset->ExtrapolatedToNative(&q[i*nvars]);
    }
  }

  //compute spatial residual
  SpatialResidual(&cspace);
  ExtraSourceResidual(&cspace);
  for(Int i = 0; i < nnode; i++){
    for(Int j = 0; j < ceqnset->neqn; j++){
      dRdB[i*ceqnset->neqn + j] = imag(cspace.crs->b[i*ceqnset->neqn + j])/imag(perturb);
    }
  } 

  delete [] dxdb;
}
Ejemplo n.º 9
0
void ComputedQdBeta_HardsetBC(Int nnodes, Int* nodes, Real* dQdB, const SolutionSpace<Real>& space, Int beta)
{
  Real h = 1.0e-11;
  RCmplx I(0.0, 1.0);
  RCmplx perturb = h*I;

  Mesh<Real>* rm = space.m;

  SolutionSpace<RCmplx> cspace(space);
  Mesh<RCmplx>* cm = cspace.m;
  PObj<RCmplx>* cp = cspace.p;
  EqnSet<RCmplx>* ceqnset = cspace.eqnset;
  Param<RCmplx>* param = cspace.param;
  RCmplx* q = cspace.q;

  Int nnode = rm->GetNumNodes();

  Int neqn = ceqnset->neqn;
  Int nvars = neqn + ceqnset->nauxvars;

  Real* dxdb = new Real[nnode*3];

  Get_dXdB(space.param->path + space.param->spacename, dxdb, rm, beta);

  //perturb complex part by dxdb*perturb
  for(Int i = 0; i < nnode; i++){
    for(Int j = 0; j < 3; j++){
      cm->xyz[i*3 + j] += dxdb[i*3 + j]*perturb;
    }
  }
  //update xyz coords
  cp->UpdateXYZ(cm->xyz);
  //calculate metrics with new grid positions
  cm->CalcMetrics();
  //compute gradient coefficients once
  ComputeNodeLSQCoefficients(&cspace);

  //perturb any parameters which we are getting sensitivities for
  Perturb_Param(beta, *cspace.param);
  //reset any interesting field which might depend on perturbations
  cspace.RefreshForParam();
  
  //the gaussian source is sometimes used to modify boundary velocities, etc.
  //pre-compute it for bc call
  if(cspace.param->gaussianSource){
    cspace.gaussian->ApplyToResidual();
  }

  //update boundary conditions
  cspace.p->UpdateGeneralVectors(q, nvars);
  UpdateBCs(&cspace);
  cspace.p->UpdateGeneralVectors(q, nvars);

  for(Int i = 0; i < nnodes; i++){
    Int node = nodes[i];
    for(Int j = 0; j < neqn; j++){
      dQdB[i*neqn + j] = imag(q[node*nvars + j])/h;
      std::cout << "dqdb: " << i << ": -" << j << " " <<  dQdB[i*neqn + j] << std::endl;
    }
  }

}
Ejemplo n.º 10
0
void Compute_dRdQ_Product_MatrixFree(SolutionSpace<RCmplx>& cspace, Real* vector, Real* prod)
{
  RCmplx perturb(0.0, 1.0e-11);
  Mesh<RCmplx>* cm = cspace.m;
  Param<RCmplx>* param = cspace.param;
  EqnSet<RCmplx>* ceqnset = cspace.eqnset;
  RCmplx* q = cspace.q;
  PObj<RCmplx>* p = cspace.p;

  Int cnnode = cm->GetNumNodes();
  Int cgnode = cm->GetNumParallelNodes();
  Int cnbnode = cm->GetNumBoundaryNodes();

  Int neqn = ceqnset->neqn;
  Int nvars = ceqnset->nauxvars + neqn;

  for(Int i = 0; i < cnnode; i++){
    RCmplx* iq = &q[i*nvars + 0];
    for(Int j = 0; j < neqn; j++){
      iq[j] += vector[i*neqn + j]*perturb;
    }
    ceqnset->ComputeAuxiliaryVariables(iq);
  }
  p->UpdateGeneralVectors(q, nvars);

  //the gaussian source is sometimes used to modify boundary velocities, etc.
  //pre-compute it for bc call
  if(cspace.param->gaussianSource){
    cspace.gaussian->ApplyToResidual();
  }

  UpdateBCs(&cspace);
  p->UpdateGeneralVectors(q, nvars);
  
  //now, compute gradients and limiters
  if(param->sorder > 1 || param->viscous){
    for(Int i = 0; i < (cnnode+cnbnode+cgnode); i++){
      ceqnset->NativeToExtrapolated(&q[i*nvars]);
    }
    cspace.grad->Compute();
    cspace.limiter->Compute(&cspace);
    for(Int i = 0; i < (cnnode+cnbnode+cgnode); i++){
      ceqnset->ExtrapolatedToNative(&q[i*nvars]);
    }
  }

  //it is assumed that this routine is going to be called iteratively,
  //therefore, calling the turbulence model here, will slowly converge the
  //turbulence model towards the correct sensitivity
  //This should theoretically be converged here at every call to this routine,
  //but that is horribly costly.... so we cheat
  //WARNING: ---- for now, we assume frozen turbulence models
  if(param->viscous && false){
    cspace.turb->Compute();
    if(param->gcl){
      std::cout << "MATRIX FREE: COMPUTE GCL FOR TURB MODEL!" << std::endl;
    }
  }

  //Now compute residual, this only works for spatial residual right now
  SpatialResidual(&cspace);
  ExtraSourceResidual(&cspace);

  //Now do the CTSE derivative part
  for(Int i = 0; i < cnnode; i++){
    for(Int j = 0; j < neqn; j++){
      prod[i*neqn + j] = imag(cspace.crs->b[i*neqn + j])/imag(perturb);
    }
  }

  //re-zero the complex part of the q vector in case we reuse the cspace
  for(Int i = 0; i < cnnode; i++){
    RCmplx* iq = &q[i*nvars + 0];
    for(Int j = 0; j < neqn; j++){
      iq[j] = real(iq[j]);
    }
    ceqnset->ComputeAuxiliaryVariables(iq);
  }
  p->UpdateGeneralVectors(q, nvars);

  return;
}
Ejemplo n.º 11
0
void Compute_dRdBeta_FD(Real* dRdB, SolutionSpace<Real>& space, Int beta)
{
  Real perturb = 1.0e-8;

  EqnSet<Real>* eqnset = space.eqnset;
  Mesh<Real>* m = space.m;
  PObj<Real>* p = space.p;
  Param<Real>* param = space.param;
  Real* q = space.q;
  Int i;

  Int neqn = eqnset->neqn;
  Int nvars = neqn + eqnset->nauxvars;

  Int nnode = m->GetNumNodes();
  Int gnode = m->GetNumParallelNodes();
  Int nbnode = m->GetNumBoundaryNodes();

  Real* Qorig = new Real[nnode*nvars];
  Real* resOrig = new Real[nnode*neqn];
  Real* resUp = new Real[nnode*neqn];
  Real* resDown = new Real[nnode*neqn];

  //store original q
  for(i = 0; i < (nnode*nvars); i++){
    Qorig[i] = space.q[i];
  }

  UpdateBCs(&space);
  //compute spatial residual
  SpatialResidual(&space);
  ExtraSourceResidual(&space);
  for(Int i = 0; i < nnode; i++){
    for(Int j = 0; j < eqnset->neqn; j++){
      resOrig[i*eqnset->neqn + j] = space.crs->b[i*eqnset->neqn + j];
    }
  } 

  Real* dxdb = new Real[nnode*3];

  Get_dXdB(space.param->path+space.param->spacename, dxdb, m, beta);

  //perturb complex part by dxdb*perturb UP
  for(Int i = 0; i < nnode; i++){
    for(Int j = 0; j < 3; j++){
      m->xyz[i*3 + j] += dxdb[i*3 + j]*perturb;
    }
  }
  //update xyz coords
  p->UpdateXYZ(m->xyz);
  //calculate metrics with new grid positions
  m->CalcMetrics();
  //compute gradient coefficients once
  ComputeNodeLSQCoefficients(&space);

  //perturb parameters as required
  Perturb_Param(beta, *(space.param), 1);
  //reset any interesting field which might depend on perturbations
  space.RefreshForParam();

  //the gaussian source is sometimes used to modify boundary velocities, etc.
  //pre-compute it for bc call
  if(space.param->gaussianSource){
    space.gaussian->ApplyToResidual();
  }

  //update boundary conditions
  UpdateBCs(&space);
  //now, compute gradients and limiters
  if(param->sorder > 1 || param->viscous){
    for(Int i = 0; i < (nnode+nbnode+gnode); i++){
      eqnset->NativeToExtrapolated(&q[i*nvars]);
    }
    space.grad->Compute();
    space.limiter->Compute(&space);
    for(Int i = 0; i < (nnode+nbnode+gnode); i++){
      eqnset->ExtrapolatedToNative(&q[i*nvars]);
    }
  }

  //compute spatial residual
  SpatialResidual(&space);
  ExtraSourceResidual(&space);
  for(Int i = 0; i < nnode; i++){
    for(Int j = 0; j < eqnset->neqn; j++){
      resUp[i*eqnset->neqn + j] = (space.crs->b[i*eqnset->neqn + j]);
    }
  } 

  //perturb parameters as required, call twice (move back to original value then perturb down)
  Perturb_Param(beta, *(space.param), -1);
  Perturb_Param(beta, *(space.param), -1);
  //reset any interesting field which might depend on perturbations
  space.RefreshForParam();

  //the gaussian source is sometimes used to modify boundary velocities, etc.
  //pre-compute it for bc call
  if(space.param->gaussianSource){
    space.gaussian->ApplyToResidual();
  }

  //perturb complex part by dxdb*perturb DOWN
  for(Int i = 0; i < nnode; i++){
    for(Int j = 0; j < 3; j++){
      m->xyz[i*3 + j] -= 2.0*dxdb[i*3 + j]*perturb;
    }
  }
  //update xyz coords
  p->UpdateXYZ(m->xyz);
  //calculate metrics with new grid positions
  m->CalcMetrics();
  //compute gradient coefficients once
  ComputeNodeLSQCoefficients(&space);
  //update boundary conditions
  UpdateBCs(&space);
  //now, compute gradients and limiters
  if(param->sorder > 1 || param->viscous){
    for(Int i = 0; i < (nnode+nbnode+gnode); i++){
      eqnset->NativeToExtrapolated(&q[i*nvars]);
    }
    space.grad->Compute();
    space.limiter->Compute(&space);
    for(Int i = 0; i < (nnode+nbnode+gnode); i++){
      eqnset->ExtrapolatedToNative(&q[i*nvars]);
    }
  }
  //compute spatial residual
  SpatialResidual(&space);
  ExtraSourceResidual(&space);
  for(Int i = 0; i < nnode; i++){
    for(Int j = 0; j < eqnset->neqn; j++){
      resDown[i*eqnset->neqn + j] = (space.crs->b[i*eqnset->neqn + j]);
    }
  } 

  for(Int i = 0; i < nnode; i++){
    for(Int j = 0; j < eqnset->neqn; j++){
      //up
      resUp[i*eqnset->neqn + j] -= resOrig[i*eqnset->neqn + j];
      resUp[i*eqnset->neqn + j] /= perturb;
      //down
      resDown[i*eqnset->neqn + j] -= resOrig[i*eqnset->neqn + j];
      resDown[i*eqnset->neqn + j] /= (-perturb);
      //central
      dRdB[i*eqnset->neqn + j] = (resUp[i*eqnset->neqn + j] + resDown[i*eqnset->neqn +j]) / 2.0;
    }
  }
  
  //reset metrics in case we need them
  for(Int i = 0; i < nnode; i++){
    for(Int j = 0; j < 3; j++){
      m->xyz[i*3 + j] += dxdb[i*3 + j]*perturb;
    }
  }
  //update xyz coords
  p->UpdateXYZ(m->xyz);
  //recalculate metrics
  m->CalcMetrics();
  //compute gradient coefficients once
  ComputeNodeLSQCoefficients(&space);
  //reset Qorig in case we need it
  for(i = 0; i < nnode*nvars; i++){
    space.q[i] = Qorig[i];
  }
 

  //go back to original values
  Perturb_Param(beta, *(space.param), 1);
  //reset any interesting field which might depend on perturbations
  space.RefreshForParam();

 //the gaussian source is sometimes used to modify boundary velocities, etc.
  //pre-compute it for bc call
  if(space.param->gaussianSource){
    space.gaussian->ApplyToResidual();
  }

 //update boundary conditions
  UpdateBCs(&space);
  //now, compute gradients and limiters
  if(param->sorder > 1 || param->viscous){
    for(Int i = 0; i < (nnode+nbnode+gnode); i++){
      eqnset->NativeToExtrapolated(&q[i*nvars]);
    }
    space.grad->Compute();
    space.limiter->Compute(&space);
    for(Int i = 0; i < (nnode+nbnode+gnode); i++){
      eqnset->ExtrapolatedToNative(&q[i*nvars]);
    }
  }

  delete [] dxdb;

  delete [] resOrig;
  delete [] resUp;
  delete [] resDown;

  return;
}
Ejemplo n.º 12
0
int main(int argc, char* argv[]){

#ifdef _DEBUG
  //enable exceptions so we can trap NaNs, etc.
  feenableexcept(FE_INVALID | FE_OVERFLOW);
#endif

  Int rank, np;
  Int mode = 0;
  Int ndv = 0;
  Real* dObjdBeta = NULL;
  
  std::vector<Param<Real>* > paramList; 
  SolutionOrdering<Real> operations;
  TemporalControl<Real> temporalControl;

  string tempname;
  stringstream temposs;

  TimerList timers(5);
  timers.CreateTimer("MPI_InitTimer");
  timers.CreateTimer("SolveTimer");
  timers.CreateTimer("DesignTimer");
  timers.CreateTimer("MovementTimer");

  //create parallel object for comms
  timers.StartTimer("MPI_InitTimer");
  MPI_Init(&argc, &argv);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &np);
  timers.StopTimer("MPI_InitTimer");

  PObj<Real> pobj;
  rank = pobj.GetRank();
  //remove Abort.Log if its present
  if(rank == 0){
    remove("Abort.Log");
  }
  
  if(!((argc == 2) || (argc == 3))){
    cerr << "Invalid arguments!!!" << endl;
    cerr << "USE: " << argv[0] << " <casename>" << endl;
    cerr << "OR" << endl;
    cerr << "USE: " << argv[0] << " <casename> <design type>" << endl;
    cerr << "<design type> - none = 0" << endl;
    cerr << "<design type> - objective f-n evaluation = 1" << endl;
    cerr << "<design type> - direct = 2" << endl;
    cerr << "<design type> - adjoint = 3" << endl;
    cerr << "<design type> - CTSE = 4" << endl;
    cerr << "<design type> - GRID SMOOTHING = 5" << endl;
    cerr << "<design type> - Compute Mesh Sensitivity = 6" << endl;
    cerr << "<design type> - Finite Difference = 7" << endl;

    //dumps all options in param file to output
    Param<Real> tmp;
    tmp.PrintAllParams();

    MPI_Finalize();
    return (1);
  }

  std::string casestring = argv[1];
  size_t pos = casestring.rfind('/');
  std::string pathname;
  if(pos != std::string::npos){
    pathname = casestring.substr(0, pos+1);
    casestring = casestring.substr(pos);
  }
  else{
    pathname = "./";
  }

  //set pathname in abort class
  Abort.rootDirectory = pathname;

  if(argc == 3){
    temposs.clear();
    temposs.str("");
    temposs << argv[2];
    temposs >> mode;
  }