nuclear_dist.h

00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006, 2007, Andrew W. Steiner
00005   
00006   This file is part of O2scl.
00007   
00008   O2scl is free software; you can redistribute it and/or modify
00009   it under the terms of the GNU General Public License as published by
00010   the Free Software Foundation; either version 3 of the License, or
00011   (at your option) any later version.
00012   
00013   O2scl is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016   GNU General Public License for more details.
00017   
00018   You should have received a copy of the GNU General Public License
00019   along with O2scl. If not, see <http://www.gnu.org/licenses/>.
00020 
00021   -------------------------------------------------------------------
00022 */
00023 #ifndef O2SCL_NUCLEAR_DIST_H
00024 #define O2SCL_NUCLEAR_DIST_H
00025 
00026 #include <iostream>
00027 #include <o2scl/nucleus.h>
00028 #include <o2scl/nuclear_mass.h>
00029 
00030 #ifndef DOXYGENP
00031 namespace o2scl {
00032 #endif
00033 
00034   /** 
00035       \brief A distribution of nuclei
00036 
00037       A simple base for a collection of objects of type \ref nucleus
00038    */
00039   class nuclear_dist {
00040 
00041 #ifndef DOXYGENP
00042 
00043   protected:
00044 
00045     virtual nucleus *next(nucleus *np)=0;
00046 
00047 #endif
00048     
00049   public:
00050 
00051     virtual ~nuclear_dist() {}
00052     
00053     /** 
00054         \brief An iterator for the nuclear distribution
00055         
00056         The standard usage of this iterator is something of the form:
00057         \code
00058         mnms95_mass mth;
00059         simple_dist sd(5,6,10,12,&mth);
00060         for(nuclear_dist::iterator ndi=sd.begin();ndi!=sd.end();ndi++) {
00061         // do something here for each nucleus
00062         }
00063         \endcode
00064         which would create a list consisting of three isotopes (A=10,
00065         11, and 12) of boron and three isotopes carbon for a total
00066         of six nuclei.
00067     */
00068     class iterator {
00069       
00070 #ifndef DOXYGEN_INTERNAL
00071 
00072     protected:
00073 
00074       // The iterator is really just a wrapper for the pointer
00075       nucleus *np;
00076 
00077       /// A pointer to the distribution
00078       nuclear_dist *ndp;
00079 
00080 #endif
00081       
00082     public:
00083 
00084 #ifndef DOXYGEN_INTERNAL
00085 
00086       /** \brief Create an iterator from the given distribution using the
00087           nucleus specified in \c npp.
00088       */
00089       iterator(nuclear_dist *ndpp, nucleus *npp) {
00090         ndp=ndpp;
00091         np=npp;
00092       }
00093 
00094 #endif
00095 
00096       /// Proceed to the next nucleus
00097       iterator operator++() {
00098         np=ndp->next(np);
00099         return iterator(ndp,np);
00100       }
00101 
00102       /// Proceed to the next nucleus
00103       iterator operator++(int unused) {
00104         nucleus *tmp=np;
00105         np=ndp->next(np);
00106         return iterator(ndp,tmp);
00107       }
00108 
00109       /// Dereference the iterator
00110       nucleus *operator->() const {
00111         return np;
00112       };
00113       
00114       friend int operator==(const nuclear_dist::iterator &i1,
00115                             const nuclear_dist::iterator &i2);
00116 
00117       friend int operator!=(const nuclear_dist::iterator &i1,
00118                             const nuclear_dist::iterator &i2);
00119     };
00120 
00121     /// The beginning of the distribution
00122     virtual iterator begin()=0;
00123 
00124     /// The end of the distribution
00125     virtual iterator end()=0;
00126 
00127     /// The number of nuclei in the distribution
00128     virtual size_t size()=0;
00129   };
00130 
00131   /// Compare two nuclei
00132   int operator==(const nuclear_dist::iterator &i1,
00133                  const nuclear_dist::iterator &i2);
00134 
00135   /// Compare two nuclei
00136   int operator!=(const nuclear_dist::iterator &i1,
00137                 const nuclear_dist::iterator &i2);
00138 
00139   /** 
00140       \brief A simple nuclear distribution given a range in A and Z
00141 
00142       The iterator for this distribution begins with the nucleus with
00143       the lowest Z and A, and increases A before incrementing Z and
00144       beginning again with the lowest A for that value of Z.
00145 
00146       \todo This takes a nuclear_mass pointer as input. It should
00147       probably be a reference instead?
00148       \todo Add error checking in constructors and set functions
00149   */
00150   class simple_dist : public nuclear_dist {
00151   public:
00152 
00153     simple_dist();
00154 
00155     /** \brief Create a distribution from ranges in A specified
00156         for each Z
00157         
00158         The length of the arrays minA and maxA should be exactly
00159         \f$\mathrm{maxZ}-\mathrm{minZ}+1\f$.
00160     */
00161     simple_dist(int minZ, int maxZ, int minA[], int maxA[],
00162                 nuclear_mass *nm);
00163   
00164     /// Create a square distribution in A and Z
00165     simple_dist(int minZ, int maxZ, int minA, int maxA,
00166                 nuclear_mass *nm);
00167   
00168     virtual ~simple_dist();
00169 
00170     /// The beginning of the distribution
00171     virtual iterator begin() {
00172       return iterator(this,list);
00173     };
00174 
00175     /// The end of the distribution
00176     virtual iterator end() {
00177       return iterator(this,list+list_size);
00178     };
00179 
00180     /// The number of nuclei in the distribution
00181     virtual size_t size() {
00182       return list_size;
00183     };
00184 
00185     /** \brief Set the distribution from ranges in A specified
00186         for each Z
00187         
00188         The length of the arrays minA and maxA should be exactly
00189         \f$\mathrm{maxZ}-\mathrm{minZ}+1\f$.
00190     */
00191     int set_dist(int minZ, int maxZ, int minA[], int maxA[],
00192                 nuclear_mass *nm);
00193   
00194     /// Set a square distribution in A and Z
00195     int set_dist(int minZ, int maxZ, int minA, int maxA,
00196                 nuclear_mass *nm);
00197   
00198 #ifndef DOXYGENP
00199 
00200   protected:
00201 
00202     /// Specify how to move to the next nucleus
00203     virtual nucleus *next(nucleus *np) {
00204       return np+1;
00205     }
00206 
00207     /// The distribution of nuclei as an array
00208     nucleus *list;
00209 
00210     /// The minimum atomic number for a given Z
00211     int *min_A;
00212     
00213     /// The maximum atomic number for a given Z
00214     int *max_A;
00215 
00216     /// The minimum proton number
00217     int min_Z;
00218     
00219     /// The maximum proton number
00220     int max_Z;
00221 
00222     /// The size of \ref list array
00223     size_t list_size;
00224 
00225     /// True if memory has been allocated
00226     bool alloc;
00227 
00228 #endif
00229 
00230   };
00231 
00232   /** 
00233       \brief Full distribution including all nuclei from a
00234       discrete mass formula
00235   */
00236   class full_dist : public nuclear_dist {
00237   public:
00238     
00239     full_dist() {
00240       list_size=0;
00241     }
00242 
00243     /** \brief Create a distribution from ranges in A specified
00244         for each Z
00245         
00246         The length of the arrays minA and maxA should be exactly
00247         \f$\mathrm{maxZ}-\mathrm{minZ}+1\f$.
00248     */
00249     full_dist(nuclear_mass *nm, int maxA=400, bool include_neutron=false);
00250 
00251     /** \brief Set the distribution from ranges in A specified
00252         for each Z
00253         
00254         The length of the arrays minA and maxA should be exactly
00255         \f$\mathrm{maxZ}-\mathrm{minZ}+1\f$.
00256     */
00257     int set_dist(nuclear_mass *nm, int maxA=400, bool include_neutron=false);
00258   
00259     virtual ~full_dist() {
00260       if (list_size>0) delete[] list;
00261     }
00262     
00263     /// The beginning of the distribution
00264     virtual iterator begin() {
00265       return iterator(this,&list[0]);
00266     };
00267 
00268     /// The end of the distribution
00269     virtual iterator end() {
00270       return iterator(this,&list[list_size-1]);
00271     };
00272 
00273     /// The number of nuclei in the distribution
00274     virtual size_t size() {
00275       return list_size;
00276     };
00277 
00278 #ifndef DOXYGENP
00279 
00280   protected:
00281 
00282     /// Specify how to move to the next nucleus
00283     virtual nucleus *next(nucleus *np) {
00284       return np+1;
00285     }
00286 
00287     /// The distribution of nuclei as an array
00288     nucleus *list;
00289 
00290     /// The size of \ref list array
00291     size_t list_size;
00292 
00293 #endif
00294 
00295   };
00296 
00297 #ifndef DOXYGENP
00298 }
00299 #endif
00300 
00301 #endif

Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.