k-dot-p 0.1

digital_alloy_optimizer_1d_mpi.h++

Go to the documentation of this file.
00001 /*
00002  *Optimizes a material according to some number.
00003 
00004 
00005     Copyright (C) 2011 Joseph Pingenot
00006 
00007     This program is free software: you can redistribute it and/or modify
00008     it under the terms of the GNU Affero General Public License as published by
00009     the Free Software Foundation, either version 3 of the License, or
00010     (at your option) any later version.
00011 
00012     This program is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015     GNU Affero General Public License for more details.
00016 
00017     You should have received a copy of the GNU Affero General Public License
00018     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00019 
00020 */
00021 
00022 #ifndef ___LIBKDOTP_DIGITAL_ALLOY_OPTIMIZER_MPI_1D_HPP___
00023 #define ___LIBKDOTP_DIGITAL_ALLOY_OPTIMIZER_MPI_1D_HPP___
00024 
00025 #include <math.h>
00026 #include <mpi.h>
00027 #include <gsl/gsl_rng.h>
00028 #include <gsl/gsl_errno.h>
00029 #include <libmodelxx/material.h++>
00030 #include <libmodelxx/generic_structure.h++>
00031 
00032 namespace kdotp {
00033   namespace libmetacalc {
00034     namespace optimizer {
00035 
00036       class digital_alloy_optimizer_1d_mpi {
00037       public:
00038   typedef void (*set_point_callback)(unsigned X, const kdotp::libmodelxx::structure::material* mat, void* privdat);
00039   enum goal {
00040     MAXIMIZE,
00041     MAXIMIZE_ABS,
00042     MINIMIZE,
00043     MAKE_ZERO
00044   };
00045 
00046   /**constructor and initializer in one
00047    *\param marker_material material used to mark the region to be optimized
00048    *\param _mat1 material to be used if the block is zero
00049    *\param _mat0 material to be used if the block is one
00050    *\param s generic_structure to be optimized
00051    *\param _set_point callback to use when setting a point, or NULL if you don't want to do anything
00052    *\param _blocksize number of points per block
00053    *\param _goal the goal of the optimization
00054    *\param err GError information if something failed. Untouched if successful.
00055    *\param privdat private data for the set_points callback (used when initializing)
00056    *\param N_nodes number of nodes being executed on
00057    *\param node node number for this program.
00058    *\param rng_seed seed for the random number generator (default is 0, i.e. no seed)
00059    *\param assignements list of initial material assignments for each block (or for all blocks)
00060    *\param assignement_expr function to evaluate to get the initial material assignments.
00061    *\param global_symbols global symbol table
00062    *\param temperature if specified or non-zero, use simulated annealing at the specified temperature.  If the temperature is never set, the steepest-descent-related Monte Carlo algorithm will be used.
00063    *\note Starting and stopping points are fetched from the generic structure.
00064    *\note that the assignments are done on the block level,
00065    *i.e. in blocks of points.  This is to improve efficiency and
00066    *accuracy, since structures can only be grown so finely, but
00067    *having a grid spacing which is a multiple of the minimum
00068    *feature size is desirable for high-accuracy calculations.
00069    *\note that any incommensurate number of points will be split
00070    *amongst the points as evenly as possible.
00071    *\note that this modifies the generic_structure, removing the marker material and replacing it with materials from the optimizer state.
00072    *\note that this constructor calls _set_point, since it has to initialize the material.
00073    */
00074   digital_alloy_optimizer_1d_mpi(
00075            kdotp::libmodelxx::structure::material* marker_material, 
00076            kdotp::libmodelxx::structure::material* _mat1, 
00077            kdotp::libmodelxx::structure::material* _mat0, 
00078            kdotp::libmodelxx::structure::generic_structure* s, 
00079            set_point_callback _set_point,
00080            unsigned _blocksize, 
00081            enum goal _goal, 
00082            GError** err, 
00083            void* privdat, 
00084            int _N_nodes,
00085            int _node,
00086            unsigned _N_blocks=0,
00087            long unsigned int rng_seed=0,
00088            GList* assignments=NULL,
00089            struct ::kdotp::libmodelxx::postprocessing::function_exp *assignment_expr=NULL,
00090            double temperature=0,
00091            GHashTable *global_symbols=NULL
00092            );
00093   
00094   /*The two materials we can be using at each site*/
00095   kdotp::libmodelxx::structure::material* mat1;
00096   kdotp::libmodelxx::structure::material* mat0;
00097   /*This stores the current material assignments.*/
00098   short unsigned *current_assignments;
00099   /*This stores the set of bits which state that the material at that location is known optimum for this particular point*/
00100   short unsigned *material_is_optimum;
00101   /*Pointer to the generic structure we're to modify.
00102    *\note Please note that although it's perfectly doable to just set the genstruct
00103    *  and then use it to create the Hamiltonian over and over and over again, that it's
00104    *  much much more efficient to use the callback to also set the Hamiltonian directly.
00105    *\note To manipulate the Hamiltonian directly, you'll need to set the material yourself
00106    *  for now.  I may later add an interface through the generic hamltonian class to accomplish
00107    *  this.
00108    */
00109   kdotp::libmodelxx::structure::generic_structure* genstruct;
00110   /*The callback to use when setting a point*/
00111   set_point_callback call_set_point_callback;
00112   /*Starting and ending points. Derived in the constructor from
00113     the generic_structure.  These points are *in*clusive. */
00114   unsigned start_X;
00115   /*This one is exclusive, i.e. this is the first point after the optimizer region.*/
00116   unsigned stop_X;
00117   /*Size of a block, in points*/
00118   unsigned blocksize;
00119   /*Stores the number of points in each block*/
00120   unsigned* points_in_block;
00121   /*This stores the point that the start of the block corresponds to*/
00122   unsigned* point_start;
00123   /**the number of blocks*/
00124   unsigned N_blocks;
00125   /**Previous value we're to track, to compare how we're changing.
00126    *\note this is a *pointer*; if it's NULL, the previous calculation was the first one, so all of the blocks had been changed.
00127    */
00128   double previous_value;
00129   /**Which block was last changed.
00130    *\note this is a *pointer*; if it's NULL, the previous calculation was the first one, so all of the blocks had been changed.
00131    *\note this is the block which was just tested
00132    */
00133   unsigned* current_block;
00134   enum goal goal;
00135   /**The GSL random number generator information.*/
00136   gsl_rng* rng;
00137   unsigned long int seed;
00138         unsigned N_nodes;
00139   unsigned node;
00140   /*Temperature for simulated annealing*/
00141   double T;
00142 
00143   /*array containing the first block assigned to each node.  There are N_nodes+1 values (the last is 
00144     the off the end of the array!*/
00145   int* node_assignments;
00146   /*The results of this node's calculation*/
00147   double* results;
00148   /*The results of modifying the requested sites.  Only on the root node; there are N_blocks nodes.
00149    */
00150   double* all_results;
00151 
00152   inline void randomize_array(short unsigned* array, unsigned int N) {
00153     for(unsigned i=0; i<N; i++) {
00154       /**\note that gsl_rng_uniform returns [0,1), so 0.5 will be considered in the upper half,
00155        *  so that both options will be equally probable
00156        *\note Upper half of [0,1) => 1; lower => 0.
00157        */
00158       if(gsl_rng_uniform(rng) >= 0.5) {
00159         array[i]=1;
00160       }else{
00161         array[i]=0;
00162       }
00163     }
00164   }
00165   inline bool is_improved(double value) {
00166     switch(goal) {
00167     case MAXIMIZE:
00168       return (value > previous_value);
00169     case MAXIMIZE_ABS:
00170       return (fabs(value) > fabs(previous_value));
00171     case MINIMIZE:
00172       return (value < previous_value);
00173     case MAKE_ZERO:
00174       return (fabs(value) < fabs(previous_value));
00175     }
00176     return false;
00177   }
00178   inline double dist_to_goal(double value) {
00179     switch(goal) {
00180     case MAXIMIZE:
00181       return value - previous_value;
00182     case MAXIMIZE_ABS:
00183       return fabs(value) - fabs(previous_value);
00184     case MINIMIZE:
00185       return previous_value - value;
00186     case MAKE_ZERO:
00187       return fabs(previous_value) - fabs(previous_value);
00188     }
00189     return false;
00190   }
00191   inline void toggle_block(unsigned block, void* privdat) {
00192     if(current_assignments[block] == 0) {
00193       current_assignments[block] = 1;
00194     }else{
00195       current_assignments[block] = 0;
00196     }
00197     set_block(block, privdat);
00198   }
00199   inline void set_block(unsigned block, void* privdat) {
00200 	  ::kdotp::libmodelxx::grid::cartesian_grid< ::kdotp::libmodelxx::structure::material*, 1, 1>* matgrid
00201       = (::kdotp::libmodelxx::grid::cartesian_grid< ::kdotp::libmodelxx::structure::material*, 1, 1>*)
00202       (genstruct->material_grid);
00203     unsigned final_point = point_start[block];
00204     for(unsigned pt=0; pt<points_in_block[block]; pt++) {
00205       matgrid->set_point(&final_point, (current_assignments[block]==0)?&mat0:&mat1);
00206       if(call_set_point_callback != NULL)
00207         call_set_point_callback(final_point, (current_assignments[block]==0)?mat0:mat1, privdat);
00208       final_point++;
00209     }
00210   }
00211 
00212   inline void set_material_from_current_assignments(void* privdat) {
00213     for(unsigned block=0; block<N_blocks; block++) {
00214       set_block(block, privdat);
00215     }
00216   }
00217   /**Does the first step in the algorithm.
00218    *\param privdat pointer to data for the set_point callback.
00219    *\return 0 if we've not converged, or 1 if we've converged.
00220    */
00221   int do_step(void* privdat);
00222 
00223   /*This performs the calculation without stepping through manually.
00224    *At each step, get_value is called with privdat
00225    *\param get_value callback to use after setting the materials.
00226    *\param privdat private data for the callback
00227    *\return NULL if we converged; GError* if there was an error.
00228    *\note that if NaN is returned, we stop and return an error
00229    *\note this should eventually deal with GErrors for better error reporting.
00230    */
00231   GError*  do_optimization(double (*get_value)(void* privdat, unsigned assignment, long unsigned iteration), void* get_value_privdat, void* set_point_privdat, double anneal_start, double anneal_end, unsigned n_anneal_steps, unsigned n_anneal_cycles, unsigned num_calculations_per_annealing_step);
00232   /**Resets the state to get ready to do an optimization.
00233    *\note that this randomizes the current assignments array, so this is what
00234    *  you'll want to call to start from another initial condition
00235    */
00236   void initialize(void* privdat);
00237   /**Initializes to a known state.
00238    *\param state the state to initialize to (array of N_blocks short unsigned ints)
00239    */
00240   void initialize(const short unsigned* state, void* privdat);
00241   /*this should be virtual if we had any real inheritance, but we don't*/
00242   ~digital_alloy_optimizer_1d_mpi();
00243       private:
00244   digital_alloy_optimizer_1d_mpi() {}
00245   bool operator==(const digital_alloy_optimizer_1d_mpi& o) {return false;}
00246   digital_alloy_optimizer_1d_mpi operator=(const digital_alloy_optimizer_1d_mpi& o) {return *this;}
00247   digital_alloy_optimizer_1d_mpi(const digital_alloy_optimizer_1d_mpi& o){}
00248       };
00249 
00250 
00251 
00252     }
00253   }
00254 }
00255 
00256 
00257 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines