/* finds the nearest stem cell */ struct distance_result distance_to_nearest_stem_cell(double x1, double y1, double z1) { /*double x2, y2, z2;*/ struct distance_result res; res.nearest_distance = -1.0; res.nearest_xy = -1.0; res.nearest_z = -1.0; location_message = get_first_location_message(); while(location_message) { double x2 = location_message->x; double y2 = location_message->y; double z2 = location_message->z; if (location_message->type == K_TYPE_STEM) { double distance_check = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2)); if (res.nearest_distance == -1.0 || distance_check < res.nearest_distance) { res.nearest_distance = distance_check; res.nearest_xy = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)); res.nearest_z = fabs(z1-z2); } } location_message = get_next_location_message(location_message); } return res; }
__FLAME_GPU_FUNC__ int inputdata(xmachine_memory_Circle* xmemory, xmachine_message_location_list* location_messages, xmachine_message_location_PBM* partition_matrix) { float x1, y1, z1, x2, y2, z2, fx, fy, fz, toLocX, toLocY, toLocZ; float separation; float k; x1 = xmemory->x; fx = 0.0; y1 = xmemory->y; fy = 0.0; z1 = xmemory->z; fz = 0.0; // Loop through all messages xmachine_message_location* location_message = get_first_location_message(location_messages, partition_matrix, (float)xmemory->x, (float)xmemory->y, (float)xmemory->z); while(location_message) { if((location_message->id != xmemory->id)) { x2 = location_message->x; y2 = location_message->y; z2 = location_message->z; toLocX = x2-x1; toLocY = y2-y1; toLocZ = z2-z1; if(toLocX!=0.0f||toLocY!=0.0f||toLocZ!=0.0f) { // Deep (expensive) check separation = sqrt(toLocX*toLocX + toLocY*toLocY + toLocZ*toLocZ); if(separation < INTERACTION_RADIUS2) { k = (separation < INTERACTION_RADIUS) ? REPULSION_FORCE : ATTRACTION_FORCE; toLocX = (separation < INTERACTION_RADIUS) ? -toLocX : toLocX; toLocY = (separation < INTERACTION_RADIUS) ? -toLocY : toLocY; toLocZ = (separation < INTERACTION_RADIUS) ? -toLocZ : toLocZ; toLocX /= separation;//Normalize (without recalculating separation) toLocY /= separation;//Normalize (without recalculating separation) toLocZ /= separation;//Normalize (without recalculating separation) separation = (separation < INTERACTION_RADIUS) ? separation : (INTERACTION_RADIUS2 - separation); fx += k * separation * toLocX; fy += k * separation * toLocY; fz += k * separation * toLocZ; } } } //Move onto next message to check location_message = get_next_location_message(location_message, location_messages, partition_matrix); } xmemory->fx = fx; xmemory->fy = fy; xmemory->fz = fz; return 0; }
/** \fn inputdata() * \brief Read all messages from other agents */ int inputdata() { xmachine_memory_Circle * xmemory = current_xmachine->xmachine_Circle; double x1, y1, x2, y2; double deep_distance_check, separation_distance; double k; double eps=1.0e-15; xmemory->fx = 0.0; xmemory->fy = 0.0; x1 = xmemory->x; y1 = xmemory->y; /* Loop through all messages */ location_message = get_first_location_message(); while(location_message) { if((location_message->id != xmemory->id)) { x2 = location_message->x; y2 = location_message->y; /* Deep (expensive) check */ deep_distance_check = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)); separation_distance = (deep_distance_check - xmemory->radius - xmemory->radius); if(separation_distance < xmemory->radius) { if(separation_distance > 0.0) k = ka; else k = kr; if(fabs(deep_distance_check) >0){ xmemory->fx += k*(separation_distance)*((x2-x1)/deep_distance_check); xmemory->fy += k*(separation_distance)*((y2-y1)/deep_distance_check); } else { printf("Agents coincident!\n"); printf("sep dist=%f deep_dist=%f\n",separation_distance,deep_distance_check); xmemory->fx += k*rand()*eps; xmemory->fy += k*rand()*eps; printf("fx=%f fy=%f rand=%d\n",xmemory->fx,xmemory->fy,rand()); } } } /* Move onto next message to check */ location_message = get_next_location_message(location_message); } return 0; }
int migrate_start() { xmachine_memory_keratinocyte * xmemory = current_xmachine->xmachine_keratinocyte; /* these are the 'current' parameters*/ double x1, y1, dir1, motility1; /* these will be the 'new' parameters*/ double x2, y2, z2, dir2, motility2; /* only TAs and HACATs can move*/ if (get_type() == K_TYPE_TA || get_type() == K_TYPE_HACAT) { /* these are the 'current' parameters*/ x1 = get_x(); y1 = get_y(); dir1 = get_dir(); motility1 = get_motility(); /* if rnd less than 0.1, then changed direction within +/- 45 degrees*/ if (rnd() < 0.1) { dir1 += PI * rnd()/4.0; } x1 += motility1 * cos(dir1); y1 += motility1 * sin(dir1); /* check if we're about to bump into a stationary cell*/ location_message = get_first_location_message(); while(location_message) { x2 = location_message->x; y2 = location_message->y; z2 = location_message->z; dir2 = location_message->dir; motility2 = location_message->motility; /* check if we're on the base of the dish and other cell is stationary*/ if (on_substrate_surface(z2) && motility2 == 0) { /* find distance*/ double distance_check = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)); if (distance_check != 0 && distance_check < K_WIDTH) { dir1 -= PI; /* reverse direction*/ if (dir1 > 2 * PI) { dir1 -= 2 * PI; } x1 = get_x() + motility1 * cos(dir1); y1 = get_y() + motility1 * sin(dir1); } } location_message = get_next_location_message(location_message); } /* update memory with new parameters*/ set_x(x1); set_y(y1); set_dir(dir1); set_motility(motility1); /* check we've not gone over the edge of the dish!*/ /* if so, reverse direction*/ if (xmemory->x > substrate_width) { xmemory->x = substrate_width - xmemory->motility *rnd(); xmemory->dir = PI + PI * (rnd()-0.5)/4.0; } if (xmemory->x < 0) { xmemory->x = xmemory->motility *rnd(); xmemory->dir = PI * (rnd()-0.5)/4.0; } if (xmemory->y > substrate_width) { xmemory->y = substrate_width -xmemory->motility *rnd(); xmemory->dir = (3.0 * PI/2.0) + PI * (rnd()-0.5)/4.0; } if (xmemory->y < 0) { xmemory->y = xmemory->motility * rnd(); xmemory->dir = (PI/2.0) + PI * (rnd()-0.5)/4.0; } } add_location_unresolved_message(ID, TYPE, DIR, MOTILITY, 1000.0, X, Y, Z); return 0; }
int differentiate() { int num_stem_neighbours; double x1 = get_x(); double y1 = get_y(); double z1 = get_z(); if (get_type() == K_TYPE_STEM) { /* For stem cells, we check if the colony is too big and if they are on the edge.*/ /* If so, they differentiate into TA cells. */ if (on_colony_edge(get_num_stem_bonds())) { num_stem_neighbours = 0; location_message = get_first_location_message(); while(location_message) { double x2 = location_message->x; double y2 = location_message->y; double z2 = location_message->z; if (location_message->type == K_TYPE_STEM) { double distance_check = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2)); double max_distance = K_WIDTH * (get_max_stem_colony_size(calcium_level) / 2.0); if (distance_check < max_distance) { num_stem_neighbours++; } } location_message = get_next_location_message(location_message); } //printf("num_stem_neighbours = %d max_colony_size = %f \n", num_stem_neighbours, get_max_stem_colony_size(calcium_level)); if (num_stem_neighbours > get_max_stem_colony_size(calcium_level)) { set_type(K_TYPE_TA); } } //printf("num_stem_bonds = %d num_stem_neighbours = %d\n", get_num_stem_bonds(), num_stem_neighbours); /* If the cell stratifies, it also differentiates into a TA cell*/ if (!on_substrate_surface(get_z())) { set_type(K_TYPE_TA); } } else if (get_type() == K_TYPE_TA) { /* If the TA cell is too far from the stem cell centre, it differentiates into in a committed cell.*/ struct distance_result nearest = distance_to_nearest_stem_cell(get_x(), get_y(), get_z()); Boolean do_diff = check_distance(nearest, get_ta_to_comm_diff_major_axis(calcium_level), get_ta_to_comm_diff_minor_axis(calcium_level), get_diff_noise_factor()); if (do_diff) { set_type(K_TYPE_COMM); /* If it has been in G0 for a certain period, it also differentiates.*/ } else if (get_contact_inhibited_ticks() >= MAX_TO_G0_CONTACT_INHIBITED_TICKS) { set_type(K_TYPE_COMM); } } else if (get_type() == K_TYPE_COMM) { /* after a period as a committed cell, it dies for good - differentiation into a corneocyte*/ set_dead_ticks(get_dead_ticks()+1); if (get_dead_ticks() > MAX_DEAD_TICKS) { set_type(K_TYPE_CORN); } } else if (get_type() == K_TYPE_HACAT) { if (get_contact_inhibited_ticks() >= MAX_TO_G0_CONTACT_INHIBITED_TICKS) { set_type(K_TYPE_COMM); } } /* corneocytes also spread a 'death' signal - i.e. they can make cells around them differentiate*/ /* into corneocytes.*/ if (get_type() != K_TYPE_CORN) { int num_corn_neighbours = 0; double prob = 0; location_message = get_first_location_message(); while(location_message) { double x2 = location_message->x; double y2 = location_message->y; double z2 = location_message->z; if (location_message->type == K_TYPE_CORN) { double distance_check = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2)); if (distance_check != 0) { if (distance_check - K_WIDTH <= FORCE_IRADIUS) { num_corn_neighbours ++; } } } location_message = get_next_location_message(location_message); } prob = num_corn_neighbours * num_corn_neighbours * 0.01; if (rnd() < prob) { /* jump through another hoop*/ if (rnd() < 0.01) { set_type(K_TYPE_CORN); } } } return 0; }
/* push cells apart or attract them */ void resolve_forces(int iteration) { double x1 = get_x(); double y1 = get_y(); double z1 = get_z(); int type1 = get_type(); int num_xy_bonds = 0; int num_z_bonds = 0; int num_stem_bonds = 0; set_force_x(0.0); set_force_y(0.0); set_force_z(0.0); location_message = get_first_location_message(); while (location_message) { //if (location_message->iteration == iteration){ double x2 = location_message->x; double y2 = location_message->y; double z2 = location_message->z; int type2 = location_message->type; double distance_check = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2)); /*if (distance_check != 0.0)*/ if (distance_check > 0.001 ) { double force; double separation_distance = (distance_check - K_WIDTH); if (separation_distance <= FORCE_IRADIUS) { if (z2 >= z1) { if (z2 - z1 > (K_WIDTH/2)) { num_z_bonds ++; } else { num_xy_bonds ++; } } if (location_message->type == K_TYPE_STEM) { num_stem_bonds ++; } if (separation_distance > 0.0) { force = FORCE_MATRIX[type1][type2]; } else { force = FORCE_REP; } if (on_substrate_surface(z1)) { force *= DOWNWARD_FORCE[get_type()]; } force *= FORCE_DAMPENER; set_force_x(get_force_x() + force * (separation_distance)*((x2-x1)/distance_check)); set_force_y(get_force_y() + force * (separation_distance)*((y2-y1)/distance_check)); set_force_z(get_force_z() + force * (separation_distance)*((z2-z1)/distance_check)); } } //} location_message = get_next_location_message(location_message); } /* attraction force to substrate*/ if (z1 <= (K_WIDTH * 1.5)) { set_force_z(get_force_z() - SUBSTRATE_FORCE[type1]); } set_num_xy_bonds(num_xy_bonds); set_num_z_bonds(num_z_bonds); set_num_stem_bonds(num_stem_bonds); x1 += get_force_x(); y1 += get_force_y(); z1 += get_force_z(); if (x1 < 0) { x1 = 0; } if (y1 < 0) { y1 = 0; } if (z1 < 0) { z1 = 0; } if (x1 > substrate_width) { x1 = substrate_width; } if (y1 > substrate_width) { y1 = substrate_width; } set_x(x1); set_y(y1); set_z(z1); }