/*!
 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				fail_time;
    quakelib::Conversion	convert;
	
	// Calculate the current rates of stress change on all blocks
	stressRecompute();
	
	// Given the rates of change, determine which block will fail next
	fail_time.block_id = UNDEFINED_BLOCK_ID;
	nextTimeStep(fail_time);
	
	// Increment the simulation year to the next failure time and
	// update the slip on all other blocks
    sim->incrementYear(fail_time.val);
    for(lid=0;lid<sim->numLocalBlocks();++lid) {
		Block &local_block = sim->getBlock(sim->getGlobalBID(lid));
		local_block.state.slipDeficit -= local_block.slip_rate()*convert.year2sec(fail_time.val)*(1.0-local_block.aseismic());
    }
	
	// Recalculate the stress on all blocks with the new slip deficits
    stressRecompute();
	
	if (sim->getYear() > sim->getSimDuration()) return SIM_STOP_REQUIRED;
	else return SIM_CONTINUE;
}
Beispiel #2
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;
}
/*!
 Initialize the stress calculation by setting initial block slip and stresses
 then calculating the stress in the whole system.
 */
void UpdateBlockStress::init(SimFramework *_sim) {
	BlockList::iterator	it;
	BlockID				bid;
	
	sim = static_cast<VCSimulation*>(_sim);
	tmpBuffer = new double[sim->numGlobalBlocks()];
	
    for(it=sim->begin();it!=sim->end();++it) {
		bid = it->getBlockID();
		
		// Set stresses to their specified initial values
		sim->setShearStress(bid, it->getInitShearStress());
		sim->setNormalStress(bid, it->getInitNormalStress());
		
		// Give each block a different random seed based on the block ID
        it->state.rand.init(bid*17);
        //double a = sim->getSlipDeficitNoise();		// TODO: move slip deficit noise to AddNoise class
        // noise in the range [1-a, 1+a)
        //double rn = (1.0-a) + 2*a*it->state.rand.nextDouble();
        //it->state.slipDeficit = -0.5*rn*it->slipCharacteristic();
        it->state.slipDeficit = 0;
		if (sim->isLocalBlockID(bid)) {
			sim->decompressNormalRow(bid);
			//sim->setGreenNormal(bid, bid, 0.0);  // Erase diagonal for normal Greens matrix
			sim->compressNormalRow(bid, 0.7);
		}
    }
	
	// Compute initial stress on all blocks
    stressRecompute();
}
Beispiel #4
0
/*!
 Initialize the stress calculation by setting initial block slip and stresses
 then calculating the stress in the whole system.
 */
void UpdateBlockStress::init(SimFramework *_sim) {
    BlockList::iterator nt;
    BlockID             gid;
    int                 lid;
    double              stress_drop, norm_velocity;

    sim = static_cast<Simulation *>(_sim);
    tmpBuffer = new double[sim->numGlobalBlocks()];

    // All processes need the friction values for all blocks, so we set rhogd here
    // and transfer stress drop values between nodes later
    for (lid=0; lid<sim->numLocalBlocks(); ++lid) {
        double rho = 5.515e3;      // density of rock in kg m^-3
        double g = 9.81;           // force of gravity in m s^-2
        double depth = -sim->getBlock(gid).center()[2];  // depth of block center in m

        gid = sim->getGlobalBID(lid);

        sim->setRhogd(gid, rho*g*depth);       // kg m^-3 * m s^-2 * m = kg m^-1 * s^-2 = Pa

        sim->setDynamicVal(gid, sim->getDynamic());
        sim->setFailed(gid, false);

        // Set stresses to their specified initial values
        sim->setShearStress(gid, sim->getInitShearStress(gid));
        sim->setNormalStress(gid, sim->getInitNormalStress(gid));

        // Set the stress drop based on the Greens function calculations
        stress_drop = 0;
        norm_velocity = sim->getBlock(gid).slip_rate();

        for (nt=sim->begin(); nt!=sim->end(); ++nt) {
            stress_drop += (nt->slip_rate()/norm_velocity)*sim->getGreenShear(gid, nt->getBlockID());
        }

        sim->setStressDrop(gid, sim->getBlock(gid).max_slip()*stress_drop);

        // noise in the range [1-a, 1+a)
        sim->setSlipDeficit(gid, 0);

        if (sim->isLocalBlockID(gid)) {
            sim->decompressNormalRow(gid);
            //sim->setGreenNormal(bid, bid, 0.0);  // Erase diagonal for normal Greens matrix
            sim->compressNormalRow(gid, 0.7);
        }
    }

#ifdef MPI_C_FOUND

    // Transfer stress drop values between nodes
    // This is needed for normal stress Green's calculations
    for (gid=0; gid<sim->numGlobalBlocks(); ++gid) {
        double     stress_drop;

        if (sim->isLocalBlockID(gid)) {
            stress_drop = sim->getStressDrop(gid);
        }

        MPI_Bcast(&stress_drop, 1, MPI_DOUBLE, sim->getBlockNode(gid), MPI_COMM_WORLD);

        if (!sim->isLocalBlockID(gid)) {
            sim->setStressDrop(gid, stress_drop);
        }
    }

#endif

    // Compute initial stress on all blocks
    stressRecompute();
}