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 ); }
//============================================================================= 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); }