Exemplo n.º 1
0
void rebx_pre_timestep_modifications(struct reb_simulation* sim){
    struct rebx_extras* rebx = sim->extras;
    struct rebx_effect* current = rebx->effects;
    const double dt2 = sim->dt/2.;
    
    while(current != NULL){
        if(current->operator_order == 2){       // if order = 1, only apply post_timestep
            if(current->operator != NULL){      // Always apply operator if set
                if(sim->integrator==REB_INTEGRATOR_IAS15 && sim->ri_ias15.epsilon != 0){
                    reb_warning(sim, "REBOUNDx: Can't use second order scheme with adaptive timesteps (IAS15). Must use operator_order = 1 or apply as force to get sensible results.");
                }
                current->operator(sim, current, dt2, REBX_TIMING_PRE_TIMESTEP);
            }
            else{                               // It's a force: numerically integrate as operator if flag set
                if(current->force_as_operator == 1){
                    if(sim->integrator==REB_INTEGRATOR_IAS15 && sim->ri_ias15.epsilon != 0){
                        reb_warning(sim, "REBOUNDx: Can't use second order scheme with adaptive timesteps (IAS15). Must use operator_order = 1 or apply as force to get sensible results.");
                    }
                    rebx_integrate(sim, dt2, current);
                }
            }
        }
        current = current->next;
    }
}
Exemplo n.º 2
0
struct reb_simulation* reb_create_simulation_from_binary(char* filename){
    enum reb_input_binary_messages warnings = REB_INPUT_BINARY_WARNING_NONE;
    struct reb_simulation* r = reb_create_simulation_from_binary_with_messages(filename,&warnings);
    if (warnings & REB_INPUT_BINARY_WARNING_VERSION){
        reb_warning(r,"Binary file was saved with a different version of REBOUND. Binary format might have changed.");
    }
    if (warnings & REB_INPUT_BINARY_WARNING_PARTICLES){
        reb_warning(r,"Binary file might be corrupted. Number of particles found does not match expected number.");
    }
    if (warnings & REB_INPUT_BINARY_WARNING_VARCONFIG){
        reb_warning(r,"Binary file might be corrupted. Number of variational config structs found does not match number of variational config structs expected.");
    }
    if (warnings & REB_INPUT_BINARY_WARNING_POINTERS){
        reb_warning(r,"You have to reset function pointers after creating a reb_simulation struct with a binary file.");
    }
    if (warnings & REB_INPUT_BINARY_ERROR_NOFILE){
        reb_error(r,"Cannot read binary file. Check filename and file contents.");
    }
    return r;
}
Exemplo n.º 3
0
void rebx_additional_forces(struct reb_simulation* sim){
	struct rebx_extras* rebx = sim->extras;
	struct rebx_effect* current = rebx->effects;
	while(current != NULL){
        if(current->force != NULL && current->force_as_operator == 0){
            if(sim->force_is_velocity_dependent && sim->integrator==REB_INTEGRATOR_WHFAST){
                reb_warning(sim, "REBOUNDx: Passing a velocity-dependent force to WHFAST. Need to apply as an operator.");
            }
            const double N = sim->N - sim->N_var;
		    current->force(sim, current, sim->particles, N);
        }
		current = current->next;
	}
}
Exemplo n.º 4
0
void rebx_initialize(struct reb_simulation* sim, struct rebx_extras* rebx){
    sim->extras = rebx;
    rebx->sim = sim;
	rebx->params_to_be_freed = NULL;
	rebx->effects = NULL;
    rebx->integrator = REBX_INTEGRATOR_IMPLICIT_MIDPOINT;
    
    if(sim->additional_forces || sim->pre_timestep_modifications || sim->post_timestep_modifications){
        reb_warning(sim, "REBOUNDx overwrites sim->additional_forces, sim->pre_timestep_modifications and sim->post_timestep_modifications.  If you want to use REBOUNDx together with your own custom functions that use these callbacks, you should add them through REBOUNDx.  See https://github.com/dtamayo/reboundx/blob/master/ipython_examples/Custom_Effects.ipynb for a tutorial.");
    }
    // Have to set all the following at initialization since we can't know
    // which will be needed from added effects. User could set force_as_operator after the fact.
    sim->additional_forces = rebx_additional_forces;
    sim->pre_timestep_modifications = rebx_pre_timestep_modifications;
    sim->post_timestep_modifications = rebx_post_timestep_modifications;
}
Exemplo n.º 5
0
int reb_remove(struct reb_simulation* const r, int index, int keepSorted){
    if (r->ri_hermes.global){
        // This is a mini simulation. Need to remove particle from two simulations.
        struct reb_simulation* global = r->ri_hermes.global;
        
        //remove from global and update global arrays
        int global_index = global->ri_hermes.global_index_from_mini_index[index];
        reb_remove(global,global_index,1);
        
        //Shifting array values (filled with 0/1)
        for(int k=global_index;k<global->N;k++){
            global->ri_hermes.is_in_mini[k] = global->ri_hermes.is_in_mini[k+1];
        }
        
        //Shifting array values (filled with index values)
        global->ri_hermes.global_index_from_mini_index_N--;
        for(int k=index;k<global->ri_hermes.global_index_from_mini_index_N;k++){
            global->ri_hermes.global_index_from_mini_index[k] = global->ri_hermes.global_index_from_mini_index[k+1];
        }
        
        //Depreciating all index values larger than global_index
        for(int k=0;k<global->ri_hermes.global_index_from_mini_index_N;k++){
            if(global->ri_hermes.global_index_from_mini_index[k] > global_index){
                global->ri_hermes.global_index_from_mini_index[k]--;
            }
        }
    }
    if (r->integrator == REB_INTEGRATOR_MERCURIUS && r->ri_mercurius.mode==1){
        struct reb_simulation_integrator_mercurius* rim = &(r->ri_mercurius);
        struct reb_simulation_integrator_whfast* riw = &(r->ri_whfast);
        //remove from global and update global arrays
        int global_index = -1;
        int count = -1;
        for(int k=0;k<rim->globalN;k++){
            if (rim->encounterIndicies[k]){
                count++;
            }
            if (count==index){
                global_index = k;
                break;
            }
        }
        if (global_index==-1){
            reb_error(r, "Error finding particle in global simulation.");
        }
	    rim->globalN--;
        if(global_index<rim->globalNactive){
            rim->globalNactive--;
        }
		for(int j=global_index; j<rim->globalN; j++){
			rim->encounterParticles[j] = rim->encounterParticles[j+1];  // These are the global particles
			riw->p_jh[j] = riw->p_jh[j+1];
			rim->p_hold[j] = rim->p_hold[j+1];
			rim->encounterIndicies[j] = rim->encounterIndicies[j+1];
			rim->rhill[j] = rim->rhill[j+1];
		}
        // Update additional parameter for local 
		for(int j=index; j<r->N-1; j++){
			rim->encounterRhill[j] = rim->encounterRhill[j+1];
		}
    }
	if (r->N==1){
	    r->N = 0;
        if(r->free_particle_ap){
            r->free_particle_ap(&r->particles[index]);
        }
		reb_warning(r, "Last particle removed.");
		return 1;
	}
	if (index >= r->N){
		char warning[1024];
        sprintf(warning, "Index %d passed to particles_remove was out of range (N=%d).  Did not remove particle.", index, r->N);
		reb_error(r, warning);
		return 0;
	}
	if (r->N_var){
		reb_error(r, "Removing particles not supported when calculating MEGNO.  Did not remove particle.");
		return 0;
	}
	if(keepSorted){
	    r->N--;
        if(r->free_particle_ap){
            r->free_particle_ap(&r->particles[index]);
        }
        if(index<r->N_active){
            r->N_active--;
        }
		for(int j=index; j<r->N; j++){
			r->particles[j] = r->particles[j+1];
		}
        if (r->tree_root){
		    reb_error(r, "REBOUND cannot remove a particle a tree and keep the particles sorted. Did not remove particle.");
		    return 0;
        }
	}else{
        if (r->tree_root){
            // Just flag particle, will be removed in tree_update.
            r->particles[index].y = nan("");
            if(r->free_particle_ap){
                r->free_particle_ap(&r->particles[index]);
            }
        }else{
	        r->N--;
            if(r->free_particle_ap){
                r->free_particle_ap(&r->particles[index]);
            }
		    r->particles[index] = r->particles[r->N];
        }
	}

	return 1;
}
Exemplo n.º 6
0
static void reb_integrator_hermes_check_for_encounter(struct reb_simulation* global){
    struct reb_simulation* mini = global->ri_hermes.mini;
    const int _N_active = ((global->N_active==-1)?global->N:global->N_active) - global->N_var;
    struct reb_particle* global_particles = global->particles;
    struct reb_particle p0 = global_particles[0];
    double hill_switch_factor = global->ri_hermes.hill_switch_factor;
    double hill_switch_factor2 = hill_switch_factor*hill_switch_factor;
    double min_dt_enc2 = INFINITY;
    for (int i=0; i<_N_active; i++){
        struct reb_particle pi = global_particles[i];
        double radius_check = global->ri_hermes.radius_switch_factor*pi.r;
        double radius_check2 = radius_check*radius_check;
        const double dxi = p0.x - pi.x;
        const double dyi = p0.y - pi.y;
        const double dzi = p0.z - pi.z;
        const double r0i2 = dxi*dxi + dyi*dyi + dzi*dzi;
        const double mi = pi.m/(p0.m*3.);
        double rhi = pow(mi*mi*r0i2*r0i2*r0i2,1./6.);
        for(int j=i+1;j<global->N;j++){
            struct reb_particle pj = global_particles[j];
            
            const double dxj = p0.x - pj.x;
            const double dyj = p0.y - pj.y;
            const double dzj = p0.z - pj.z;
            const double r0j2 = dxj*dxj + dyj*dyj + dzj*dzj;
            const double mj = pj.m/(p0.m*3.);
            double rhj = pow(mj*mj*r0j2*r0j2*r0j2,1./6.);
            const double rh_sum = rhi+rhj;
            const double rh_sum2 = rh_sum*rh_sum;
            
            const double dx = pi.x - pj.x;
            const double dy = pi.y - pj.y;
            const double dz = pi.z - pj.z;
            const double rij2 = dx*dx + dy*dy + dz*dz;

            if(rij2 < hill_switch_factor2*rh_sum2 || rij2 < radius_check2){
                global->ri_hermes.mini_active = 1;
                // Monitor hill radius/relative velocity
                const double dvx = pi.vx - pj.vx;
                const double dvy = pi.vy - pj.vy;
                const double dvz = pi.vz - pj.vz;
                const double vij2 = dvx*dvx + dvy*dvy + dvz*dvz;
                const double dt_enc2 = hill_switch_factor2*rh_sum2/vij2;
                min_dt_enc2 = MIN(min_dt_enc2,dt_enc2);
                if (j>=_N_active && global->ri_hermes.is_in_mini[j]==0){//make sure not already added
                    // Add particle to mini simulation
                    reb_add(mini,pj);
                    global->ri_hermes.is_in_mini[j] = 1;
                    if (global->ri_hermes.global_index_from_mini_index_N>=global->ri_hermes.global_index_from_mini_index_Nmax){
                        while(global->ri_hermes.global_index_from_mini_index_N>=global->ri_hermes.global_index_from_mini_index_Nmax) global->ri_hermes.global_index_from_mini_index_Nmax += 32;
                        global->ri_hermes.global_index_from_mini_index = realloc(global->ri_hermes.global_index_from_mini_index,global->ri_hermes.global_index_from_mini_index_Nmax*sizeof(int));
                    }
                    global->ri_hermes.global_index_from_mini_index[global->ri_hermes.global_index_from_mini_index_N] = j;
                    global->ri_hermes.global_index_from_mini_index_N++;
                }
            }
        }
    }
    if (global->ri_hermes.timestep_too_large_warning==0 && min_dt_enc2 < 16.*global->dt*global->dt){
        global->ri_hermes.timestep_too_large_warning = 1;
        reb_warning(global,"The timestep is likely too large. Close encounters might be missed. Decrease the timestep or increase the switching radius. This warning will appear only once.");
    }
}