Question

I'm trying to make a method which would do transformation from initial frame of reference to Center of Mass frame. The set used in the method contains a number of objects which among other properties have mass, position and velocity (if that helps).

    /**
 * Method used to set origin at the Center of Mass (COM) of the system. This
 * method calculates position(r) and velocity(v) of the COM in initial
 * frame, then uses them to transform v and r of each particle in the system
 * to COM frame.
 * 
 * @param astroObjSet
 *            a set containing massive particles
 */
private static void COM(Set<Particle> astroObjSet) {
    // temporary variables used in the method
    Vector velSum = new Vector();// Sum of velocities multiplied by mass
    Vector posSum = new Vector();// Sum of position multiplied by mass
    double totalMass = 0;

    // this loop calculates total mass of the given system, sum of v_i*m_i,
    // and sum of r_i*m_i for each particle i in the system

    for (Particle element : astroObjSet) {

        totalMass = totalMass + element.getMass();

        velSum = Vector.add(velSum,element.getVelocity().times(element.getMass()));

        posSum = Vector.add(posSum,element.getPosition().times(element.getMass()));

    }

    // calculate COM velocity and position in initial frame of reference
    Vector COMpos = posSum.times(1 / totalMass);
    Vector COMvel = velSum.times(1 / totalMass);

    // transform position and velocity of each particle in the set to COM
    // frame of reference.
    for (Particle element : astroObjSet) {


        Vector finPos = new Vector(Vector.Subtract(element.getPosition(),
                COMpos));
        Vector finVel = new Vector(Vector.Subtract(element.getVelocity(),
                COMvel));

        element.setPosition(finPos);
        element.setVelocity(finVel);
    }

But for some reason unless I put println("String") somewhere in the method, method would work only 1 out of ten times (I even counted). If you put println("String") before or after method is called it would also work, but not without. Essentially everything works only when I examine it. Never thought quantum mechanics would hunt me even in Java.

Does anybody have an idea what is going on?

Update 1 Fixed summation loop, thanks to Boann.

Was it helpful?

Solution

The Particle class does not have explicit implementations of equals and hashCode (i didn't do anything :/), do you meant that I can not modify parameters of Objects inside HashSet?

A Java Set enforces uniqueness of elements. Every object added is compared with existing objects to ensure it is not a duplicate.

HashSet does this using the hashCode and equals methods of objects to ask them whether they are the same as each other. You can modify fields of objects inside HashSets, but you must not modify any fields that you use in computing the hashCode or testing equality, because that will break/confuse the set.

Since you have not overridden the hashCode and equals methods, the default implementations simply test for object "identity": is this the same object? In that case, two created objects with equal values are treated as separate, and both can be added to a single HashSet. Since the fields are not even looked at, you can safely modify any of them without breaking the set.

So it looks like HashSet gives out elements at random. Is it normal?

Yes. A HashSet gives no guarantee as to the order of the elements, and the order will not even remain stable over time. (Internally it orders objects by some of the bits of their hashCodes, giving a difficult-to-predict and effectively random order. When a set grows, it starts looking at more bits of the hashCodes to efficiently determine uniqueness, causing them to rearrange randomly again.) If you really need to enforce order of a Set you can use a LinkedHashSet instead.

However, using a Set at all is probably wasted effort in your application. Instead of Set and HashSet, use List and ArrayList. A List is much simpler and guarantees predictable iteration order: elements are iterated in the order they were added. A List is faster than a Set too, since it doesn't expend effort trying to prevent equal objects from being added twice.

Also no idea what are multiple threads, so unlikely I'm doing that.

As a simple analogy, a thread is an instruction pointer that runs around through the code. (Imagine a finger pointing at a currently executing line of code.) It is what steps through methods, statements, loops, etc, and executes them. You always have at least one thread, otherwise your program wouldn't be running at all. You can create any number of threads and set them running around your program all at once. On a multi-CPU system, these threads can be executed truly simultaneously, one on each CPU. However, you can also have more threads than CPUs, in which case CPUs will take turns executing threads (changing to a different thread every 10 milliseconds or so) to make them seem simultaneous.

And why adding print makes it more systematic?

The only reason I can think of is that you are modifying shared data from multiple threads. Threads are essentially blind to each other, by which I mean they do not naturally try to cooperate. This causes two problems: (1) if two threads try to change data simultaneously, the data can be corrupted and end up with a value that is not correct for either thread; (2) threads might not notice if another thread has changed some variables, because any thread can assume that variables have the same values they were previously set to by that thread.

To make multithreading safe, it is necessary to add some synchronization around any changing data which is shared between threads.

If your set of particles is being used from multiple threads without synchronization, it is possible for the set to be corrupted, and/or for changes in some of the values to not be seen by other threads. The effect of adding a print statement is that it accesses a shared, properly synchronized resource (the output stream to the console) so it causes a happens-before relationship between threads doing the printing, that ensures prior changes are seen, which fixes problem (2), although it is a very sloppy substitute for explicit synchronization.

You could be using multiple threads unintentionally. For example, creating a graphical user interface creates a thread which is used to handle input events. From then on, you should either switch to that thread and do all your program's work on it, or add synchronization around any shared changing data.

If you're sure you're not editing data from multiple threads, I can't see how the print statement could possibly make any difference. (Perhaps it didn't make a difference, and the only confusion was the mis-assumption about the stability of the HashSet.)

OTHER TIPS

You probably have a memory visibility problem between threads. The print happens to synchronize over the output stream which creates a memory barrier and synchronizes with main memory masking the problem.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top