/** Spring force with a directional force to align with flow direction. */ static const Vector edge_force(const Vector& dir, const Vector& hpos, const Vector& tpos) { return vec_add(dir, spring_force(hpos, tpos, EDGE_LEN, EDGE_K)); }
void get_forces(struct chain_param *chain_pm, struct monomer *monomers, Float ***velcs_df, int n_step, VSLStreamStatePtr rngstream) { extern int n_proc, num_proc; extern int num_x; extern int max_x, max_y, max_z; extern int wall_flag; int mon_proc; int num_beads, Nbead; int i, j; int n1, n2; int s_type = 1; /* spring type : 0 = FENE, 1=WLC */ int ev_type = 1; /* ev type: 0=HS, 1=WCA, 2=Gaussian */ int maxsize[DIMS]; int max_N_flag=0; double send_buffer[2*DIMS+1]; char filename[80]; FILE *stream; maxsize[0]=max_x; maxsize[1]=max_y; maxsize[2]=max_z; num_beads = chain_pm->num_beads; Nbead = chain_pm->num_beads / chain_pm->Nchain; for(j=0; j<DIMS; j++) monomers[0].force[j] = monomers[0].f_ext[j]; for(n1=1; n1<num_beads; n1++) for(j=0; j<DIMS; j++) monomers[n1].force[j] = 0.0; /* Calculate spring and exc. vol. forces if # of beads > 1 */ if(num_beads > 1) { spring_force(chain_pm, monomers); /* 0 = FENE, 1=WLC */ /*excluded volume forces */ if(num_beads < 200) ev_force(monomers[0].radius, chain_pm, monomers); else { for(n1=0; n1<num_beads; n1++) if(monomers[n1].list[0] >= MAX_N-1) max_N_flag = 1; if(max_N_flag == 1) ev_force(monomers[0].radius, chain_pm, monomers); else ev_force_nlist(monomers[0].radius, chain_pm, monomers); } } for(n1=0; n1<num_beads; n1++) for(j=0; j<DIMS; j++) { monomers[n1].force[j] *= chain_pm->monmass; monomers[n1].f_int[j] = monomers[n1].force[j]; } /*hydrodynamic and fluctuation forces */ hi_force(monomers, velcs_df, chain_pm->fric, chain_pm->MD_steps, chain_pm->dt, num_beads, chain_pm->monmass, rngstream); if(wall_flag > 0) wall_force(chain_pm, monomers); /* send forces and fluid_vel back to proc 0 then broadcast from 0 */ for(n1=0; n1< num_beads; n1++) { mon_proc = (int)(monomers[n1].pos[0]/num_x); send_buffer[0]=n1; for(i=0; i<DIMS; i++) { send_buffer[i+1]=monomers[n1].force[i]; send_buffer[i+DIMS+1]=monomers[n1].fluid_vel[i]; } vector_copy(send_buffer, 2*DIMS+1, n_proc, mon_proc, 0); for(i=0; i<DIMS; i++) { monomers[(int)send_buffer[0]].force[i]=send_buffer[i+1]; monomers[(int)send_buffer[0]].fluid_vel[i]=send_buffer[i+1+DIMS]; } } sync_procs(); for(n1=0; n1< num_beads; n1++) { broad_cast(monomers[n1].force, DIMS, 0); broad_cast(monomers[n1].fluid_vel, DIMS, 0); } }
void settle_sheet( tectonic_sheet *ts, size_t iterations, float dt, float equilibrium_distance, float spring_constant, int hold_edges ) { size_t iter, i, j; size_t idx, idx_a, idx_b, idx_c; size_t pw, ph; pw = sheet_pwidth(ts); ph = sheet_pheight(ts); vector *a, *b, *c; // the points of the current triangle vector *f; // the force on the current point vector tmp; // vector used for intermediate calculations for (iter = 0; iter < iterations; ++iter) { // First pass: compute forces by iterating over triangles in the sheet: for (i = 0; i < ts->width; ++i) { for (j = 0; j < ts->height; ++j) { idx_a = sheet_pidx_a(ts, i, j); idx_b = sheet_pidx_b(ts, i, j); idx_c = sheet_pidx_c(ts, i, j); a = &(ts->points[idx_a]); b = &(ts->points[idx_b]); c = &(ts->points[idx_c]); if (i % 2 == j % 2) { // if this triangle points up // All six forces on all three corners of this triangle: // a <- b f = &(ts->forces[idx_a]); spring_force(b, a, &tmp, equilibrium_distance, spring_constant); vadd_to(f, &tmp); // a <- c spring_force(c, a, &tmp, equilibrium_distance, spring_constant); vadd_to(f, &tmp); // b <- a f = &(ts->forces[idx_b]); spring_force(a, b, &tmp, equilibrium_distance, spring_constant); vadd_to(f, &tmp); // b <- c spring_force(c, b, &tmp, equilibrium_distance, spring_constant); vadd_to(f, &tmp); // c <- a f = &(ts->forces[idx_c]); spring_force(a, c, &tmp, equilibrium_distance, spring_constant); vadd_to(f, &tmp); // c <- b spring_force(b, c, &tmp, equilibrium_distance, spring_constant); vadd_to(f, &tmp); } else if (i == 0 && (j % 2 == 1)) { // Both forces on our a <-> b edge: // a <- b f = &(ts->forces[idx_a]); spring_force(b, a, &tmp, equilibrium_distance, spring_constant); vadd_to(f, &tmp); // b <- a f = &(ts->forces[idx_b]); spring_force(a, b, &tmp, equilibrium_distance, spring_constant); vadd_to(f, &tmp); } else if ((i == ts->width - 1) && (j % 2 == 0) ) { // Both forces on our a <-> c edge: // a <- c f = &(ts->forces[idx_a]); spring_force(c, a, &tmp, equilibrium_distance, spring_constant); vadd_to(f, &tmp); // c <- a f = &(ts->forces[idx_c]); spring_force(a, c, &tmp, equilibrium_distance, spring_constant); vadd_to(f, &tmp); } } } // Second pass: apply forces (iterating over points this time) for (i = 0; i < pw; ++i) { for (j = 0; j < ph; ++j) { idx = sheet_pidx(ts, i, j); f = &(ts->forces[idx]); if ( hold_edges && (i == 0 || i == pw - 1 || j == 0 || j == ph - 1) ) { vzero(f); continue; } vscale(f, dt); vadd_to(&(ts->points[idx]), f); vzero(f); } } } }