locked
"Fusion" Simulation. NEED HELP! RRS feed

  • Question

  • hi!

    i just quickly coded a Fusion today or something like that.

    but i have some problems with it. i made all the drops attract each other. but the problem is, their speed is as fast as the distance. this means, when the distance between the drops is small, their speed to each other is slower. but when their distance is big, the speed is also high.

    how do i make them faster when the distance is smaller?

    i also have a problem with the collision. Why wont they fuse, as soon as they touch??

    Import code: CTD945

    Live for nothing, OR CODE FOR SOMETHING!
    Sunday, November 1, 2009 5:33 PM

Answers

  • 1] You want the velocity to be proportional to 1/distance, try:

    Drop_X[b] = Drop_X[b] + (Drop_X[i] - Drop_X[b]) / Distance / Distance * 150
    Drop_Y[b] = Drop_Y[b] + (Drop_Y[i] - Drop_Y[b]) / Distance / Distance * 150

    Since (Drop_X[i] - Drop_X[b]) is proportional to distance, we need to divide by distance squared to get the overall velocity proportional to 1/distance.
    The 150 is just a scaling to get the speeds OK

    2] To fuse immediately on contact we need to detect when the atoms just touch, this is when their separation (distance) is equal to the sum of the two radii.

    If Distance <= Drop_Radius[b]+Drop_Radius[i] Then


    ALSO note that Drop_Radius is a multiplier to the radius used for scaling and not the actual radius so you need to be careful with this.
    Sunday, November 1, 2009 5:59 PM
  • This is due to Drop_Radius not being the actual radii - they are used in Shapes.Zoom where they are scale factors on the original shape size of radius 5, hence the image radii are actually 5*Drop_Radius.

    You also need to centre the Shapes.Move using the usual (X-width/2,Y-height/2).

    This means a bit of work sorting out what is a radius and what is a scale factor.

    Also, you shouldn't include the removed shapes in the CheckDistance loops since they still affect the velocity.

    You may also then have to consider these loops since you consider each pair twice and change their sizes within the loops before the shape size and position are updated in the GraphicsWindow, hence it may appear that shapes merge at odd times because you are seeing the results of several changes.
    Sunday, November 1, 2009 6:58 PM
  • The velocity is calculated by summing contributions from all blobs and their relative distances, including those moved to -1000,-1000 in your code.  You will notice that the final blob sometimes keeps moving, this is the influence of the deleted blobs.

    Here is a version to look at with some changes that cover these, the double counting i,b and b,i and the scale issues etc, also as the blobs grow, their total area is preserved.  Import QCX681-1.
    Sunday, November 1, 2009 7:34 PM
  • heres mine: RFN007

    this works too, doesnt it??
    Live for nothing, OR CODE FOR SOMETHING!
    Monday, November 2, 2009 6:56 PM
  • Yes, this works good.

    Only comments are:

    1] If you later want to work with the object centres (e.g. to select with mouse etc) you may want to offset them so they are centred on Drop_X,Drop_Y

    Shapes.Move(Drop[i],Drop_X[i]-15,Drop_Y[i]-15)

    2] It is more efficient to do simple arithmetic rather than call a SmallBasic Math.Power command.

    (Drop_X[i]-Drop_X[b])*(Drop_X[i]-Drop_X[b]) is probably faster than math.Power(Drop_X[i]-Drop_X[b],2)

    3] Could you just replace

    If Drop_X[i] <> Drop_OldX[i] or Drop_Y[i] <> Drop_OldY[i] And Drop_X[i] > -500 Then

    with

    If Drop_Radius[i] > 0 Then

    and do away with the Drop_OldX,Drop_OldY variables.

    And the same inside the b loop (test for Drop_Radius[b] > 0 )

    4] Inside the b loop Distance > (Drop_Radius[b] + Drop_Radius[i]) is always true on the following line and therefore is unnecessary.

    ElseIf Distance > (Drop_Radius[b] + Drop_Radius[i]) and Distance < GW Then

    If you did the above and the test for Drop_Radius[b] > 0 test, then you wouldn't need the  Distance < GW test either.

      For b = 1 to Drop_Amount
        If b <> i Then
          If Drop_Radius[b] > 0 Then
            Distance = math.SquareRoot(math.Power(Drop_X[i]-Drop_X[b],2)+math.Power(Drop_Y[i]-Drop_Y[b],2))
            If Distance <= (Drop_Radius[b] + Drop_Radius[i]) Then
    ...
            Else
    ...
            EndIf
          EndIf
        EndIf
      EndFor

    5] Your code checks all b <> i.  Therefore any pair (i=2 and b= 5) is checked twice (b=5 and i=2).  This is OK, but much of the code is repeated (e.g. the distance is the same).  Therefore a loop like the following may be faster, if the logic is right.  For example you need to update the velocity of i and b (but these are the same velocity with just the sign reversed, hence only needs to be calculated once).  This is a minor point, but since you are interested in performance it could make a difference.

    For i = 1 To Drop_Amount
      For b = i+1 To Drop_Amount
    ...
      EndFor
    EndFor
    Monday, November 2, 2009 7:36 PM

All replies

  • 1] You want the velocity to be proportional to 1/distance, try:

    Drop_X[b] = Drop_X[b] + (Drop_X[i] - Drop_X[b]) / Distance / Distance * 150
    Drop_Y[b] = Drop_Y[b] + (Drop_Y[i] - Drop_Y[b]) / Distance / Distance * 150

    Since (Drop_X[i] - Drop_X[b]) is proportional to distance, we need to divide by distance squared to get the overall velocity proportional to 1/distance.
    The 150 is just a scaling to get the speeds OK

    2] To fuse immediately on contact we need to detect when the atoms just touch, this is when their separation (distance) is equal to the sum of the two radii.

    If Distance <= Drop_Radius[b]+Drop_Radius[i] Then


    ALSO note that Drop_Radius is a multiplier to the radius used for scaling and not the actual radius so you need to be careful with this.
    Sunday, November 1, 2009 5:59 PM
  • wow! thx for the fast response!

    heres the new version: QCX681

    but the "collisions" still dont seem to be working.. the drops just fuse when they are inside of each other a little already...

    but the idea with "If Distance <= Drop_Radius[b]+Drop_Radius[i] Then " is smart! i didnt notice that it wouldnt work with just 1 radius...

    Live for nothing, OR CODE FOR SOMETHING!
    Sunday, November 1, 2009 6:18 PM
  • This is due to Drop_Radius not being the actual radii - they are used in Shapes.Zoom where they are scale factors on the original shape size of radius 5, hence the image radii are actually 5*Drop_Radius.

    You also need to centre the Shapes.Move using the usual (X-width/2,Y-height/2).

    This means a bit of work sorting out what is a radius and what is a scale factor.

    Also, you shouldn't include the removed shapes in the CheckDistance loops since they still affect the velocity.

    You may also then have to consider these loops since you consider each pair twice and change their sizes within the loops before the shape size and position are updated in the GraphicsWindow, hence it may appear that shapes merge at odd times because you are seeing the results of several changes.
    Sunday, November 1, 2009 6:58 PM
  • youre right!

    i fixed it now by using:
    Shapes.Zoom(Drop[i],Drop_Radius[i]/15,Drop_Radius[i]/15)

    where 15 is the original drop size.


    but what did you mean by:
    "Also, you shouldn't include the removed shapes in the CheckDistance loops since they still affect the velocity."
    ???

    when this works perfectly, i'll maybe try to make them "cuttable", so you can make out of 1 drop 2 drops for example.

    thx so much!
    Live for nothing, OR CODE FOR SOMETHING!
    Sunday, November 1, 2009 7:19 PM
  • The velocity is calculated by summing contributions from all blobs and their relative distances, including those moved to -1000,-1000 in your code.  You will notice that the final blob sometimes keeps moving, this is the influence of the deleted blobs.

    Here is a version to look at with some changes that cover these, the double counting i,b and b,i and the scale issues etc, also as the blobs grow, their total area is preserved.  Import QCX681-1.
    Sunday, November 1, 2009 7:34 PM
  • heres mine: RFN007

    this works too, doesnt it??
    Live for nothing, OR CODE FOR SOMETHING!
    Monday, November 2, 2009 6:56 PM
  • Yes, this works good.

    Only comments are:

    1] If you later want to work with the object centres (e.g. to select with mouse etc) you may want to offset them so they are centred on Drop_X,Drop_Y

    Shapes.Move(Drop[i],Drop_X[i]-15,Drop_Y[i]-15)

    2] It is more efficient to do simple arithmetic rather than call a SmallBasic Math.Power command.

    (Drop_X[i]-Drop_X[b])*(Drop_X[i]-Drop_X[b]) is probably faster than math.Power(Drop_X[i]-Drop_X[b],2)

    3] Could you just replace

    If Drop_X[i] <> Drop_OldX[i] or Drop_Y[i] <> Drop_OldY[i] And Drop_X[i] > -500 Then

    with

    If Drop_Radius[i] > 0 Then

    and do away with the Drop_OldX,Drop_OldY variables.

    And the same inside the b loop (test for Drop_Radius[b] > 0 )

    4] Inside the b loop Distance > (Drop_Radius[b] + Drop_Radius[i]) is always true on the following line and therefore is unnecessary.

    ElseIf Distance > (Drop_Radius[b] + Drop_Radius[i]) and Distance < GW Then

    If you did the above and the test for Drop_Radius[b] > 0 test, then you wouldn't need the  Distance < GW test either.

      For b = 1 to Drop_Amount
        If b <> i Then
          If Drop_Radius[b] > 0 Then
            Distance = math.SquareRoot(math.Power(Drop_X[i]-Drop_X[b],2)+math.Power(Drop_Y[i]-Drop_Y[b],2))
            If Distance <= (Drop_Radius[b] + Drop_Radius[i]) Then
    ...
            Else
    ...
            EndIf
          EndIf
        EndIf
      EndFor

    5] Your code checks all b <> i.  Therefore any pair (i=2 and b= 5) is checked twice (b=5 and i=2).  This is OK, but much of the code is repeated (e.g. the distance is the same).  Therefore a loop like the following may be faster, if the logic is right.  For example you need to update the velocity of i and b (but these are the same velocity with just the sign reversed, hence only needs to be calculated once).  This is a minor point, but since you are interested in performance it could make a difference.

    For i = 1 To Drop_Amount
      For b = i+1 To Drop_Amount
    ...
      EndFor
    EndFor
    Monday, November 2, 2009 7:36 PM
  • nice idea with the "Drop_Radius[b] > 0"!

    but i dont get the number 5...


    heres my updated code:
    VJK277

    i also couldnt do the centering, because the "collision ellipse" seems to be smaller than the actual shape.

    Live for nothing, OR CODE FOR SOMETHING!
    Monday, November 2, 2009 10:00 PM
  • The Shapes.Move needs the offset to be just the original Ellipse Radius (15)

    Shapes.Move(Drop[i],Drop_X[i]-15,Drop_Y[i]-15)

    Commented modified code to show the double counting and also a weighted mean position for fused atoms.  Import VJK277-0.

    The physics of Fusion is somewhat different to this.  The charged (always charged since it must be a very high energy plasma) Hydrogen ions strongly repel each other due to the electric charge repulsion.  Only if they get close enough, by high density and high energy (high velocity) can they overcome the electric repulsion to fuse to form Helium and then release lots of energy from the Strong nuclear force.  To get the required neutrons for Helium (2 protons+2neutrons), The hydrogen (1p) is usually Deuterium (1p+1n) or Tritium (1p+2n), or others.

    EDIT, actually is best to always delete atom b, since it is atom i that redrawn after the call to CheckDistance.

    Also, if we centre the atoms

      Drop_X[i] = Math.GetRandomNumber(GW)-30
      Drop_Y[i] = Math.GetRandomNumber(GW)-30


    should be

      Drop_X[i] = Math.GetRandomNumber(GW)
      Drop_Y[i] = Math.GetRandomNumber(GW)

    Finally, to detect the atom with the mouse

    If Distance2 <= Drop_Radius[i] then

    should be the following due to the way you are merging the atoms at a separation somewhat less than their actual separation.

    If Distance2 <= Drop_Radius[i]*15/12 then


    Monday, November 2, 2009 10:51 PM
  • uhm.. i actually dont want to do atoms. i want to do something like drops, or liquid, like quicksilver...

    okay.

    i'll check that stuff. thx!

    Live for nothing, OR CODE FOR SOMETHING!
    Tuesday, November 3, 2009 2:14 PM