Esempio n. 1
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;
}
Esempio n. 2
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;
}
Esempio n. 3
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;
}
Esempio n. 4
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;
}
Esempio n. 5
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;
}
Esempio n. 6
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;
    }
  }

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