예제 #1
0
/*!
 Set up the event recorder by defining the fault boundaries (in terms of block IDs).
 */
void EventRecorder::init(SimFramework *_sim) {
	VCSimulation				*sim = static_cast<VCSimulation*>(_sim);
	std::string					file_name = sim->getEventsFile().c_str();
	BlockList::const_iterator	it;
	
	if (!sim->isRootNode()) return;
	
    eFile.open(file_name.c_str());
    assertThrow(eFile, "Failed to open events file: " + file_name);
    eFile << std::fixed << std::setprecision(2);
	
    // SETTING FID BOUNDS, ID OF THE FIRST AND THE LAST BLOCK
    FaultID prev_fid = UNDEFINED_FAULT_ID;
	BlockID start_block_id = UNDEFINED_BLOCK_ID;
    for(it=sim->begin();it!=sim->end();++it) {
        if(it->getFaultID() != prev_fid) {
			if (start_block_id != UNDEFINED_BLOCK_ID) {
				faultBlockIDs.push_back(std::make_pair(start_block_id, it->getBlockID()-1));
			}
			start_block_id = it->getBlockID();
            prev_fid = it->getFaultID();
        }
    }
	faultBlockIDs.push_back(std::make_pair(start_block_id, sim->numGlobalBlocks()-1));
	assertThrow(start_block_id!=UNDEFINED_BLOCK_ID, "Could not find any blocks in simulation.");
}
예제 #2
0
/*!
 Allocate and initialize the arrays needed for a VC simulation.
 These include the shear and normal Greens function matrices
 and stress value arrays.
 */
void VCSimData::setupArrays(const unsigned int &global_sys_size,
							const unsigned int &local_sys_size,
							const bool &compressed,
							const bool &transposed) {
	int				i;
	
	deallocateArrays();
	
	global_size = global_sys_size;
	// Make the local size a factor of 16 to allow SSE loop unrolling
	local_size = local_sys_size+(16-local_sys_size%16);
	
	if (compressed) {
		if (transposed) {
			green_shear = new quakelib::CompressedRowMatrixTranspose<GREEN_VAL>(local_size, global_size);
			green_normal = new quakelib::CompressedRowMatrixTranspose<GREEN_VAL>(local_size, global_size);
		} else {
			green_shear = new quakelib::CompressedRowMatrixStraight<GREEN_VAL>(local_size, global_size);
			green_normal = new quakelib::CompressedRowMatrixStraight<GREEN_VAL>(local_size, global_size);
		}
	} else {
		if (transposed) {
			green_shear = new quakelib::DenseStdTranspose<GREEN_VAL>(local_size, global_size);
			green_normal = new quakelib::DenseStdTranspose<GREEN_VAL>(local_size, global_size);
		} else {
			green_shear = new quakelib::DenseStdStraight<GREEN_VAL>(local_size, global_size);
			green_normal = new quakelib::DenseStdStraight<GREEN_VAL>(local_size, global_size);
		}
	}
	
	shear_stress = (double*)malloc(sizeof(double)*global_size);
	assertThrow(shear_stress, "Not enough memory to allocate shear stress array.");
	normal_stress = (double*)malloc(sizeof(double)*global_size);
	assertThrow(normal_stress, "Not enough memory to allocate normal stress array.");
    f_shear_stress = (double*)malloc(sizeof(double)*global_size);
	assertThrow(f_shear_stress, "Not enough memory to allocate shear stress array.");
	f_normal_stress = (double*)malloc(sizeof(double)*global_size);
	assertThrow(f_normal_stress, "Not enough memory to allocate normal stress array.");
	update_field = (double*)malloc(sizeof(double)*global_size);
	assertThrow(update_field, "Not enough memory to allocate update field array.");
	
	for (i=0;i<global_size;++i) {
		shear_stress[i] = normal_stress[i] = 0;
		f_shear_stress[i] = f_normal_stress[i] = 0;
		update_field[i] = 0;
	}
}
예제 #3
0
// Read the Greens function values in from a specified file
void GreensFuncFileParse::CalculateGreens(Simulation *sim) {
#ifdef HDF5_FOUND
    HDF5GreensDataReader    *greens_file_reader;
    BlockID                 gid;
    int                     i, j, num_global_blocks;
    double                  *in_shear_green, *in_normal_green;

    // Open the Greens data file and initialize arrays to read in Greens values
    if (sim->getGreensInputfile().empty()) {
        sim->errConsole() << "ERROR: Greens input file undefined. Quitting." << std::endl;
        exit(-1);
    }

    num_global_blocks = sim->numGlobalBlocks();
    greens_file_reader = new HDF5GreensDataReader(sim->getGreensInputfile());
    assertThrow(greens_file_reader->getGreensDim() == num_global_blocks, "Greens input file not same dimension as model.");

    in_shear_green = new double[num_global_blocks];
    in_normal_green = new double[num_global_blocks];

    // Read the Greens function shear and normal values
    for (i=0; i<sim->numLocalBlocks(); ++i) {
        progressBar(sim, 0, i);

        gid = sim->getGlobalBID(i);
        greens_file_reader->getGreensVals(gid, in_shear_green, in_normal_green);

        for (j=0; j<num_global_blocks; ++j) {
            //// Schultz, excluding zero slip rate elements from sim by setting Greens to zero
            if (sim->getBlock(gid).slip_rate()==0  ||  sim->getBlock(j).slip_rate()==0) {
                sim->setGreens(gid, j, 0, 0);
            } else {
                sim->setGreens(gid, j, in_shear_green[j], in_normal_green[j]);
            }
        }
    }

    // use delete [] for c-arrays.
    delete greens_file_reader;
    delete [] in_shear_green;
    delete [] in_normal_green;
#else
    assertThrow(false, "HDF5 is required to use Greens function file I/O.");
#endif
}
예제 #4
0
/*!
 Calculate the stress on all blocks and determine which block will be
 the next to fail and when it will fail. Use this to determine the
 slipDeficit on all blocks at the time of failure. Finally, use the
 new slipDeficit to recalculate the stress on all blocks at the time of failure.
 */
SimRequest UpdateBlockStress::run(SimFramework *_sim) {
    // Put a stress load on all blocks and determine which block will fail first
    int                     lid;
    BlockVal                next_static_fail, next_aftershock, next_event, next_event_global;
    quakelib::Conversion    convert;
    quakelib::ModelEvent    new_event;

    // Calculate the current rates of stress change on all blocks
    stressRecompute();

    // Given the rates of change, determine which block will fail next
    nextStaticFailure(next_static_fail);

    // Get the next aftershock event time
    nextAftershock(next_aftershock);

    // Take whichever is sooner, with ties going in favor of aftershocks
    if (next_static_fail.val < next_aftershock.val) {
        next_event.val = next_static_fail.val;
        next_event.block_id = next_static_fail.block_id;
    } else {
        next_event.val = next_aftershock.val;
        next_event.block_id = next_aftershock.block_id;
    }

    // Each node now has the time before the first failure among its blocks
    // Determine the time to first failure over all nodes
    sim->allReduceBlockVal(next_event, next_event_global, BLOCK_VAL_MIN);

    // If we didn't find any static failures or aftershocks, abort the simulation
    if (sim->isRootNode()) assertThrow(next_event_global.val < DBL_MAX, "System stuck, no blocks to move.");

    // Increment the simulation year to the next failure time and
    // update the slip on all other blocks
    sim->incrementYear(next_event_global.val);

    for (lid=0; lid<sim->numLocalBlocks(); ++lid) {
        BlockID gid = sim->getGlobalBID(lid);
        Block &local_block = sim->getBlock(gid);
        double cur_slip_deficit = sim->getSlipDeficit(gid);
        sim->setSlipDeficit(gid, cur_slip_deficit-local_block.slip_rate()*convert.year2sec(next_event_global.val)*(1.0-local_block.aseismic()));
    }

    // Recalculate the stress on all blocks with the new slip deficits
    stressRecompute();

    // Record the current event
    new_event.setEventTriggerOnThisNode(next_event_global.block_id==next_static_fail.block_id);
    new_event.setEventTrigger(next_event_global.block_id);
    new_event.setEventYear(sim->getYear());
    new_event.setEventNumber(sim->getEventCount());
    sim->addEvent(new_event);

    if (sim->getYear() > sim->getSimDuration()) return SIM_STOP_REQUIRED;
    else return SIM_CONTINUE;
}
예제 #5
0
void GreensFuncCalcBarnesHut::bhInnerCalc(Simulation *sim, quakelib::Octree<3> *tree, const BlockID &bid) {
    Block                               &source_block = sim->getBlock(bid);
    BlockIDList                         target_blocks;
    BlockIDList::const_iterator         bit;
    BlockList::const_iterator           it;
    double                              stress_values[2];
    quakelib::Vec<3>                    target_point;
    quakelib::Octree<3>                 *local_node;
    quakelib::RectBound<3>              local_bound;
    BlockID                             start_id, end_id;
    std::set<std::pair<BlockID, BlockID> >::const_iterator  sbit;
    unsigned int                        i;
    quakelib::Vec<3>                    mean_center, mean_normal, rake_vec, up_vec, v0, v1, v2, v3;
    double                              mean_dip, mean_rake, mean_area, side_length;
    double                              mean_lambda, mean_mu, mean_unit_slip;
    Block                               repr_block;

    // Allocate row for this block (if using compressible matrices)
    sim->allocateShearNormalRows(bid);

    target_point = sim->getBlock(bid).center();
    local_node = tree->get_leaf_containing_point(target_point);
    local_bound = local_node->bound();

    quakelib::BHAnalyzer<3>             bh_analysis(local_bound, sim->getBarnesHutTheta());
    tree->traverse(&bh_analysis);

    // Ensure that we got all the fault segments
    assertThrow(bh_analysis.num_checks()==sim->numGlobalBlocks(), "Didn't find all necessary points in the octree.");

    sbit = bh_analysis.run_bounds.begin();

    for (; sbit!=bh_analysis.run_bounds.end(); ++sbit) {
        start_id = sbit->first;
        end_id = sbit->second;

        // Make a list of target blocks
        target_blocks.clear();

        for (i=start_id; i!=end_id; ++i) target_blocks.push_back(i);

        // Reset mean values/vectors
        mean_center = rake_vec = mean_normal = quakelib::Vec<3>();
        mean_dip = mean_rake = mean_area = mean_lambda = mean_mu = mean_unit_slip = 0;

        // Convert the strains to Greens values and record them
        for (bit=target_blocks.begin(); bit!=target_blocks.end(); ++bit) {
            Block target_block = sim->getBlock(*bit);

            mean_center += target_block.center();
            rake_vec += target_block.rake_vector();
            mean_rake += target_block.rake();
            mean_area += target_block.area();
            mean_normal += target_block.normal();
            mean_lambda += target_block.lame_lambda();
            mean_mu += target_block.lame_mu();
            mean_unit_slip += target_block.slip_rate();
        }

        mean_center /= target_blocks.size();
        rake_vec /= target_blocks.size();
        mean_rake /= target_blocks.size();
        mean_area /= target_blocks.size();
        mean_lambda /= target_blocks.size();
        mean_mu /= target_blocks.size();
        mean_unit_slip  /= target_blocks.size();
        mean_normal /= target_blocks.size();

        side_length = sqrt(mean_area);
        up_vec = -mean_normal.cross(rake_vec);

        v0 = mean_center + rake_vec*(side_length/2) + up_vec*(side_length/2);
        v1 = mean_center + rake_vec*(side_length/2) - up_vec*(side_length/2);
        v2 = mean_center - rake_vec*(side_length/2) - up_vec*(side_length/2);
        v3 = mean_center - rake_vec*(side_length/2) + up_vec*(side_length/2);

        repr_block.set_rake(mean_rake);
        repr_block.set_vert(0, v0);
        repr_block.set_vert(1, v1);
        repr_block.set_vert(2, v2);
        repr_block.set_vert(3, v3);
        repr_block.set_lame_lambda(mean_lambda);
        repr_block.set_lame_mu(mean_mu);
        repr_block.set_slip_rate(mean_unit_slip);

        repr_block.get_rake_and_normal_stress_due_to_block(stress_values, sim->getGreensSampleDistance(), source_block);

        // Set Green's values to averaged values
        for (bit=target_blocks.begin(); bit!=target_blocks.end(); ++bit) {
            sim->setGreens(*bit, bid, stress_values[0], stress_values[1]);
        }
    }

    // Compress the computed matrix row if savings are greater than 30%
    sim->compressShearRow(bid, 0.7);
    sim->compressNormalRow(bid, 0.7);
}
예제 #6
0
void GreensFuncCalc::symmetrizeMatrix(Simulation *sim, GreensValsSparseMatrix &ssh) {
    double      sxrl, sxru;
    int         ir, ic, n;

    // If we're using MPI, exchange Greens values between nodes
    // in order to symmetrize the shear stress matrix
#ifdef MPI_C_FOUND
    int                     i, world_size, local_rank, root_node, num_local_blocks, num_global_blocks;
    int                     *local_counts, *local_ids, *global_ids, *displs;
    GREEN_VAL               *send_buf, *recv_buf;
    MPI_Datatype            data_type;

    // MPI and decomposition values
    world_size = sim->getWorldSize();
    local_rank = sim->getNodeRank();

    // Get the size of the data we will transmit
    if (sizeof(GREEN_VAL)==4) data_type = MPI_FLOAT;
    else if (sizeof(GREEN_VAL)==8) data_type = MPI_DOUBLE;

    // Find out how many local objects each node has
    local_counts = new int[world_size];
    num_local_blocks = sim->numLocalBlocks();
    num_global_blocks = sim->numGlobalBlocks();
    MPI_Allgather(&num_local_blocks, 1, MPI_INT, local_counts, 1, MPI_INT, MPI_COMM_WORLD);

    // Setup array for displacements
    displs = new int[world_size];
    displs[0] = 0;

    for (n=1; n<world_size; ++n) displs[n] = displs[n-1]+local_counts[n-1];

    // Find out the global block IDs for each local block on other nodes
    local_ids = new int[num_local_blocks];

    for (n=0; n<num_local_blocks; ++n) local_ids[n] = sim->getGlobalBID(n);

    global_ids = new int[num_global_blocks];
    MPI_Allgatherv(local_ids, num_local_blocks, MPI_INT, global_ids, local_counts, displs, MPI_INT, MPI_COMM_WORLD);

    // Setup send and receive buffers
    send_buf = new GREEN_VAL[num_global_blocks];
    recv_buf = new GREEN_VAL[num_local_blocks];

    // Go through each of the Greens function rows
    // If we computed the row, send pieces of it to other processors
    // If we need the row for symmetrization, receives pieces of it from another processor
    for (i=0; i<num_global_blocks; ++i) {
        root_node = sim->getBlockNode(i);

        // Fill the send buffer with the appropriate values
        if (root_node == local_rank) {
            for (n=0; n<num_global_blocks; ++n) {
                send_buf[n] = ssh[i][global_ids[n]];
            }
        }

        // Scatter each of the required matrix sections
        // There is no need to send snorm since it isn't used outside the local node
        MPI_Scatterv(send_buf, local_counts, displs, data_type,
                     recv_buf, num_local_blocks, data_type,
                     root_node, MPI_COMM_WORLD);

        // Copy the receive buffer to the matrix for non-local transfers
        for (n=0; n<num_local_blocks; ++n) {
            if (root_node != local_rank) {
                ssh[i][n] = recv_buf[n];
            }
        }
    }

    // use delete [] for c-arrays.
    delete [] local_counts;
    delete [] displs;
    delete [] local_ids;
    delete [] global_ids;
    delete [] send_buf;
    delete [] recv_buf;


#endif

    // Symmetrize the shear stress matrices
    for (ir=0; ir<sim->numGlobalBlocks(); ++ir) {
        bool full_row = sim->isLocalBlockID(ir);
        int num_elems = (full_row ? sim->numGlobalBlocks() : sim->numLocalBlocks());

        for (n=0; n<num_elems; ++n) {
            ic = (full_row ? n : sim->getGlobalBID(n));
            double ir_area, ic_area;
            ir_area = sim->getBlock(ir).area();
            ic_area = sim->getBlock(ic).area();
            assertThrow(ir_area > 0 && ic_area > 0, "Blocks cannot have negative area.");

            int local_ir = (sim->isLocalBlockID(ic) ? ir : sim->getLocalInd(ir));
            sxru=ssh[ir][n]*ic_area;
            sxrl=ssh[ic][local_ir]*ir_area;

            ssh[ir][n]=0.5*(sxrl + sxru)/ic_area;
            ssh[ic][local_ir]=0.5*(sxrl + sxru)/ir_area;
        }
    }
}
/*!
 Determine the next time step in the simulation when a failure occurs.
 Return the block ID of the block responsible for the failure and the timestep until the failure.
 */
void UpdateBlockStress::nextTimeStep(BlockVal &fail_time) {
	BlockList::iterator		it;
	BlockVal				temp_block_fail;
	double					ts;
	VCEvent					new_event;
	BlockID					gid;
	int						lid;
    quakelib::Conversion	convert;
	
	// Set up the temporary buffer and update field
    for(it=sim->begin();it!=sim->end();++it) {
		tmpBuffer[it->getBlockID()] = 0.0;
		
		// Set the update field to be the slip rate of each block
		sim->setUpdateField(it->getBlockID(), it->slip_rate());
    }
	
	// update the temporary buffer with the Greens function applied to the block slip rates
	sim->matrixVectorMultiplyAccum(tmpBuffer,
								   sim->greenShear(),
								   sim->getUpdateFieldPtr(),
								   true);
	
	if (sim->doNormalStress()) {
		for(it=sim->begin();it!=sim->end();++it) {
            sim->setUpdateField(it->getBlockID(), -it->friction()*it->slip_rate());
        }
		sim->matrixVectorMultiplyAccum(tmpBuffer,
									   sim->greenNormal(),
									   sim->getUpdateFieldPtr(),
									   true);
	}
	
	// Go through the blocks and find which one will fail first
    temp_block_fail.val = DBL_MAX;
	temp_block_fail.block_id = UNDEFINED_BLOCK_ID;
	
    for(lid=0;lid<sim->numLocalBlocks();++lid) {
		gid = sim->getGlobalBID(lid);
		Block &block = sim->getBlock(gid);
		// Calculate the time until this block will fail
		// If the block has aseismic slip, the calculation is the exact solution of the
		// differential equation d(cff)/dt = rate_of_stress_change + cff*aseismic_frac*self_shear/recurrence
		if (block.aseismic() > 0) {
			double		A, B, K;
			A = -tmpBuffer[gid];
			B = -block.aseismic()*block.getSelfStresses()/block.getRecurrence();
			K = -log(A+B*block.getCFF())/B;
			ts = K + log(A)/B;
		} else {
			ts = convert.sec2year(block.getCFF()/tmpBuffer[gid]);
		}
		
		// Blocks with negative timesteps are skipped. These effectively mean the block
		// should have failed already but didn't. This can happen in the starting phase
		// of a simulation due to initial stresses. These blocks will fail anyway in the
		// event propagation section, so we can safely ignore them here. However, negative
		// timesteps should not happen after the simulation has progressed for a while.
		if (ts <= 0) continue;
		
		// If the time to slip is less than the current shortest time, record the block
        if(ts < temp_block_fail.val) {
            temp_block_fail.block_id = gid;
            temp_block_fail.val = ts;
        }
    }
	
	// Each node now has the time before the first failure among its blocks
	// Determine the time to first failure over all nodes
	sim->allReduceBlockVal(temp_block_fail, fail_time, BLOCK_VAL_MIN);
	
	// If we didn't find any blocks that slipped, abort the simulation
	assertThrow(fail_time.val < DBL_MAX, "System stuck, no blocks to move.");
	
	// Setup the current event to have the trigger block ID and time
	new_event.setEventTriggerOnThisNode(fail_time.block_id==temp_block_fail.block_id);
	new_event.setEventTrigger(fail_time.block_id);
	new_event.setEventYear(sim->getYear()+fail_time.val);
	new_event.setEventNumber(sim->getEventCount());
	sim->addEvent(new_event);
}
예제 #8
0
int main (int argc, char **argv) {
    // Initialize the world (where the squares live), squares and vertices
    tsunamisquares::World                       this_world;
    tsunamisquares::SquareIDSet::const_iterator it;
    tsunamisquares::SquareIDSet                 ids;
    std::ifstream								param_file;
    std::ofstream                               out_file;
    clock_t                                     start,end;


    // -------------------------------------------------------------------------------- //
    ///////////          CONSTANTS         ////////////
    // -------------------------------------------------------------------------------- //
    /*  Wilson: Trying a simple input file for these parameters.  Can be improved in the future for readability and suseptability to errors
    const std::string   out_file_name    = "tsunami_output.txt"; // name this relevant
    const std::string   bathy_file       = "bathymetry/Pacific_900.txt"; // name this relevant
    //const std::string   kml_file         = "local/Pacific_36.kml";
    // const std::string   deformation_file = "local/Channel_Islands_test_bump.txt"; // kasey says we dont need this now
    // until later
    
    // Diffusion constant (fit to a reasonable looking sim)
    double D = 140616.45; //140616.45;
    // Flattening the bathymetry to a constant depth (negative for below sea level)
    double new_depth = -100.0;
    // Bumping up the bottom
    double bump_height = 50.0;
    // Number of times to move squares
    int N_steps = 20; //number of time steps 10 is fine, to see a bit of movement
    // because boundaries aren't defined very well, we limit the time steps whenever the water hits the walls of things
    // Updating intervals, etc.
    int current_step = 0;
    int update_step = 1;
    int save_step = 1;
    double time = 0.0;
    int output_num_digits_for_percent = 3;
    */

    // Ensure we are given the parameter file name
	assertThrow(argc == 2, "usage: param_file");

	param_file.open(argv[argc-1]);


	std::string 				param_name;
	std::string					value;
	std::vector<std::string>	param_values;

	while ( param_file >> param_name >> value )
	{
	  param_values.push_back(value);
	}

    const std::string   out_file_name    	= param_values[0];
    const std::string   bathy_file       	= param_values[1];
    const std::string   kml_file         	= param_values[2];
    const std::string   deformation_file 	= param_values[3];

    // Diffusion constant (fit to a reasonable looking sim)
    double 	D 								= atof(param_values[4].c_str()); //140616.45;
    // Time step in seconds
    double  dt_param								= atof(param_values[5].c_str());
    // Number of times to move squares
    int 	N_steps 						= atof(param_values[6].c_str()); //number of time steps 10 is fine, to see a bit of movement
    // because boundaries aren't defined very well, we limit the time steps whenever the water hits the walls of things
    // Updating intervals, etc.
    int 	current_step 					= atof(param_values[7].c_str());
    int 	update_step 					= atof(param_values[8].c_str());
    int 	save_step 						= atof(param_values[9].c_str());
    double 	time 							= atof(param_values[10].c_str());
    int 	output_num_digits_for_percent 	= atof(param_values[11].c_str());
    // Flattening the bathymetry to a constant depth (negative for below sea level)
	double 	flat_depth 						= atof(param_values[12].c_str());
	// Bumping up the bottom
	double 	bump_height 					= atof(param_values[13].c_str());
    //Boolean to decide whether to flatten the seafloor before running, for testing purposes
    bool	flatten_bool					= atof(param_values[14].c_str());


    // Header for the simulation output
    const std::string   header = "# time \t lon \t\t lat \t\t water height \t altitude \n";
    
    
    // -------------------------------------------------------------------------------- //
    ///////                Simulation Initialization and Loading                   ///////
    // --------------------------------------------------------------------------------//
    start = clock();
    // Read in the bathymetry data
    this_world.clear();
    std::cout << std::endl << "Reading..."   << bathy_file.c_str() << std::endl;
    this_world.read_bathymetry(bathy_file.c_str());
    // Index the neighbors by left/right/top etc.
    std::cout << "Indexing neighbors......" << std::endl;
    this_world.computeNeighbors();
    
    // Compute the time step given the diffusion constant D
    //double dt = (double) (int) this_world.square(0).Lx()*this_world.square(0).Ly()/(2*D); //seconds
    // Use file-provided time step.
    double dt = dt_param;
    
    // Gather model information
    this_world.info();
    int num_lats = this_world.num_lats();
    int num_lons = this_world.num_lons();
    std::cout << "Lons by Lats = (" << num_lons << ", " << num_lats << ")...";
    ids = this_world.getSquareIDs();
    double max_time = N_steps*dt;
    

    //tsunamisquares::SquareIDSet valids = this_world.square(0).get_valid_neighbors();
    //tsunamisquares::SquareIDSet::const_iterator vit;

    //for (vit=valids.begin(); vit!=valids.end(); ++vit) {
    //    std::cout << *vit << std::endl;
    //}

    // Write KML model
    //std::cout << "Writing KML..."   << kml_file.c_str() << "  ...";
    //this_world.write_file_kml(kml_file.c_str());

    // Flatten the bottom for simple simulation test cases, do not do this for tsunami simulations
    if(flatten_bool){
    	std::cout << "Flattening the bottom..."<< std::endl;
    	this_world.flattenBottom(flat_depth);
    }
    
    // for (int pixel = 0; pixel++; pixel < (int) (num_lons*0.75)){
    //   tsunamisquares::UIndex landcenter = (int) (pixel);
    //   tsunamisquares::UIndex landright   = this_world.square(landcentral).right();
    //   this_world.deformBottom(landright,  bump_height);
    // }

    // Put water into squares to bring water level up to sealevel.
    //std::cout << "Filling with water..." << std::flush;
    //this_world.fillToSeaLevel();

    // for (int pixel_lons = 0; pixel_lons++; pixel_lons < num_lons){
    //   for ( int pixel_lats = 0; pixel_lats++; pixel_lats < ((int) num_lats*0.5) )
    //     this_world.deformBottom(pixel_lons*pixel_lats,  bump_height*10);
    // }
    
    // Put water into squares to bring water level up to sealevel.
    std::cout << "Filling with water..." << std::endl;
	this_world.fillToSeaLevel();

    // --------------------------------------------------------------------------------//
    //            Sea Floor Deformation and Initial Conditions                         //
    // --------------------------------------------------------------------------------//
    std::cout << "Deforming the bottom... " << std::endl;

    //   == DEFORM FROM FILE ==

    std::cout << "\t Deforming from file" << std::endl;

    this_world.deformFromFile(deformation_file);


    //this_world.diffuseSquares(dt);

    // --------------------------------------------------------------------------------//
    // --==                         File I/O Preparation                          --== //
    // --------------------------------------------------------------------------------//
    out_file.open(out_file_name.c_str());
    out_file << header.c_str();
    std::cout.precision(output_num_digits_for_percent);



    // --------------------------------------------------------------------------------//
    // --========-           Begin the Simulation; Move the Squares          ----====- //
    // --------------------------------------------------------------------------------//
    std::cout << "Moving squares....time_step=" <<dt << "...";
    while (time < max_time) {
        // If this is a writing step, print status
        if (current_step%update_step == 0) {
            std::cout << ".." << (100.0*current_step)/N_steps << "%..";
            std::cout << std::flush;
        }

        // Write the current state to file
        if (current_step%save_step == 0) {
            for (it=ids.begin(); it!=ids.end(); ++it) {
                this_world.write_square_ascii(out_file, time, *it);
            }
        }
        // Move the squares
        this_world.moveSquares(dt);
        //TODO: turn back on:
        this_world.diffuseSquares(dt); //smoothing operation
        time += dt;
        current_step += 1;
    }
    out_file.close();


    // --------------------------------------------------------------------------------//
    // --========---                    Wrap up and Reporting            ---=======--- //
    // --------------------------------------------------------------------------------//
    std::cout << std::endl << "Results written to " << out_file_name << std::endl;
    end = clock();
    std::cout.precision(2+output_num_digits_for_percent);
    std::cout << "Total time: " << (float(end)-float(start))/CLOCKS_PER_SEC << " secs." << std::endl << std::endl;
    return 0;
}