void SolveBracketPair( char *bracket_open, char *bracket_close )
{
	//			(1+2)
	//			1
	Assert( bracket_open && *bracket_open );

	int len_real = bracket_close - bracket_open;

	char *ops_Start = bracket_open;
	char *ops_End = bracket_close;

	if ( ISCHAR_BRACKET( *ops_Start ) && *(ops_Start+1) )
		ops_Start++;
	const bool bIsClosing = ISCHAR_BRACKET( *ops_End );

	int len_operation = ops_End - ops_Start;

	char solveString[ MAX_OPERATION_C ];

	Q_memcpy( solveString, ops_Start, len_operation );
	solveString[ len_operation ] = '\0';

	for ( int step = 0; step < 2; step++ )
	{
		bool didValueLastStep = false;

		for( char *SolveIterate = solveString; *SolveIterate; SolveIterate++ )
		{
			const bool bOps_step1 = ISCHAR_OPERATOR_STEP1( *SolveIterate );
			const bool bOps_step2 = ISCHAR_OPERATOR_STEP2( *SolveIterate );
			const bool bOps_common = bOps_step1 || bOps_step2;
			const bool bOps_cur = step ? bOps_step2 : bOps_step1;

			const bool bValue = ISSTRING_LITERAL( solveString, SolveIterate ) || ISSTRING_VALUE( solveString, SolveIterate );
			if ( bValue && !bOps_cur )
				didValueLastStep = true;
			else if ( bOps_cur && didValueLastStep )
			{
				SolveOperator( solveString, SolveIterate );
				SolveIterate = solveString;
				didValueLastStep = false;
			}
			else if ( !bValue && !bOps_common )
			{
				SnipCharFromString( SolveIterate );
			}
		}
	}

	float finalValue = GetValueFromChar( solveString, solveString );
	char valueString[ MAX_OPERATION_C ];
	Q_snprintf( valueString, MAX_OPERATION_C, "%f\0", finalValue );
	StringReplace( bracket_open, len_real + bIsClosing, valueString );
}
Esempio n. 2
0
//=============================================================================
void
FluidNavierStokes(
const int         order,      ///< order of the time discretization
const mesh_t*     mesh,       ///< mesh structure
const bc_t*       bc,         ///< boundary conditions
#ifdef VERSION_Z
      mesh_t*     mesh_o,     ///< mesh structure of outer domain
      double*     Vel_o[4],   ///< fluid velocity of outer domain
#endif          
const fluid_t*    fluid,      ///< fluid parameters
const particle_t  particle[], ///< particles
const double      tau[3],     ///< time discretization coefficients
const double      dt,         ///< time step
      FluidVar_t* FluidVar )  ///< fluid variables
{
  double
  *VelTilde1[4] = {NULL,NULL,NULL,NULL}, // Convected velocity from level n 
  *VelTilde2[4] = {NULL,NULL,NULL,NULL}, // Convected velocity from level n-1
  FrameVel[4] = { 0.,0.,0.,0. }; // frame velocity
  
  for ( int dir = 1 ; dir <= 3 ; dir++ )
  {
    AllocVdouble(mesh->NbOfNodes, VelTilde1[dir]);
    AllocVdouble(mesh->NbOfNodes, VelTilde2[dir]);
  }
  
#ifdef VERSION_Z
  if ( UsingMicroGrid() )
  {
    // find nodes of inner domain that are outside outer domain
    FindNodesOutside(particle, mesh_o, mesh);
    
    // set those nodes velocity to 0.
    for ( int NodeId = 1 ; NodeId <= mesh->NbOfNodes ; NodeId++ )
      if ( mesh->OutsideNodes[NodeId] == true )
        for ( int dir = 1 ; dir <= 3 ; dir++ )
          FluidVar->Vel[dir][NodeId] = 0.;    
  }
#endif
  
  //----------------------------------------------------------------------------
  // Compute all the velocity rhs contributions
  //----------------------------------------------------------------------------
  // rhs = 0
  for ( int dir = 1 ; dir <= 3 ; dir++ )
    scal( mesh->NbOfNodes+1, 0., FluidVar->VelRHS[dir] );
  
  // compute frame velocity
  FrameVelSet( particle, fluid->FrameVelDir, FrameVel );
  
  //----------------------------------------------------------------------------
  // Pressure gradient contribution
  //----------------------------------------------------------------------------
  // compute and substract pressure gradient to rhs
  ApplyOperator("gradient", &FluidVar->Pre, FluidVar->VelRHS);
  
  //----------------------------------------------------------------------------
  // Convection terms contribution
  //----------------------------------------------------------------------------
#ifdef VERSION_Z
  const double *ParticlePos = (order == 1) ? particle[1].Pos1 : particle[1].Pos2;
//  const double *ParticlePos = particle[1].Pos;
  
  if ( UsingMicroGrid() )
    ConvectionMicroGrid(order, mesh, dt, FrameVel,
             ParticlePos, mesh_o, Vel_o,
             FluidVar->VelOld1, FluidVar->VelOld2, VelTilde1, VelTilde2);
  else
    ConvectionMacroGrid(order, mesh, dt, FrameVel,
                        ParticlePos, mesh_o, Vel_o,
                        FluidVar->VelOld1, FluidVar->VelOld2, VelTilde1, VelTilde2);
#else
  
  Convection(order, mesh, dt, FrameVel,
             FluidVar->VelOld1, FluidVar->VelOld2, VelTilde1, VelTilde2);
#endif 
  
  // compute the convection terms in Acc
  for ( int dir = 1 ; dir <= 3 ; dir++ )
    axpby( mesh->NbOfNodes+1, -tau[1], VelTilde1[dir], 0., FluidVar->Acc[dir] );
  
  if ( order == 2 )
    for ( int dir = 1 ; dir <= 3 ; dir++ )
      axpby( mesh->NbOfNodes+1, -tau[2], VelTilde2[dir], 1., FluidVar->Acc[dir]);
  
  // weight by mass matrix and substract them from rhs
  ApplyOperator("convection", FluidVar->Acc, FluidVar->VelRHS);
  
  // set convected velocity at previous timestep as initial guess for conjugate gradient
  // WARNING : this has to be done before we set boundary conditions, otherwise those latter could get overwritten
  for ( int dir = 1 ; dir <= 3 ; dir++ )
    copy(mesh->NbOfNodes+1, VelTilde1[dir], FluidVar->Vel[dir]);
  
  //----------------------------------------------------------------------------
  // Particle weight contribution
  //----------------------------------------------------------------------------
  if ( UsingMicroGrid() )
    GetParticleMomentumContribution(mesh, particle, fluid, FluidVar->VelRHS);
  
  //----------------------------------------------------------------------------
  // Boundary conditions contribution
  //----------------------------------------------------------------------------
  SetVelBC( mesh->NbOfNodes, bc, FluidVar->Vel );
  
#ifdef VERSION_Z
  // prescribe dirichlet bc by interpolating outer domain velocity, this has to be done after SetVelBC !
  if ( UsingMicroGrid() )
    MassConserveBC( particle[1].Pos, mesh_o, Vel_o, mesh, FluidVar->Vel );
#endif
  
  // weight with stifness matrix and substract to rhs
  ApplyOperator("v_bc", FluidVar->Vel, FluidVar->VelRHS);
  
  //----------------------------------------------------------------------------
  // Solve for the velocity: advection-diffusion step
  //----------------------------------------------------------------------------
  debug( "\nVelocity diffusion step\n" );
  
  SolveOperator("v_stiffness", mesh->OutsideNodes, FluidVar->VelRHS, FluidVar->Vel);

  //----------------------------------------------------------------------------
  // Solve for the pressure star: projection step
  //----------------------------------------------------------------------------
  debug( "\nPressure prediction step\n" );
  
  // initialize pressure rhs
  double *PreStar = NULL, // Predicted presssure
  *PreRHS  = NULL; // Presssure RHS
  
  AllocVdouble( mesh->NbOfPressureNodes,PreStar );
  AllocVdouble( mesh->NbOfPressureNodes,PreRHS );
  
  // compute and add velocity divergence to pressure rhs
  ApplyOperator("divergence", FluidVar->Vel, &PreRHS);
  
  // mutliply pressure rhs by -tau_0
  scal( mesh->NbOfPressureNodes+1, -tau[0], PreRHS );
  
  // set previous step pressure as initial guess for conjugate gradient
  copy( mesh->NbOfFreePressureNodes+1, FluidVar->Pre, PreStar );
  
  SolveOperator("p_stiffness", mesh->OutsideNodes, &PreRHS, &PreStar);

  //----------------------------------------------------------------------------
  // Solve for the velocity: projection step
  //----------------------------------------------------------------------------
  debug( "\nVelocity projection step\n" );
  
  // rhs = 0
  for ( int dir = 1 ; dir <= 3 ; dir++ )
    scal( mesh->NbOfNodes+1, 0., FluidVar->VelRHS[dir] );
  
  // compute and substract pressure star gradient to velocity rhs
  ApplyOperator("gradient", &PreStar, FluidVar->VelRHS);
  
  // VelTilde2 = 0, used here as temporary array, it will store the un-weigthed gradient
  for ( int dir = 1 ; dir <= 3 ; dir++ )
    scal( mesh->NbOfNodes+1, 0., VelTilde2[dir] );
  
  // compute the un-weigthed gradient
  SolveOperator("v_mass", mesh->OutsideNodes, FluidVar->VelRHS, VelTilde2);
  
  // Remove the non solenoidal part of the velocity, i.e. the un-weigthed gradient
  for ( int dir = 1 ; dir <= 3 ; dir++ )
    axpby(mesh->NbOfNodes+1, 1. / tau[0], VelTilde2[dir], 1.,
          FluidVar->Vel[dir]);
  
  //----------------------------------------------------------------------------
  // Solve for the pressure: correction step
  //----------------------------------------------------------------------------
  debug( "\nPressure correction step\n" );
  
  // p = p + p*
  axpby( mesh->NbOfPressureNodes+1, 1., PreStar, 1., FluidVar->Pre );
  
#ifdef PRE_INCREMENTAL_ROTATIONAL
  // then solve for - 1/Re Div(vel) = PreMass^{-1} * PreRHS, solve in p* again
  
  // solve for PreStar
  for ( int i = 1 ; i <= mesh->NbOfPressureNodes ; i++ ) 
    PreStar[i] = PreRHS[i] * FluidOperators->PreMassPrec[i];
  
  // p = p + p* = p - 1/Re Div(vel)
  axpby( mesh->NbOfPressureNodes+1, 1., PreStar, 1., FluidVar->Pre );
#endif
  
  // Compute the acceleration field of the fluid, Acc = tau0 * Vel - Acc
  for ( int dir = 1 ; dir <= 3 ; dir++ )
    axpby(mesh->NbOfNodes+1, tau[0], FluidVar->Vel[dir], -1.,
          FluidVar->Acc[dir]);
  
  // free local arrays
  for ( int dir = 1 ; dir <= 3 ; dir++ )
  {  
    free(VelTilde1[dir]);    
    free(VelTilde2[dir]);
  }
  free(PreStar);
  free(PreRHS);  
}