Principles of Parallel Scientific Computing