PHYCS 3730/5720
Assignment 6

Fall Semester 2000


Home | Announcements | Lecture Plan | Assignments | Exercises | References | Web Resources

Exercise 1.

This problem is an introduction to classes in C++.

  • Create your own header file (simple text file) called vec3d.h. For debugging purposes you may wish to do this exercise concurrently with Exercise 2. The important issue is that the g++ compiler won't let you compile a ".h" file on its own. You must "#include" it a regular "c" or ".cc" source file, as you are instructed in the next exercise, and compile the source code. You could start off by having your source code in exercise 2 contain only some "#include" statements and a "main()" function which does nothing ("int&npsb;main() { }")

    This exercise is divided into a fair number of parts, but each part requires not more than a few lines of code at most. Hint: Do the Lab exercise on C++ classes before attempting this exercise.

  • Put statements to "#include" the iostream and cmath header files at the very top of your own header file.

  • Then, define a class called vec3d with public members x,y,z, all of type double.

  • Define two constructor functions for your class, one which accepts an instatiation of vec3d without any initializing arguments and one which initializes members x,y,z. Specifically, set things up so that
        vec3d v; vec3d u(1,2,3);
    
    are both valid instantiations where x has uninitialized members and u has (x,y,z) set to (1,2,3).

  • Overload the "+=" and "+" operators so that "u+=v" sets "u" to its original value with vector-added value of "v", and "u+v" returns the vector sum of "v" and "u" (both "w" and "u", as well as the return value for the operators, should be of type vec3d).

  • Overload the "*=" and "*" operators for a vector multiplied by a scalar (e.g., "v*=10.0" or "v*10.0"). Put in a second overload of "*" for the case of a scalar times a vector (e.g., "10.0*v").

  • Overload the "*" operator for the product of two vectors. For usefulness in vector arithmetic, have this operator set up so that "v*w" returns the dot product of vectors "v" and "w". The return type should be "double".

  • Now overload the "^" operator to return the vector cross product of two vectors (e.g., u^v). Incidental note: in some instances you might be tempted to do this
         v ^ w * u;
    
    where we know that the cross product should be done before the dot product (since you aren' allowed to take the cross product of a vector and a scalar). The compiler does not know this. It looks to the "precedence" of the "*" and "^" operators and it turns out that "*" has a higher precedence, just as it has a higher precedence over the "+" and "-" for scalar math. Thus the dot product will be taken before the cross product and the above syntax may not get passed the compiler. To make sure you get the order of the operations correct, when in doubt, use parentheses: try "(v^w)*u".

  • Create a class member function "norm()" that returns the norm (i.e., length) of the the vector. For example,
        vec3d z(1,1,1); cout << z.norm()
    
    should print out the square root of 3, in double precision.

  • Finally (!), look at the file ~p5720/src/vec3d_extras.h and cut-n-paste the operator overloads for vector subtraction, scalar division, etc., as well as an overload for the "[]" operator (so you can say "s[0]" to mean "s.x", if you ever want to), and for printing out a vector with cout. Note this file is not a valid header; it only has things for you to put in your header file.

    Between the lab exercise and the vec3d_extras.h, you will see examples of how and where to overload the various operators. (Again, please go through the lab exercise AND please look at the header-extras!) One possibility (not necessarily the best for all situations...[long story?]) is to overload all the "op-assign" operators (+=, *=, -=, /=) inside your class def, and to overload others just below the def (+, -, *, /, ^). (Reminder: The mult operator will have to be overloaded three times: for vec3d*double, double*vec3d, and vector-dot-product, vec3d*vec3d). It makes sense to put your member function norm() inside the class def.

    Submit your file vec3d.h -- please do not submit a ".c" file! (You may wish to complete the next exercise before handing in your header file, since the next exercise is intended to demonstrate that your header does what it is supposed to....)


    Exercise 2.

    In a file called testvec3d.c (just ".c", not ".cc" or ".C"), write code to work with vectors

        v = (1,1,1) and u = (-1,2,3).
    
    Put the statement
    #include "vec3d.h"
    
    near the top of your code by any other "#include <...>" statements you deem necessary (before main(), anyway). This will cause your work from the previous exercise to be read in as if it were part of your new program. Have your code print out something of exactly this form:
    v: (1,1,1)
    u: (-1,2,3)
    v+u: (XXX,XXX,XXX)
    v-u: (XXX,XXX,XXX)
    v*u: XXX
    2*v*u: XXX
    v^u: (XXX,XXX,XXX)
    
    where XXX values are to be calculated within your code.

    Caution! because of "operator precedence" rules, when you print out the cross product, be sure to use parentheses, "(v^u)", in your "cout" statement. The "^" operator has lower precedence than "<<", so without the parentheses, "^" will be executed after the "<<" -- not what you meant. (A better choice for the cross product operator would have been "%", since it has the same precedence as "*" and "/".)


    Exercise 3.

    Write a C++ code, electric.c to calculate the electric field from a set of point charges. Include your header file from exercise 1 just as you did in exercise 2. The point charges should be located at (x,y,z) coordinates

      (0.5,0.15,0.1), (0.15,0.5,0.1), (0.5,0.85,0.1), (0.85,0.5,0.1);
    
    (for corners of a square lying in the z=0.1 plane). The charges on these points are 1,-1,1,-1, respectively. The units are such that the electric potential from a unit charge is 1/r, where r is the radial separation from the charge.

    Have your code loop over a 16x16 grid of points spanning the unit square with corners at (x,y)=(0,0) and (1,1) in the z=0 plane. Print out the x-y coordinates of each grid point and the x-y components of the electric field at that point to cout, so that

    g++ electric.c -o electric
    electric > electric.dat
    
    will produce a four column ascii data file electric.dat. (Remember, use the redirect ">!" to overwrite the target file if you run "electric" as above more than once.)

    Note that while you are printing out only quantities in the z=0 plane, this is not strictly a 2D problem. The charges themselves do not lie in this plane -- hence there are no singularities to worry about in the field calculations. Also, take full advantage of your vec3d class: for example, to calculate the x-component of a unit vector parallel to some other vector "r", simply write "r.x/r.norm()" (the x-component of "r" divided by the norm of "r").

    To view your electric field data, copy the file ~p5720/src/electric.sm to your working directory and "execute electric.sm" within the "sm" plotting utility. Have "sm" dump output to a postscript file, "electric.ps" and invoke the un*x utility

         pstojpeg electric.ps
    
    This will create a JPEG file "electric.jpeg", an image which can be viewed by "gimp", "xv", or your web browser. Or, perhaps better, try dumping sm output to a pbm (pixel bit-map) file ("device pbm electric.pbm"), then use
        pbmtopgm 1 1 electric.pbm | cjpeg > ! electric.jpeg 
    
    This may give you a better-looking image.

    Please submit your source code, electric.c and the image file electric.jpeg.


    Files to be submitted for this assignment:

    vec3d.h
    testvec.c
    electric.c
    electric.jpeg


    bcb 6-Oct-00.