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