Ejemplo n.º 1
0
EXPORT void compute_body_force_x2( 
      Array3<double> curvature,				// interface curvature 
      Array3<double> level_set, 				// level set field
      Array3<double> surface_tension_body_force_x2,	// x2 component of the body force due to
							// CSF formulation of surface tension model
      double mesh_width_x1,				// grid spacing in x1 direction (uniform)
      double mesh_width_x2,				// grid spacing in x2 direction (uniform)
      double mesh_width_x3,				// grid spacing in x3 direction (uniform)
      int number_primary_cells_i,			// number of primary (pressure) cells in x1 direction
      int number_primary_cells_j,			// number of primary (pressure) cells in x2 direction
      int number_primary_cells_k,			// number of primary (pressure) cells in x3 direction
      double rho_plus_over_rho_minus, 		// rho_plus / rho_minus indicated 
      double sigma_over_rho_minus,			// sigma / rho_minus (scaled sigma)
      double maximum_body_force_x2,			// maximum body force in x2 direction			
      double total_body_force_x2,			// total body force in x2 direction 
      double maximum_weighted_curvature,		// maximum 'active' value of the curvature 
							// used to evaluate the capillary time step
							// restriction 
      double smoothing_distance_factor		// the smoothing distance is smoothing_distance_factor
       )						
       
 {
      double rho_minus_over_rho_mean=			//  rho_minus/( 0.5* (rho_plus + rho_minus))
		2.0/(1.0+rho_plus_over_rho_minus); 
      double weighted_curvature=0;				// curvature weighted by the derivative of
								// the derivative of the heaviside of the level-set
      double one_over_dx2	=    				// 1/(grid spacing in x2 direction)
	    1.0/(mesh_width_x2);
      int i_index, j_index, k_index;  			// local variables for loop indexing
      
      /* reset total and maximum body force */
      
     maximum_body_force_x2=0.0;
     total_body_force_x2=0.0;
	
     /* set body force in x2 direction to zero */
     
     set_constant_matrix2(number_primary_cells_i+2,number_primary_cells_j+1, number_primary_cells_k+2,
				surface_tension_body_force_x2, 0.0);


	
     for(i_index=1;i_index<number_primary_cells_i+1;i_index++)
      {
	
	  for(j_index=0;j_index<number_primary_cells_j+1;j_index++)
	  {
	      
	      for(k_index=1;k_index<number_primary_cells_k+1;k_index++)
	      {
		/* weight the curvature with the derivative of the heaviside function */
		/* this basically makes it only 'active' near the interface */
		
		weighted_curvature=0.5*( curvature[i_index][j_index][k_index]+
					      curvature[i_index][j_index+1][k_index])*
						computed_derivative_heaviside_function(
						    level_set[i_index][j_index][k_index],
							 level_set[i_index][j_index+1][k_index],	  		
							    mesh_width_x1, mesh_width_x2, mesh_width_x3,			
							      smoothing_distance_factor);
						
		/* the surface tension body force is */
		/* 2 * sigma * dPhi / dx * kappa * delta_a / (rho_p + rho_m) */
		
		
		surface_tension_body_force_x2[i_index][j_index][k_index]= 
					     -1.0*rho_minus_over_rho_mean*sigma_over_rho_minus*
						one_over_dx2*(level_set[i_index][j_index+1][k_index]-
								level_set[i_index][j_index][k_index])*
								    weighted_curvature;
								    
		/* update the maximum body force in the x2 direction */
		
		maximum_body_force_x2=std::max(maximum_body_force_x2, 
					       fabs(surface_tension_body_force_x2[i_index][j_index][k_index]));

		/* update the maximum weighted curvature in the x2 direction */
		
		maximum_weighted_curvature=std::max(maximum_weighted_curvature,
						      fabs(weighted_curvature));
		total_body_force_x2+=surface_tension_body_force_x2[i_index][j_index][k_index];
		      
	      }
	  }
      }
// 	  	std::cerr<< " maximum body force x2 direction "<< maximum_body_force_x2 <<"\n";
// 	  	std::cerr<< " maximum weighted curvature x2 "<< maximum_weighted_curvature <<"\n";
 }
Ejemplo n.º 2
0
EXPORT void   compute_level_set_gradient(				
	Array3<double> level_set, 			// level set field at new time level
						// after convection and reinitialization
						// not mass conserving
	Array3<double> d_level_set_d_x1,			// first partial derivative of
							// the level-set field wrt x1
							// second order central approximation
	Array3<double> d_level_set_d_x2,			// first partial derivative of 
							// the level-set field wrt x2
							// second order central approximation
	Array3<double> d_level_set_d_x3,			// first partial derivative of
 							// the level-set field wrt x3
							// second order central approximation
        int number_primary_cells_i,		// number of primary (pressure) cells in x1 direction
	int number_primary_cells_j,		// number of primary (pressure) cells in x2 direction
	int number_primary_cells_k		// number of primary (pressure) cells in x3 direction
	  )
   {
	int i_index, j_index, k_index;  			// local variables for loop indexing
// 	int vector_length= 					// length of the one dimensional array
// 	    (number_primary_cells_i+2)*				// that results from reshaping the 3D
// 		(number_primary_cells_j+2)*			// array of unknowns, with 1 virtual cell
// 		    (number_primary_cells_k+2);			// on all sides

		    
	/* set all first derivatives to zero, this takes care of all the virtual cells */

        set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+2, 
			    number_primary_cells_k+2, d_level_set_d_x1, 0.0);
        set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+2, 
			    number_primary_cells_k+2, d_level_set_d_x2, 0.0);
        set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+2, 
			    number_primary_cells_k+2, d_level_set_d_x3, 0.0);

	/* compute the gradient in all nonvirtual cells, using a central approximation        */
	/* to the first derivative 						      	      */
	/* note the nonvirtual cells start at index 1 and end at index number_primary_cells_* */
	
	
	for(i_index=1;i_index<number_primary_cells_i+1;i_index++)
	{
	    for(j_index=1;j_index<number_primary_cells_j+1;j_index++)
	    {
		    for(k_index=1;k_index<number_primary_cells_k+1;k_index++)
		{
		  
		    d_level_set_d_x1[i_index][j_index][k_index]=
				     0.5*(level_set[i_index+1][j_index  ][k_index  ]-
					    level_set[i_index-1][j_index  ][k_index  ]);
		    d_level_set_d_x2[i_index][j_index][k_index]=
				     0.5*(level_set[i_index  ][j_index+1][k_index  ]-
					    level_set[i_index  ][j_index-1][k_index  ]);
		    d_level_set_d_x3[i_index][j_index][k_index]=
				     0.5*(level_set[i_index  ][j_index  ][k_index+1]-
					    level_set[i_index  ][j_index  ][k_index-1]);
		}

	      
	    }
	}
     
   }
EXPORT int modify_volume_of_fluid_values(
      Array3<double> level_set, 				    	// level-set field
      Array3<double> volume_of_fluid,					// volume of fluid field, uncorrected
									// so with possible vapour cells and 
									// under/overfilled cells
      Array3<double> volume_of_fluid_correction,		    	// correction to the volume of fluid field
									// to make it valid
      Array3<double> invalid_vof_cells,                                 // indication field to show what is wrong
                                                                        // indicator field showing cells that are either
                                                                        // within bounds =0
                                                                        // underfilled   =-1
                                                                        // overfilled    =+1
                                                                        // vapour cells  = 5
      double mesh_width_x1,                                             // grid spacing in x1 direction (uniform)
      double mesh_width_x2,                                             // grid spacing in x2 direction (uniform)
      double mesh_width_x3,                                             // grid spacing in x3 direction (uniform)
      int number_primary_cells_i,			    		// number of primary (pressure) cells in x1 direction
      int number_primary_cells_j,			    	    	// number of primary (pressure) cells in x2 direction
      int number_primary_cells_k,			            	// number of primary (pressure) cells in x3 direction
      double volume_of_fluid_tolerance			    	        // tolerance for volume of fluid value
      )
      {

      double current_level_set_value;				        // current level-set field value in the control volume
      double current_volume_of_fluid_value;				// current volume of fluid field value in 
									// the control volume 
      double correct_vof_value;					        // the value a cell with an invalid volume of
									// fluid is set to: 1, 0 dependent on the sign
									// of the level-set function
      int number_cells_vof_out_of_bounds=0;				// number of control volumes where the volume of fluid
									// function is OUTSIDE the interval [0,1]
      int number_cells_numerical_vapor=0;				// number of control volumes where the volume of fluid
									// function is INSIDE the interval [0,1]
									// while the cell has 6 neighbours with the same sign:
									// the cell is NOT an interface cell
      int number_cells_invalid_volume_of_fluid; 			// sum of number of vapour cells and number of cells
      int i_index, j_index, k_index;  				        // local variables for loop indexing
      int adapt_vof_value;						// =1 adapt the volume of fluid value in this
									// cell, because it has an invalid value
      bool detailed_output=0;                                           // =1, provide detailed output
                                                                        // =0, provide non output 

          
          
         /* we start with the assumption that all volume of fluid values are valid */
         
          set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+2, 
                            number_primary_cells_k+2, invalid_vof_cells, 0.0);
          set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+2, 
                            number_primary_cells_k+2, volume_of_fluid_correction, 0.0);
        
         

         /* all nonvirtual cells are modified */
         /* the required modification is stored in volume_of_fluid_correction */
         
         
	  for(i_index=1;i_index<number_primary_cells_i+1;i_index++)
	  {
	      for(j_index=1;j_index<number_primary_cells_j+1;j_index++)
	      {
		  for(k_index=1;k_index<number_primary_cells_k+1;k_index++)
		  {
		        current_level_set_value=level_set[i_index][j_index][k_index];
		        current_volume_of_fluid_value=volume_of_fluid[i_index][j_index][k_index];
                      
                        /* assume the cell has a valid vof value */
                    
		        adapt_vof_value=0;
		      
		        /* check if the cell is a vapour cell, when this update is applied */
                      
		        if(
                               
			/* is the cell surrounded by neighbours with the same sign ?*/
                        
		                (
		                (level_set[i_index-1][j_index  ][k_index  ]*current_level_set_value>0)&&
		                (level_set[i_index+1][j_index  ][k_index  ]*current_level_set_value>0)&&
		                (level_set[i_index  ][j_index-1][k_index  ]*current_level_set_value>0)&&
		                (level_set[i_index  ][j_index+1][k_index  ]*current_level_set_value>0)&&
		                (level_set[i_index  ][j_index  ][k_index+1]*current_level_set_value>0)&&
		                (level_set[i_index  ][j_index  ][k_index-1]*current_level_set_value>0)
                                )
			    &&
			    
			/* is the volume of fluid at the same time in the OPEN interval <0,1>? */
                        
		                (current_volume_of_fluid_value<(1.0-volume_of_fluid_tolerance) &&
			                current_volume_of_fluid_value>(0.0+volume_of_fluid_tolerance))
		           )
		        {
                           
		    /* then the cell is a vapour cell, and the volume_of_fluid_correction is not correct yet */
		    /* additional iterations are required */
		    /* update the number of vapour cells */
		    
			        number_cells_numerical_vapor++;
			        adapt_vof_value=1;
                                invalid_vof_cells[i_index][j_index][k_index]=5.0;
                     
		        }
		        if( (current_volume_of_fluid_value> 1.0+volume_of_fluid_tolerance)||
			    (current_volume_of_fluid_value < 0.0-volume_of_fluid_tolerance))
		        {
                               
		        /* the volume of fluid value is out of bounds */
		        /* additional iterations are required */
		        /* update the number of out of bounds cells */
			  
			        number_cells_vof_out_of_bounds++;
			        adapt_vof_value=1;
                          
                                if(current_volume_of_fluid_value> 1.0+volume_of_fluid_tolerance)
                                {
                                        invalid_vof_cells[i_index][j_index][k_index]=1.0;
                                }
                                else
                                {
                                        invalid_vof_cells[i_index][j_index][k_index]=-1.0;
                                }
                       
		        }  
		        if(adapt_vof_value)
		        {
                               
		        /* cell is either a vapour cell or an over/under filled cell   */
		        /* the correct value shoul be either 1/0 depending on the sign */
		        /* of the level-set field                                      */
                      
			        correct_vof_value=0.5+sign(0.5,current_level_set_value);
			        if(current_level_set_value==0.0)
			        {
                            
		      /* this is not really very likely to happen but still */

                                        correct_vof_value=0.5;
			        }
			
			        volume_of_fluid_correction[i_index][j_index][k_index]=
			                        volume_of_fluid[i_index][j_index][k_index]-correct_vof_value;
			        volume_of_fluid[i_index][j_index][k_index]=correct_vof_value;
				      
		        }
		  } 
  
	      }  
     
	  } 
	  
	  number_cells_invalid_volume_of_fluid=number_cells_numerical_vapor+number_cells_vof_out_of_bounds;
          
          /* for debugging mode show detailed output */
          
          if(detailed_output)
          {
                dump_redistribution_for_debugging(level_set, volume_of_fluid,        
                                                    level_set, invalid_vof_cells, volume_of_fluid_correction,          
                                                      number_primary_cells_i, number_primary_cells_j, number_primary_cells_k,                    
                                                        mesh_width_x1, mesh_width_x2, mesh_width_x3, 1 );
                for(i_index=1;i_index<number_primary_cells_i+1;i_index++)
                {
                        for(j_index=1;j_index<number_primary_cells_j+1;j_index++)
                        {
                                for(k_index=1;k_index<number_primary_cells_k+1;k_index++)
                                {
                                        if( fabs(invalid_vof_cells[i_index][j_index][k_index]-5.0)<0.0001) 
                                        {
                                                std::cerr.setf(std::ios::scientific);
                                                std::cerr<<" this is vapour cell "<< i_index <<" "<< j_index <<" "<<k_index <<" "<<level_set[i_index][j_index][k_index]<<" "<<volume_of_fluid[i_index][j_index][k_index] <<"\n";
                                                std::cerr<<"with neighbours:        level-set               vof   \n";
                                                std::cerr<<" [i_index+1][j_index  ][k_index  ] "<<level_set[i_index+1][j_index  ][k_index  ]<< " "<<volume_of_fluid[i_index+1][j_index  ][k_index  ]<<"\n"; 
                                                std::cerr<<" [i_index-1][j_index  ][k_index  ] "<<level_set[i_index-1][j_index  ][k_index  ]<< " "<<volume_of_fluid[i_index-1][j_index  ][k_index  ]<<"\n"; 
                                                std::cerr<<" [i_index  ][j_index+1][k_index  ] "<<level_set[i_index  ][j_index+1][k_index  ]<< " "<<volume_of_fluid[i_index  ][j_index+1][k_index  ]<<"\n"; 
                                                std::cerr<<" [i_index  ][j_index-1][k_index  ] "<<level_set[i_index  ][j_index-1][k_index  ]<< " "<<volume_of_fluid[i_index  ][j_index+1][k_index  ]<<"\n"; 
                                                std::cerr<<" [i_index  ][j_index  ][k_index+1] "<<level_set[i_index  ][j_index  ][k_index+1]<< " "<<volume_of_fluid[i_index  ][j_index  ][k_index+1]<<"\n"; 
                                                std::cerr<<" [i_index  ][j_index  ][k_index-1] "<<level_set[i_index  ][j_index  ][k_index-1]<< " "<<volume_of_fluid[i_index  ][j_index  ][k_index+1]<<"\n"; 
                                        
                                        }
                                } 
  
                        }  
     
                } 
          }
          
	  return number_cells_invalid_volume_of_fluid;
    }
Ejemplo n.º 4
0
int main()
{
      Array3<double> level_set;				// level-set field
      Array3<double> pressure;				// pressure field
      Array3<double> u_1_velocity_old;			// velocity field at old time level x1 direction
      Array3<double> u_2_velocity_old;			// velocity field at old time level x2 direction
      Array3<double> u_3_velocity_old;			// velocity field at old time level x3 direction
      Array3<double> u_1_velocity_new;			// velocity field at new time level x1 direction
      Array3<double> u_2_velocity_new;			// velocity field at new time level x2 direction
      Array3<double> u_3_velocity_new;			// velocity field at new time level x3 direction
      Array3<double> momentum_source_term_u_1;		// source term of the momentum equation in x1 direction
					       		// defined on all u1 points (including boundaries)
      Array3<double> momentum_source_term_u_2;		// source term of the momentum equation in x2 direction
					        	// defined on all u1 points (including boundaries)
      Array3<double> momentum_source_term_u_3;		// source term of the momentum equation in x3 direction
					        	// defined on all u1 points (including boundaries)
      Array3<double> surface_tension_body_force_x1;	// source term of the momentum equation in x1 direction
					        	// defined on all u1 points (including boundaries)
      Array3<double> surface_tension_body_force_x2;	// source term of the momentum equation in x2 direction
					        	// defined on all u1 points (including boundaries)
      Array3<double> surface_tension_body_force_x3;	// source term of the momentum equation in x3 direction
					        	// defined on all u1 points (including boundaries)
      Array3<double> scaled_density_u1;			// scaled density for the controlvolumes
							// of the momentum equation in x1 direction
      Array3<double> scaled_density_u2;			// scaled density for the controlvolumes
							// of the momentum equation in x2 direction
      Array3<double> scaled_density_u3;			// scaled density for the controlvolumes
							// of the momentum equation in x3 direction
      boundary_face boundary_faces[6];		// array with all the information
							// for the boundary conditions 
      double mesh_width_x1;				// grid spacing in x1 direction (uniform)
      double mesh_width_x2;				// grid spacing in x2 direction (uniform)
      double mesh_width_x3;				// grid spacing in x3 direction (uniform)
      int number_primary_cells_i;			// number of primary (pressure) cells in x1 direction
      int number_primary_cells_j;			// number of primary (pressure) cells in x2 direction
      int number_primary_cells_k;			// number of primary (pressure) cells in x3 direction
      int number_matrix_connections = 7;			// number of connections in momentum matrix				       
      vector gravity;					// gravitational acceleration vector 
      double actual_time_step_navier_stokes;	// time step used for level-set advection
							// computed from all stability restrictions and 
							// possibly subscycling
      double rho_plus_over_rho_minus;		// ratio of the densities of the two phases
      double smoothing_distance_factor;		// the smoothing distance is smoothing_distance_factor
							// times the smallest mesh width
      double rho_minus_over_mu_minus;		// this was the 'Reynolds' number
							// in the original implementation of Sander
      double mu_plus_over_mu_minus;			// ratio of the viscosities of both phases
      double tolerance_pressure = 1e-8;	  		// the tolerance with which the system for the pressure is solved	
      int maximum_iterations_allowed_pressure=1e3;	// maximum number of iterations allowed for the
							// conjugate gradient method
      double tolerance_velocity=1e-7;	  		// the tolerance with which the system for the momentum predictor is solved	
      int maximum_iterations_allowed_velocity=1e2;	// maximum number of iterations allowed for the
							// conjugate gradient method
      int continuous_surface_force_model = 1;       	// =1, the continuous surface force model is applied
					        	// =0, the exact interface boundary conditions are applied
      int source_terms_in_momentum_predictor =1;   	// =1, the source terms are applied in the momentum predictor
					        	// equation
					        	// =0, the source terms are applied in the momentum corrector
					        	// equation
      vector initial_velocity;				// some initial velocity to fill the arrays


int i, j, k;  		// local variables for loop indexing
double x,y,z;		// coordinates
double x_length = 1;
double y_length = 2;
double z_length = 3; 

      double a,b,c,d,e,f,g,h,l,m,n,o,p,q,r,s,t,u;  // input coefficients
      
      double u_1, u_2, u_3; 
      double viscosity_over_density;
      double output_polynomial; 
      double scaled_density_constant = 1; 

      initial_velocity.u1 = 0.0;
      initial_velocity.u2 = 0.0;
      initial_velocity.u3 = 0.0;
 
      smoothing_distance_factor = 2; 
      rho_plus_over_rho_minus = 10.0;
      rho_minus_over_mu_minus = 1e20;
      mu_plus_over_mu_minus = 1; 
      
      
      gravity.u1 = 00.0;
      gravity.u2 = 00.0;
      gravity.u3 = 00.0;
 	
	actual_time_step_navier_stokes = 0.1; 

set_boundary_conditions(boundary_faces, initial_velocity); 
//	set_boundary_conditions(boundary_face[6], initial_velocity);
	
      number_primary_cells_i = pow(2,1); 
      number_primary_cells_j = pow(2,2); 
      number_primary_cells_k = pow(2,2); 

      	mesh_width_x1 = x_length/number_primary_cells_i; 
	mesh_width_x2 = y_length/number_primary_cells_j; 
	mesh_width_x3 = z_length/number_primary_cells_k; 

viscosity_over_density = (1/scaled_density_constant)*compute_scaled_viscosity(100,mesh_width_x1,mesh_width_x2,mesh_width_x3, smoothing_distance_factor, rho_minus_over_mu_minus,mu_plus_over_mu_minus);
      
      level_set.create(number_primary_cells_i+2,number_primary_cells_j+2,number_primary_cells_k+2);
      set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+2, 
			    number_primary_cells_k+2, level_set, 0.1);

      pressure.create(number_primary_cells_i+2, number_primary_cells_j+2, number_primary_cells_k+2);
      set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+2, 
			    number_primary_cells_k+2, pressure, 10000.0);
	// velocity old
      u_1_velocity_old.create(number_primary_cells_i+1, number_primary_cells_j+2, number_primary_cells_k+2);
      u_2_velocity_old.create(number_primary_cells_i+2, number_primary_cells_j+1, number_primary_cells_k+2);
      u_3_velocity_old.create(number_primary_cells_i+2, number_primary_cells_j+2, number_primary_cells_k+1);
      set_constant_matrix2(number_primary_cells_i+1, number_primary_cells_j+2,
			    number_primary_cells_k+2, u_1_velocity_old, initial_velocity.u1);
      set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+1, 
			    number_primary_cells_k+2, u_2_velocity_old, initial_velocity.u2);
      set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+2, 
			    number_primary_cells_k+1, u_3_velocity_old, initial_velocity.u3);


// multiple input sets of parameters
//	a=1;	b=2;	c=3;	d=4;	e=5;	f=6;	g=7;	h=8;	l=9;	m=1;	n=2;	o=3;	p=4; 	q=5; 	r=6;	s=7;	t=8;	u=9; // full test
	a=0;	b=0;	c=3;	d=4;	e=5;	f=6;	g=7;	h=8;	l=0;	m=0;	n=-3;	o=3;	p=4; 	q=5; 	r=6;	s=7;	t=0;	u=0; // divergence free velocity input b+m+n = 0
//	a=0;	b=2;	c=0;	d=4;	e=0;	f=6;	g=0;	h=8;	l=0;	m=1;	n=0;	o=3;	p=0; 	q=5; 	r=0;	s=7;	t=0;	u=9; // linear test
//	a=0;	b=0;	c=0;	d=0;	e=0;	f=0;	g=0;	h=1;	l=0;	m=0;	n=0;	o=0;	p=0; 	q=0; 	r=0;	s=0;	t=0;	u=0; // random test
//	a=0;	b=1;	c=0;	d=0;	e=0;	f=0;	g=0;	h=0;	l=0;	m=0;	n=0;	o=0;	p=0; 	q=0; 	r=0;	s=0;	t=0;	u=0; // random test

//	a=1;	b=2;	c=3;	d=4;	e=5;	f=6;	g=7;	h=8;	l=9;	m=1;	n=2;	o=3;	p=4; 	q=5; 	r=6;	s=7;	t=8;	u=9;  // test for diffusion, only quadratic terms

  for(i=0;i<number_primary_cells_i+2;i++)
  {
     for(j=0;j<number_primary_cells_j+2;j++)
      {
	  for(k=0;k<number_primary_cells_k+2;k++)
	  {
	  x = x_length * i/number_primary_cells_i -0.5*mesh_width_x1;
//	  printf("x = %f \n",x);
	  y = y_length * j/number_primary_cells_j -0.5*mesh_width_x2;
//	  printf("y = %f \n",y);
	  z = z_length * k/number_primary_cells_k -0.5*mesh_width_x3;
	  
	  if(i!=number_primary_cells_i+1)
	  	{x += 0.5*mesh_width_x1;
//	  	printf("x = %f \t",x);
	  	u_1_velocity_old[i][j][k]= a*x*x+b*x 	+c*y*y+d*y	+e*z*z+f*z; 	// 1st test
//	  	u_1_velocity_old[i][j][k]= a*x*x+b*y*y+c*z*z 	+d*x*y+e*x*z +f*y*z; 	// 2nd test, only quadratic terms 
//	  	printf("u_1 = %f \n", u_1_velocity_old[i][j][k]);
	  	x -= 0.5*mesh_width_x1;}
	  if(j!=number_primary_cells_j+1)
	  	{y += 0.5*mesh_width_x2;
	  	u_2_velocity_old[i][j][k]= g*x*x+h*x 	+l*y*y+m*y	+n*z*z+o*z; 	// 1st test
//	  	u_2_velocity_old[i][j][k]= g*x*x+h*y*y+l*z*z 	+m*x*y+n*x*z +o*y*z; 	// 2nd test, only quadratic terms 	  	
	  	y -= 0.5*mesh_width_x2;}
	  if(k!=number_primary_cells_k+1)
	  	{z += 0.5*mesh_width_x3;
	  	u_3_velocity_old[i][j][k]= p*x*x+q*x 	+r*y*y+s*y	+t*z*z+u*z;	// 1st test
//	  	u_3_velocity_old[i][j][k]= p*x*x+q*y*y+r*z*z 	+s*x*y+t*x*z +u*y*z; 	// 2nd test, only quadratic terms 
	  	z -= 0.5*mesh_width_x3;}
	  }  
  
      }  
     
  } 


	// velocity new
      u_1_velocity_new.create(number_primary_cells_i+1, number_primary_cells_j+2, number_primary_cells_k+2);
      u_2_velocity_new.create(number_primary_cells_i+2, number_primary_cells_j+1, number_primary_cells_k+2);
      u_3_velocity_new.create(number_primary_cells_i+2, number_primary_cells_j+2, number_primary_cells_k+1);
      set_constant_matrix2(number_primary_cells_i+1, number_primary_cells_j+2,
			    number_primary_cells_k+2, u_1_velocity_new, initial_velocity.u1);
      set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+1, 
			    number_primary_cells_k+2, u_2_velocity_new, initial_velocity.u2);
      set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+2, 
			    number_primary_cells_k+1, u_3_velocity_new, initial_velocity.u3);

	// momentum source terms
      momentum_source_term_u_1.create(number_primary_cells_i+1, number_primary_cells_j+2, number_primary_cells_k+2);
      momentum_source_term_u_2.create(number_primary_cells_i+2, number_primary_cells_j+1, number_primary_cells_k+2);
      momentum_source_term_u_3.create(number_primary_cells_i+2, number_primary_cells_j+2, number_primary_cells_k+1);
      set_constant_matrix2(number_primary_cells_i+1, number_primary_cells_j+2,
			    number_primary_cells_k+2, momentum_source_term_u_1, 0.0);
      set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+1, 
			    number_primary_cells_k+2, momentum_source_term_u_2, 0.0);
      set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+2, 
			    number_primary_cells_k+1, momentum_source_term_u_3, 0.0);
			    
	// surface_tension_body_force      
      surface_tension_body_force_x1.create(number_primary_cells_i+1, number_primary_cells_j+2, number_primary_cells_k+2);
      surface_tension_body_force_x2.create(number_primary_cells_i+2, number_primary_cells_j+1, number_primary_cells_k+2);
      surface_tension_body_force_x3.create(number_primary_cells_i+2, number_primary_cells_j+2, number_primary_cells_k+1);
      set_constant_matrix2(number_primary_cells_i+1, number_primary_cells_j+2,
			    number_primary_cells_k+2, surface_tension_body_force_x1, 0);
      set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+1, 
			    number_primary_cells_k+2, surface_tension_body_force_x2, 0);
      set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+2, 
			    number_primary_cells_k+1, surface_tension_body_force_x3, 0);			    			    			    



	// scaled density
      scaled_density_u1.create(number_primary_cells_i+1, number_primary_cells_j+2, number_primary_cells_k+2);
      scaled_density_u2.create(number_primary_cells_i+2, number_primary_cells_j+1, number_primary_cells_k+2);
      scaled_density_u3.create(number_primary_cells_i+2, number_primary_cells_j+2, number_primary_cells_k+1);
      set_constant_matrix2(number_primary_cells_i+1, number_primary_cells_j+2,
			    number_primary_cells_k+2, scaled_density_u1, 1);
      set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+1, 
			    number_primary_cells_k+2, scaled_density_u2, 1);
      set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+2, 
			    number_primary_cells_k+1, scaled_density_u3, 1);

 	
	advance_flow_field(level_set, pressure,
                       u_1_velocity_old, u_2_velocity_old, u_3_velocity_old,
                         u_1_velocity_new, u_2_velocity_new, u_3_velocity_new,
                           momentum_source_term_u_1, momentum_source_term_u_2, momentum_source_term_u_3,
                            surface_tension_body_force_x1, surface_tension_body_force_x2, surface_tension_body_force_x3,
                             scaled_density_u1, scaled_density_u2, scaled_density_u3,
                              boundary_faces,
                                mesh_width_x1, mesh_width_x2, mesh_width_x3,
                                  number_primary_cells_i, number_primary_cells_j, number_primary_cells_k,
                                   number_matrix_connections, gravity,
                                     actual_time_step_navier_stokes,
                                       rho_plus_over_rho_minus,
                                         smoothing_distance_factor,
                                          rho_minus_over_mu_minus, mu_plus_over_mu_minus,
                                           tolerance_pressure, maximum_iterations_allowed_pressure,
                                             tolerance_velocity, maximum_iterations_allowed_velocity,
                                                continuous_surface_force_model,
                                                 source_terms_in_momentum_predictor
	);
	
	
// check for u,v,w momentum 
for(i=1;i<number_primary_cells_i+1;i++)
{
  for(j=1;j<number_primary_cells_j+1;j++)
  {
      for(k=1;k<number_primary_cells_k+1;k++)
      {
	  x = x_length * i/number_primary_cells_i -0.5*mesh_width_x1;
	  y = y_length * j/number_primary_cells_j -0.5*mesh_width_x2;
	  z = z_length * k/number_primary_cells_k -0.5*mesh_width_x3;
	
	printf("\n i=%i j=%i k=%i \n", i,j,k);


	if(i!=number_primary_cells_i){
		x += 0.5*mesh_width_x1;
		u_1 = a*x*x+b*x 	+c*y*y+d*y	+e*z*z+f*z;
		u_2 = g*x*x+h*x 	+l*y*y+m*y	+n*z*z+o*z;
		u_3 = p*x*x+q*x 	+r*y*y+s*y	+t*z*z+u*z;
		output_polynomial = 2*u_1*(2*a*x+b) + u_1*(2*y*l+m) + u_2*(2*y*c+d) + u_1*(2*z*t+u) + u_3*(2*z*e+f)	+viscosity_over_density*(2*2*a+2*c+2*e); // 1st test
//		output_polynomial = viscosity_over_density*(4*a+2*b+m+2*c+t); // 2nd test, only quadratic terms 
		x -= 0.5*mesh_width_x1;
		printf("\n u_1_velocity_old = %f \n", u_1);		
		printf("u_1_velocity_new = %f \n", u_1_velocity_new[i][j][k]);		
		printf("new - old = %f \n", u_1_velocity_new[i][j][k]-u_1);			
		printf("polynomial   = %f \n", output_polynomial);
	}	
	
	if(j!=number_primary_cells_j){
		y += 0.5*mesh_width_x2;
		u_1 = a*x*x+b*x 	+c*y*y+d*y	+e*z*z+f*z;
		u_2 = g*x*x+h*x 	+l*y*y+m*y	+n*z*z+o*z;
		u_3 = p*x*x+q*x 	+r*y*y+s*y	+t*z*z+u*z;
		output_polynomial = u_1*(2*x*g+h)+u_2*(2*x*a+b) + 2*u_2*(2*y*l+m) + u_3*(2*z*n+o)+u_2*(2*z*t+u)		+viscosity_over_density*(2*2*l+2*g+2*n); // 1st test
//		output_polynomial = viscosity_over_density*(4*h+2*g+d+2*l+u); // 2nd test, only quadratic terms 
		y -= 0.5*mesh_width_x2;
		printf(" \n u_2_velocity_old = %f \n", u_2);		
		printf("u_2_velocity_new = %f \n", u_2_velocity_new[i][j][k]);		
		printf("new - old = %f \n", u_2_velocity_new[i][j][k]-u_2);			
		printf("polynomial   = %f \n", output_polynomial);	
	}	
	if(k!=number_primary_cells_k){
		z += 0.5*mesh_width_x3;
		u_1 = a*x*x+b*x 	+c*y*y+d*y	+e*z*z+f*z;
		u_2 = g*x*x+h*x 	+l*y*y+m*y	+n*z*z+o*z;
		u_3 = p*x*x+q*x 	+r*y*y+s*y	+t*z*z+u*z;
		output_polynomial = u_1*(2*x*p+q)+u_3*(2*x*a+b) + u_2*(2*y*r+s)+u_3*(2*y*l+m) + 2*u_3*(2*z*t+u)		+viscosity_over_density*(2*2*t+2*p+2*r); // 1st test
//		output_polynomial = viscosity_over_density*(4*r+2*p+e+2*q+o); // 2nd test, only quadratic terms 
		z -= 0.5*mesh_width_x3;
		printf("\n u_3_velocity_old = %f \n", u_3);		
		printf("u_3_velocity_new = %f \n", u_3_velocity_new[i][j][k]);		
		printf("new - old = %f \n", u_3_velocity_new[i][j][k]-u_3);			
		printf("polynomial   = %f \n", output_polynomial);
	}
}}}


//		printf("u_1_velocity_new = %f \n", u_1_velocity_new[i][j][k]);
//		printf("u_2_velocity_old = %f \n", u_2_velocity_old[i][j][k]);
//		printf("u_2_velocity_new = %f \n", u_2_velocity_new[i][j][k]);
//		printf("u_3_velocity_old = %f \n", u_3_velocity_old[i][j][k]);
//		printf("u_3_velocity_new = %f \n", u_3_velocity_new[i][j][k]);
//		printf("pressure = %f \n", pressure[i][j][k]);
	

      printf("%s \n", "advance_flow_field_unit_test finish");

      return 0;
}
 EXPORT void solve_momentum_predictor_rk(
      Array3<double> u_1_velocity_star, 		// velocity field at star time level x1 direction
      Array3<double> u_2_velocity_star, 		// velocity field at star time level x2 direction
      Array3<double> u_3_velocity_star,			// velocity field at star time level x3 direction
      Array3<double> u_1_velocity_old, 			// velocity field at old time level x1 direction
      Array3<double> u_2_velocity_old, 			// velocity field at old time level x2 direction
      Array3<double> u_3_velocity_old,			// velocity field at old time level x3 direction
      Array3<double> scaled_density_u1,			// scaled density for the controlvolumes
      Array3<double> scaled_density_u2,			// scaled density for the controlvolumes
      Array3<double> scaled_density_u3,			// scaled density for the controlvolumes      
      
      Array3<double> momentum_source_term_u_1,		// source term of the momentum equation in x1 direction
					       		// defined on all u1 points (including boundaries)
      Array3<double> momentum_source_term_u_2,		// source term of the momentum equation in x2 direction
					        	// defined on all u1 points (including boundaries)
      Array3<double> momentum_source_term_u_3,		// source term of the momentum equation in x3 direction
					        	// defined on all u1 points (including boundaries)
      Array3<double> level_set, 			// level-set field
      double actual_time_step_navier_stokes,	        // time step used for level-set advection
							// computed from all stability restrictions and 
							// possibly subscycling
      int number_primary_cells_i,			// number of primary (pressure) cells in x1 direction
      int number_primary_cells_j,			// number of primary (pressure) cells in x2 direction
      int number_primary_cells_k,			// number of primary (pressure) cells in x3 direction
      double mesh_width_x1,				// grid spacing in x1 direction (uniform)
      double mesh_width_x2,				// grid spacing in x2 direction (uniform)
      double mesh_width_x3,				// grid spacing in x3 direction (uniform)
      double smoothing_distance_factor,			// the smoothing distance is smoothing_distance_factor
      double rho_plus_over_rho_minus,			// ratio of the densities of the two phases
      double rho_minus_over_mu_minus,			// this was the 'Reynolds' number
							// in the original implementation of Sander
      double mu_plus_over_mu_minus,			// ratio of the viscosities of both phases
      boundary_face boundary_faces[6],		        // array with all the information
							// for the boundary conditions 
      int source_terms_in_momentum_predictor,    	// =1, the source terms are applied in the momentum predictor
					        	// equation
					        	// =0, the source terms are applied in the momentum corrector
					        	// equation  
      double actual_time				// actual time 
       )

  {
	double sigma, zeta;
	double actual_time_in_RK;  		// actual time used to evaluate the boundary conditon
 
       Array3<double> u_1_old_con_diff; 	// contains the convection and diffusion terms of a previous RK-stage in the x1 direction
       Array3<double> u_2_old_con_diff; 	// contains the convection and diffusion terms of a previous RK-stage in the x2 direction
       Array3<double> u_3_old_con_diff;		// contains the convection and diffusion terms of a previous RK-stage in the x3 direction

      u_1_old_con_diff.create(number_primary_cells_i+1, number_primary_cells_j+2, number_primary_cells_k+2);
      u_2_old_con_diff.create(number_primary_cells_i+2, number_primary_cells_j+1, number_primary_cells_k+2);
      u_3_old_con_diff.create(number_primary_cells_i+2, number_primary_cells_j+2, number_primary_cells_k+1);	

      set_constant_matrix2(number_primary_cells_i+1, number_primary_cells_j+2, number_primary_cells_k+2, u_1_old_con_diff,  0.0);
      set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+1, number_primary_cells_k+2, u_2_old_con_diff,  0.0);
      set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+2, number_primary_cells_k+1, u_3_old_con_diff,  0.0);
      
       Array3<double> u_1_new_con_diff; 	// contains the convection and diffusion terms of a RK-stage in the x1 direction
       Array3<double> u_2_new_con_diff; 	// contains the convection and diffusion terms of a RK-stage in the x2 direction	
       Array3<double> u_3_new_con_diff;		// contains the convection and diffusion terms of a RK-stage in the x3 direction	

      u_1_new_con_diff.create(number_primary_cells_i+1, number_primary_cells_j+2, number_primary_cells_k+2);
      u_2_new_con_diff.create(number_primary_cells_i+2, number_primary_cells_j+1, number_primary_cells_k+2);
      u_3_new_con_diff.create(number_primary_cells_i+2, number_primary_cells_j+2, number_primary_cells_k+1);	

      set_constant_matrix2(number_primary_cells_i+1, number_primary_cells_j+2, number_primary_cells_k+2, u_1_new_con_diff,  0.0);
      set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+1, number_primary_cells_k+2, u_2_new_con_diff,  0.0);
      set_constant_matrix2(number_primary_cells_i+2, number_primary_cells_j+2, number_primary_cells_k+1, u_3_new_con_diff,  0.0);

	// first step Runge-Kutta
	sigma = 8.0/15.0; // parameter for new stage
	zeta  = 0.0; // parameter for previous stage
	actual_time_in_RK = actual_time+(sigma+zeta-1)*actual_time_step_navier_stokes;

      forward_euler(
	u_1_velocity_star,u_2_velocity_star,u_3_velocity_star,			
	u_1_new_con_diff,u_2_new_con_diff,u_3_new_con_diff,                      
	u_1_velocity_old,u_2_velocity_old,u_3_velocity_old,		
	u_1_old_con_diff,u_2_old_con_diff,u_3_old_con_diff,               
 	scaled_density_u1,scaled_density_u2,scaled_density_u3,			   
 	momentum_source_term_u_1,momentum_source_term_u_2,momentum_source_term_u_3,	
	level_set, actual_time_step_navier_stokes,	       
  	sigma,zeta,					
  	number_primary_cells_i,number_primary_cells_j,number_primary_cells_k,			
	mesh_width_x1,mesh_width_x2,mesh_width_x3,				
	smoothing_distance_factor,
 	rho_plus_over_rho_minus,rho_minus_over_mu_minus,mu_plus_over_mu_minus,			
 	boundary_faces, source_terms_in_momentum_predictor, 
 	actual_time_in_RK
 	);
       

	// second step Runge-Kutta
       Array3<double> u_1_velocity_star_star; 		// velocity field at star_star time level x1 direction   
       Array3<double> u_2_velocity_star_star; 		// velocity field at star_star time level x2 direction     
       Array3<double> u_3_velocity_star_star;		// velocity field at star_star time level x3 direction

    	/* allocate memory for tentative velocity field u star_star */
      u_1_velocity_star_star.create(number_primary_cells_i+1, number_primary_cells_j+2, number_primary_cells_k+2);
      u_2_velocity_star_star.create(number_primary_cells_i+2, number_primary_cells_j+1, number_primary_cells_k+2);
      u_3_velocity_star_star.create(number_primary_cells_i+2, number_primary_cells_j+2, number_primary_cells_k+1);

	sigma = 5.0/12.0; // parameter for new stage
	zeta  = -17.0/60.0; // parameter for previous stage
	actual_time_in_RK = actual_time_in_RK + (sigma+zeta)*actual_time_step_navier_stokes; 


		
      forward_euler(
	u_1_velocity_star_star,u_2_velocity_star_star,u_3_velocity_star_star,			
	u_1_new_con_diff,u_2_new_con_diff,u_3_new_con_diff,                      
	u_1_velocity_star,u_2_velocity_star,u_3_velocity_star,		
	u_1_old_con_diff,u_2_old_con_diff,u_3_old_con_diff,               
 	scaled_density_u1,scaled_density_u2,scaled_density_u3,			   
 	momentum_source_term_u_1,momentum_source_term_u_2,momentum_source_term_u_3,	
	level_set, actual_time_step_navier_stokes,	       
  	sigma,zeta,					
  	number_primary_cells_i,number_primary_cells_j,number_primary_cells_k,			
	mesh_width_x1,mesh_width_x2,mesh_width_x3,				
	smoothing_distance_factor,
 	rho_plus_over_rho_minus,rho_minus_over_mu_minus,mu_plus_over_mu_minus,			
 	boundary_faces, source_terms_in_momentum_predictor, 
 	actual_time_in_RK
       );

	// third step Runge-Kutta
	sigma = 3.0/4.0; // parameter for new stage
	zeta  = -5.0/12.0; // parameter for previous stage
	actual_time_in_RK = actual_time_in_RK + (sigma+zeta)*actual_time_step_navier_stokes; 

		
      forward_euler(
	u_1_velocity_star,u_2_velocity_star,u_3_velocity_star,		// u_star is reused to reduce the number of allocations it can also be seen as u_star_star_star	
	u_1_new_con_diff,u_2_new_con_diff,u_3_new_con_diff,                      
	u_1_velocity_star_star,u_2_velocity_star_star,u_3_velocity_star_star,		
	u_1_old_con_diff,u_2_old_con_diff,u_3_old_con_diff,               
 	scaled_density_u1,scaled_density_u2,scaled_density_u3,			   
 	momentum_source_term_u_1,momentum_source_term_u_2,momentum_source_term_u_3,	
	level_set, actual_time_step_navier_stokes,	       
  	sigma,zeta,					
  	number_primary_cells_i,number_primary_cells_j,number_primary_cells_k,			
	mesh_width_x1,mesh_width_x2,mesh_width_x3,				
	smoothing_distance_factor,
 	rho_plus_over_rho_minus,rho_minus_over_mu_minus,mu_plus_over_mu_minus,			
 	boundary_faces, source_terms_in_momentum_predictor, 
 	actual_time_in_RK
       );


	u_1_old_con_diff.destroy();
	u_2_old_con_diff.destroy();
	u_3_old_con_diff.destroy();
	
	u_1_new_con_diff.destroy();
	u_2_new_con_diff.destroy();
	u_3_new_con_diff.destroy();

	u_1_velocity_star_star.destroy();
	u_2_velocity_star_star.destroy();
	u_3_velocity_star_star.destroy();

  }