Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spatial messaging shrinks interaction radius to a factor of width, when not a factor #1157

Closed
Robadob opened this issue Dec 1, 2023 · 3 comments · Fixed by #1160
Closed
Labels

Comments

@Robadob
Copy link
Member

Robadob commented Dec 1, 2023

hd_data.gridDim[axis] = static_cast<unsigned int>(ceil(hd_data.environmentWidth[axis] / hd_data.radius));

Consider:
Width 105
Radius 10

This currently creates 11 bins.
Therefore the 11th bin would only be half occupied (covering 5 width, rather than 10).
Therefore any agents in the 10th bin, will only access the 11th bin and not wrap to the 1st bin.
Therefore missing out on messages in that direction, creating bias.

The solution would be to floor() rather than ceil() and accept that the 10th bin will be denser as it covers any overflow width.

@Robadob Robadob added the bug label Dec 1, 2023
@Robadob
Copy link
Member Author

Robadob commented Dec 1, 2023

False alarm, it works though I don't know why.

FLAMEGPU_AGENT_FUNCTION(in_wrapped_not_factor, MessageSpatial2D, MessageNone) {
    const float x1 = FLAMEGPU->getVariable<float>("x");
    const float y1 = FLAMEGPU->getVariable<float>("y");
    unsigned int count = 0;
    unsigned int id[3];
    // Count how many messages we recieved (including our own)
    for (const auto& message : FLAMEGPU->message_in.wrap(x1, y1)) {
        id[count] = message.getVariable<unsigned int>("id");
        ++count;
    }
    FLAMEGPU->setVariable<unsigned int>("count", count);
    return ALIVE;
}
TEST(Spatial2DMessageTest, wrapped_not_factor) {
    // This tests that bug #1157 is fixed
    // When the interaction radius is not a factor of the width
    // that agent's near the max env bound all have the full interaction radius
    ModelDescription m("model");
    MessageSpatial2D::Description message = m.newMessage<MessageSpatial2D>("location");
    message.setMin(0, 0);
    message.setMax(105, 105);
    message.setRadius(10);
    message.newVariable<flamegpu::id_t>("id");  // unused by current test
    AgentDescription agent = m.newAgent("agent");
    agent.newVariable<float>("x");
    agent.newVariable<float>("y");
    agent.newVariable<unsigned int>("count", 0);
    AgentFunctionDescription fo = agent.newFunction("out", out_mandatory2D);
    fo.setMessageOutput(message);
    AgentFunctionDescription fi = agent.newFunction("in", in_wrapped_not_factor);
    fi.setMessageInput(message);
    LayerDescription lo = m.newLayer();
    lo.addAgentFunction(fo);
    LayerDescription li = m.newLayer();
    li.addAgentFunction(fi);
    // Set pop in model
    CUDASimulation c(m);
    // Create an agent in the middle of each edge
    AgentVector population(agent, 6);
    // Initialise agents
    // Vertical pair that can interact
    // Bottom side
    AgentVector::Agent i1 = population[0];
    i1.setVariable<float>("x", 105.0f / 2);
    i1.setVariable<float>("y", 99.0f);
    // Bottom side boundary
    AgentVector::Agent i2 = population[1];
    i2.setVariable<float>("x", 105.0f / 2);
    i2.setVariable<float>("y", 105.0f);
    // Top side
    AgentVector::Agent i3 = population[2];
    i3.setVariable<float>("x", 105.0f / 2);
    i3.setVariable<float>("y", 0.1f);
    // Horizontal pair that can interact
    // Right side
    AgentVector::Agent i4 = population[3];
    i4.setVariable<float>("x", 99.0f);
    i4.setVariable<float>("y", 105.0f / 2);
    // Right side boundary
    AgentVector::Agent i5 = population[4];
    i5.setVariable<float>("x", 105.0f);
    i5.setVariable<float>("y", 105.0f / 2);
    // Left side
    AgentVector::Agent i6 = population[5];
    i6.setVariable<float>("x", 0.1f);
    i6.setVariable<float>("y", 105.0f / 2);
    c.setPopulationData(population);
    c.SimulationConfig().steps = 1;
    EXPECT_NO_THROW(c.simulate());
    // Recover the results and check they match what was expected
    c.getPopulationData(population);
    // Validate each agent has same result
    for (AgentVector::Agent ai : population) {
        EXPECT_EQ(3u, ai.getVariable<unsigned int>("count"));
    }
}

@Robadob Robadob closed this as completed Dec 1, 2023
@Robadob
Copy link
Member Author

Robadob commented Dec 1, 2023

static_cast<int>(floorf(((x-md->min[0]) / md->environmentWidth[0])*md->gridDim[0])),

There does exist a bug.

The maths here places a value of 99, into bin 10, rather than bin 9 (with 105 width, 10 rad).

This essentially means the com radius is shrunk when not a factor of the environment width.

@Robadob Robadob reopened this Dec 1, 2023
@Robadob
Copy link
Member Author

Robadob commented Dec 1, 2023

From @mondus in meeting, fix line 602 from previous comment and block wrapped from operating when interaction radius is not a factor of width.

@Robadob Robadob changed the title Wrapped spatial messaging where radius is not a factor of env width Spatial messaging shrinks interaction radius to a factor of width, when not a factor Dec 1, 2023
@Robadob Robadob mentioned this issue Dec 12, 2023
3 tasks
Robadob added a commit that referenced this issue Dec 12, 2023
ptheywood pushed a commit that referenced this issue Dec 15, 2023
#1160)

* BugFix: MsgSpatial interaction radius correct when not a factor of environment width.

Closes #1157

* Test that bug has been fixed.

* Seatbelts now prevents wrapped spatial iterator if radius is not a factor of environment dims.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant