bool Convergence_tester_DRbar<Model>::accuracy_goal_reached()
{
   current_model = *model;
   bool precision_reached = false;

   if (it_count > 0) {
      run_to_scale();
      const double scale_accuracy_goal = accuracy_goal * 16*M_PI*M_PI;
      if (rel_scale_difference() < scale_accuracy_goal) {
         current_accuracy = max_rel_diff();
         precision_reached = current_accuracy < accuracy_goal;
         VERBOSE_MSG("Convergence_tester_DRbar: current accuracy = "
                     << current_accuracy
                     << ", accuracy goal = " << accuracy_goal);
      } else {
         VERBOSE_MSG("scale has changed by " << scale_difference()
                     << " GeV (" << rel_scale_difference()
                     << "), skipping parameter comparison");
      }
   }

   // save old model parameters
   last_iteration_model = current_model;
   ++it_count;

   return precision_reached;
}
Example #2
0
void RGFlow<Two_scale>::solve()
{
   check_setup();

   unsigned int max_iterations = get_max_iterations();
   if (models.empty() || max_iterations == 0)
      return;

   initial_guess();

   iteration = 0;
   bool accuracy_reached = false;
   while (iteration < max_iterations && !accuracy_reached) {
      update_running_precision();
      run_up();
      run_down();
      accuracy_reached = accuracy_goal_reached();
      ++iteration;
   }

   apply_lowest_constraint();

   if (!accuracy_reached)
      throw NoConvergenceError(max_iterations);

   VERBOSE_MSG("convergence reached after " << iteration << " iterations");
}
Example #3
0
void RGFlow<Two_scale>::run_up()
{
   VERBOSE_MSG("> running tower up (iteration " << iteration << ") ...");
   const size_t number_of_models = models.size();
   for (size_t m = 0; m < number_of_models; ++m) {
      TModel* model = models[m];
      model->model->set_precision(get_precision());
      VERBOSE_MSG("> \tselecting model " << model->model->name());
      // apply all constraints
      const size_t n_upwards_constraints = model->upwards_constraints.size();
      for (size_t c = 0; c < n_upwards_constraints; ++c) {
         Constraint<Two_scale>* constraint = model->upwards_constraints[c];
         const double scale = constraint->get_scale();
         VERBOSE_MSG("> \t\tselecting constraint " << c << " at scale " << scale);
         VERBOSE_MSG("> \t\t\trunning model to scale " << scale);
         if (model->model->run_to(scale))
            throw NonPerturbativeRunningError(scale);
         VERBOSE_MSG("> \t\t\tapplying constraint");
         constraint->apply();
      }
      // apply matching condition if this is not the last model
      if (m != number_of_models - 1) {
         VERBOSE_MSG("> \tmatching to model " << models[m + 1]->model->name());
         Matching<Two_scale>* mc = model->matching_condition;
         mc->match_low_to_high_scale_model();
      }
   }
   VERBOSE_MSG("> running up finished");
}
Example #4
0
void RGFlow<Two_scale>::apply_lowest_constraint()
{
   if (models.empty())
      return;

   TModel* model = models[0];
   model_at_this_scale = model->model;

   if (model->downwards_constraints.empty())
      return;

   Constraint<Two_scale>* constraint = model->downwards_constraints.back();
   const double scale = constraint->get_scale();
   VERBOSE_MSG("| selecting constraint 0 at scale " << scale);
   VERBOSE_MSG("| \trunning model " << model->model->name() << " to scale " << scale);
   if (model->model->run_to(scale))
      throw NonPerturbativeRunningError(scale);
   VERBOSE_MSG("| \tapplying constraint");
   constraint->apply();
}
void MSSM_spectrum_plotter::write_to_file(const std::string& file_name) const
{
   if (spectrum.empty())
      return;

   std::ofstream filestr(file_name.c_str(), std::ios::out);
   VERBOSE_MSG("MSSM_spectrum_plotter::write_to_file: opening file: "
               << file_name.c_str());
   if (filestr.fail()) {
      ERROR("MSSM_spectrum_plotter::write_to_file: can't open file "
            << file_name);
      return;
   }

   filestr << "### one-loop pole masses (Q = " << scale << " GeV)\n";
   write_spectrum(spectrum, filestr);

   filestr.close();
   VERBOSE_MSG("MSSM_spectrum_plotter::write_to_file: file written: "
               << file_name.c_str());
}
Example #6
0
void Trace( std::vector<ListOfHBonds *> *HBStrings,
            HBVecIter *TrjIdx_iter )
{
	time_t timer = time(NULL);

	for( unsigned int f=0; f < TrjIdx_iter->size(); ++f )
	{
#ifdef PTHREADS
		struct worker_data_s wd;
		wd.jobtype = THREAD_JOB_TRACE;
		wd.jobnum = f;
		wd.num_threads = NumberOfCPUs();
		wd.HBit = &(TrjIdx_iter->at(f));
		wd.HBStrings = new std::vector<ListOfHBonds *>;
		wd.HBStrings->reserve(5000);

		inQueue.push(wd);
#else
		if (  (difftime(time(NULL),timer) > 1.0) || ((f+1)==TrjIdx_iter->size())  )
		{
			VERBOSE_RMSG("Tracing HB strings: frame " << f+1 <<"/"<< TrjIdx_iter->size() << ".");
			timer = time(NULL);
		}

		HBVec::iterator iter_hb = TrjIdx_iter->at(f).begin;
		TraceThread( HBStrings, &TrjIdx_iter->at(f) );
#endif // PTHREADS
	}
#ifdef PTHREADS
	// Get the results back from the worker threads.
	for( unsigned int f=0; f < TrjIdx_iter->size(); ++f )
	{
		if (  (difftime(time(NULL),timer) > 1.0) || ((f+1)==TrjIdx_iter->size())  )
		{
			VERBOSE_RMSG("Tracing HB strings: frame " << f+1 <<"/"<< TrjIdx_iter->size() << ".");
			timer = time(NULL);
		}

		struct worker_data_s wd = outQueue.pop();
		HBStrings->reserve( TrjIdx_iter->size()*wd.HBStrings->size() );
		HBStrings->insert( HBStrings->end(),
		                   wd.HBStrings->begin(),
		                   wd.HBStrings->end() );

		wd.HBStrings->clear();
		delete wd.HBStrings;
	}
#endif // PTHREADS
	VERBOSE_MSG("Tracing HB strings: frame " << TrjIdx_iter->size() <<"/"<< TrjIdx_iter->size() << ".");
}
Example #7
0
int open_pclta( struct inode *inode, struct file *file )
{
	struct pclta_device *device = pclta_device_table[MINOR(inode->i_rdev)];
	file->private_data = device;

//	file->f_op=&pclta_fops;  karl test 13/07/2000

	CALL_MSG("open_pclta()", ++pclta_call_level );
	
	if( device == NULL ) {
		RETURN_MSG("open_pclta() ENXIO", pclta_call_level-- );
		return -ENXIO; // no such device
	}
	
	if( device->state != Offline ) {
		RETURN_MSG("open_pclta() EBUSY", pclta_call_level-- );
		return -EBUSY; // device busy
	}
	
	if( !open_device( device ) ) {
		RETURN_MSG("open_pclta() ENOMEM", pclta_call_level-- );
		return -ENOMEM; // out of memory
	}
	
	// program interrupt request line
//	outb_p(irq_mask[device->interrupt], selirq_reg(device->base_address) );  //removed 07/07/200  karl. added init_hw below

    DEBUG_MSG("Base Addy=0x0%x ; IRQ=%d ; IRQ MASK = 0x0%x \n",device->base_address, device->interrupt ,pclta_irq_mask[device->interrupt]);
    init_hw( device->base_address, pclta_irq_mask[device->interrupt], device->txcvr_clock );

    if( ! wait_reset(device->base_address, 500 ) ) {
        VERBOSE_MSG( "error(%d) PCLTA_LRESET.\n", PCLTA_LRESET );
        return -EBUSY;
    } // waiting to leave reset state
	
		
	device->state = Idle;
	
	//enable_irq( device->interrupt );  // karl's test  07/07/2000

	MOD_INC_USE_COUNT;
	
	RETURN_MSG("open_pclta() OK", pclta_call_level-- );
	return 0;
}
/**
 * Apply all experimental constraints to the Standard Model class.  It
 * is assumed that the Standard Model class is at the Z mass scale.
 * If this is not the case, a warning is printed.
 */
void StandardModel_exp_constraint::apply()
{
   assert(sm && "pointer to StandardModel<Two_scale> must not be zero");

   VERBOSE_MSG("Applying SM experimental constraints at scale "
               << sm->get_scale());
   if (std::fabs(Electroweak_constants::MZ - sm->get_scale()) > 1.0)
      WARNING("Applying the experimental constraints "
              "of StandardModel<Two_scale> at scale " << sm->get_scale()
              << " != MZ is not save!");

   sm->setYukawaElement(StandardModel<Two_scale>::YU, 3, 3, Electroweak_constants::yt);
   sm->setYukawaElement(StandardModel<Two_scale>::YD, 3, 3, Electroweak_constants::yb);
   sm->setYukawaElement(StandardModel<Two_scale>::YE, 3, 3, Electroweak_constants::ytau);
   sm->setGaugeCoupling(1, Electroweak_constants::g1);
   sm->setGaugeCoupling(2, Electroweak_constants::g2);
   sm->setGaugeCoupling(3, Electroweak_constants::g3);
}
Example #9
0
void RGFlow<Two_scale>::run_down()
{
   assert(models.size() > 0 && "model size must not be zero");
   VERBOSE_MSG("< running tower down ...");
   const size_t number_of_models = models.size();
   for (long m = number_of_models - 1; m >= 0; --m) {
      TModel* model = models[m];
      VERBOSE_MSG("< \tselecting model " << model->model->name());
      // apply all constraints:
      // If m is the last model, do not apply the highest constraint,
      // because it was already appied when we ran up.
      const size_t c_begin = (m + 1 == (long)number_of_models ? 1 : 0);
      const size_t c_end = model->downwards_constraints.size();
      for (size_t c = c_begin; c < c_end; ++c) {
         Constraint<Two_scale>* constraint = model->downwards_constraints[c];
         const double scale = constraint->get_scale();
         VERBOSE_MSG("< \t\tselecting constraint " << c << " at scale " << scale);
         VERBOSE_MSG("< \t\t\trunning model to scale " << scale);
         if (model->model->run_to(scale))
            throw NonPerturbativeRunningError(scale);
         // If m is the lowest energy model, do not apply the lowest
         // constraint, because it will be applied when we run up next
         // time.
         if (m != 0 || c + 1 != c_end) {
            VERBOSE_MSG("< \t\t\tapplying constraint");
            constraint->apply();
         }
      }
      // apply matching condition if this is not the first model
      if (m > 0) {
         Matching<Two_scale>* mc = models[m - 1]->matching_condition;
         VERBOSE_MSG("< \tmatching to model " << models[m - 1]->model->name());
         mc->match_high_to_low_scale_model();
      }
   }
   VERBOSE_MSG("< running down finished");
}
Example #10
0
/**
 * main function
 */
int main(int argc, char *argv[])
{
	unsigned int NumBins = 0;
	// Connections filename without the .arc extension for discover, with
	// extension for LAMMPS.
	char *fileData    =  NULL;
	char *fileTrj     =  NULL; // LAMMPS trajectory file.
	char *fileMols    =  NULL; // Molecular definition file for LAMMPS.
	char *ofPrefix    =  NULL; // Prefix for output filename.
	char *ofSuffix    =  NULL; // Suffix for output filename.
	double rCutoff    =   0.0;  // Distance Cutoff for Hydrogen bonds.
	double angleCutoff= 180.0; // Angle Cutoff for Hydrogen bonds.
	// Matching keys for hydrogens and acceptors.
	struct HydrogenBondMatching match;
	int   flag[(unsigned int)Flags::COUNT] = {}; // Initialize all elements of flag to zero.
	unsigned int flags = 0;

	// Read command line arguments.
	int c;
	while(1)
	{
		static struct option long_options[] =
		{
			/* These options set a flag. */
			{"verbose"     , no_argument, &flag[0],  (unsigned int)Flags::VERBOSE      },
			{"brief"       , no_argument, &flag[0],  0            },
			{"povray"      , no_argument, &flag[1],  (unsigned int)Flags::POVRAY       },
			{"lifetime"    , no_argument, &flag[2],  (unsigned int)Flags::LIFETIME     },
			{"lengths"     , no_argument, &flag[3],  (unsigned int)Flags::LENGTHS      },
			{"angles"      , no_argument, &flag[4],  (unsigned int)Flags::ANGLES       },
			{"sizehist"    , no_argument, &flag[5],  (unsigned int)Flags::SIZE_HIST    },
			{"neighborhist", no_argument, &flag[6],  (unsigned int)Flags::NEIGHBOR_HIST},
			{"json"        , no_argument, &flag[7],  (unsigned int)Flags::JSON         },
			{"incell"      , no_argument, &flag[8],  (unsigned int)Flags::INCELL       },
			{"jsonall"     , no_argument, &flag[9],  (unsigned int)Flags::JSONALL      },
			{"all"         , no_argument, &flag[10], (unsigned int)Flags::ALL          },
			{"list"        , no_argument, &flag[11],  (unsigned int)Flags::LIST       },
			/* These options don’t set a flag.
			   We distinguish them by their indices. */
			{"input",       required_argument, 0, 'i'},
			{"trajectory",  required_argument, 0, 't'},
			{"molecules",   required_argument, 0, 'm'},
			{"outprefix",   required_argument, 0, 'p'},
			{"outsuffix",   required_argument, 0, 's'},
			{"bins",        required_argument, 0, 'b'},
			{"rcutoff",     required_argument, 0, 'r'},
			{"anglecutoff", required_argument, 0, 'a'},
			{"hydrogen",    required_argument, 0, 'H'},
			{"acceptor",    required_argument, 0, 'A'},
			{"help",        no_argument,       0, 'h'},
			{0, 0, 0, 0}
		};

		/* getopt_long stores the option index here. */
		int option_index = 0;

		c = getopt_long (argc, argv, "i:t:m:p:s:f:l:b:r:a:H:A:h",
		                 long_options, &option_index);

		/* Detect the end of the options. */
		if (c == -1)
			break;

		switch (c)
		{
			case 0:
				/* If this option set a flag, do nothing else now. */
				if (long_options[option_index].flag != 0)
					break;
				std::cout << "Option: " << long_options[option_index].name;
				if (optarg)
					std::cout << " with arg " <<  optarg <<"\n";
				break;
			case 'i':
				fileData = optarg;
				break;
			case 't':
				fileTrj = optarg;
				break;
			case 'm':
				fileMols = optarg;
				break;
			case 'p':
				ofPrefix = optarg;
				break;
			case 's':
				ofSuffix = optarg;
				break;
			case 'b':
				NumBins = atoi(optarg);
				break;
			case 'r':
				rCutoff = atof(optarg);
				break;
			case 'a':
				angleCutoff = atof(optarg);
				break;
			case 'H':
				match.Hydrogens.push_back(optarg);
				break;
			case 'A':
				match.Acceptors.push_back(optarg);
				break;
			case 'h':
			case '?':
			default:
				Help(argv[0]);
				return(1);
		}
	}
	// Done reading command line arguments

	if ( match.Hydrogens.size() == 0 ) {
		Help(argv[0]);
		BRIEF_MSG("\nError: Must specify at least one type of Hydrogen.");
		return EXIT_FAILURE;
	}
	if ( match.Acceptors.size() == 0 ) {
		Help(argv[0]);
		BRIEF_MSG("\nError: Must specify at least one type of Acceptor.");
		return EXIT_FAILURE;
	}
	// Set the flags;
	for ( unsigned int i=0; i < (unsigned int)Flags::COUNT; i++ ) {
		flags |= flag[i];
	}

	if ( flags & Flags::VERBOSE ) THB_VERBOSE=true;

	if ( (fileData == NULL) )
	{
		Help(argv[0]);
		BRIEF_MSG("\nError: Must specify an input file.");
		return EXIT_FAILURE;
	}

	if ( (fileTrj != NULL) && (fileMols == NULL) )
	{
		Help(argv[0]);
		BRIEF_MSG("\nError: When specifying a trajectory file, must also specify a molecule file.");
		return EXIT_FAILURE;
	}

	if ( (fileMols != NULL) && (fileTrj == NULL) )
	{
		Help(argv[0]);
		BRIEF_MSG("\nError: When specifying a molecule file, must also specify an trajectory file.");
		return EXIT_FAILURE;
	}

	if ( (flags & Flags::SIZE_HIST) && (ofPrefix == NULL) )
	{
		Help(argv[0]);
		BRIEF_MSG("\nError: Must specify a prefix for the output file.");
		return EXIT_FAILURE;
	}

	VERBOSE_MSG("\t--- Calculations ---");
	if ( flags & Flags::LIFETIME )     VERBOSE_MSG("\tHydrogen bond lifetime correlations");
	if ( flags & Flags::SIZE_HIST)     VERBOSE_MSG("\tChain lengths in each frame");
	if ( flags & Flags::NEIGHBOR_HIST) VERBOSE_MSG("\t- Consolidated chain lengths");
	if ( flags & Flags::LENGTHS)       VERBOSE_MSG("\tHydrogen - Acceptor distances");
	if ( flags & Flags::ANGLES)        VERBOSE_MSG("\tHydrogen bond angles");
	if ( flags & Flags::LIST)          VERBOSE_MSG("\tHydrogen bond list");
	VERBOSE_MSG("\t--------------------\n");

#ifdef PTHREADS
	VERBOSE_MSG("Starting " << NumberOfCPUs() << " threads.");

	std::vector<MyThread *>MyThreads;
	for (unsigned int j=0; j != NumberOfCPUs(); ++j)
	{
		// Setup and start a thread.
		MyThreads.push_back( new MyThread() );
		MyThreads.at(j)->start();
	}
#endif

	doArcFile(fileData, fileTrj, fileMols,
	          ofPrefix, ofSuffix,
	          &match,
	          rCutoff, angleCutoff,
	          NumBins, flags);

#ifdef PTHREADS
	// Tell the threads to exit.
	// Use a dummy worker_data_s. All that matters is the jobtype. The other
	// parameters are set just to avoid 'uninitialize parameter' warning by
	// the compiler.
	struct worker_data_s wd;
	wd.jobtype = THREAD_JOB_EXIT;
	wd.jobnum  = 0;
	wd.hydrogens = NULL;
	wd.acceptors = NULL;
	wd.hb = NULL;
	wd.TrjIdx = 0;
	wd.num_threads = NumberOfCPUs();
	wd.rCutoff = 0.0;
	wd.angleCutoff = 0.0;

	for (unsigned int j=0; j != NumberOfCPUs(); ++j) {
		inQueue.push(wd); }

	// Wait for the threads to return.
	for (unsigned int j=0; j != NumberOfCPUs(); ++j) {
		MyThreads.at(j)->join(); }

	while ( !MyThreads.empty() ) {
		delete MyThreads.back();
		MyThreads.pop_back();
	}
#endif

	return(0);
}
Example #11
0
void
Lifetime(std::vector< std::vector<bool> >*b,  HBVecIter *TrjIdx_iter )
{
	HBVec::iterator iter_hb;
	HBVec::iterator iter_begin;
	HBVec::iterator iter_end;


	unsigned int MaxNumHBsInFrame=0;

	for(unsigned int i=0; i < TrjIdx_iter->size(); ++i) {
		iter_begin = TrjIdx_iter->at(i).begin;
		iter_end   = TrjIdx_iter->at(i).end;

		unsigned int NumHBsInFrame=0;
		for(iter_hb = iter_begin ; iter_hb < iter_end; ++iter_hb ) {
			++NumHBsInFrame; }

		if (NumHBsInFrame > MaxNumHBsInFrame) {
			MaxNumHBsInFrame = NumHBsInFrame; }
	}

	VERBOSE_MSG("\tMaximum number of Hydrogen bonds in a frame: " << MaxNumHBsInFrame);


	if (MaxNumHBsInFrame == 0)
		return;

	unsigned int NumFrames = TrjIdx_iter->size();
	iter_begin = TrjIdx_iter->at( 0 ).begin;
	iter_end   = TrjIdx_iter->at( 0 ).end;

	HBVec::iterator iter_hbmain = iter_begin;

	// Initialize all elements to false.
	b->assign(MaxNumHBsInFrame, std::vector<bool>(NumFrames,false));

#ifdef PTHREADS
	for( unsigned int jobnum=0; jobnum < NumberOfCPUs(); ++jobnum)
	{
		struct worker_data_s wd;
		wd.jobtype = THREAD_JOB_LIFETIME;
		wd.jobnum = jobnum;
		wd.num_threads = NumberOfCPUs();
		wd.TrjIdx_iter = TrjIdx_iter;

		wd.b = new std::vector< std::vector<bool> >(MaxNumHBsInFrame,
		                                            std::vector<bool>(NumFrames,false));

		inQueue.push(wd);
	}

	// Get the results back from the worker threads.
	struct worker_data_s wd[NumberOfCPUs()];
	for( unsigned int jobnum=0; jobnum < NumberOfCPUs(); ++jobnum) {
		wd[jobnum] = outQueue.pop(); }

	// Merge the results, if any b->at(i).at(j) is true, set it.
	for ( unsigned int i=0; i < MaxNumHBsInFrame; ++i ) {
		for ( unsigned int j=0; j < NumFrames; ++j ) {
			for ( unsigned int t=0; t < NumberOfCPUs(); ++t ) {
				if ( wd[t].b->at(i).at(j) ) {
					b->at(i).at(j) = true;
					break;
				}
			}
		}
	}

	for ( unsigned int i=0; i < NumberOfCPUs(); ++i ) {
		delete wd[i].b; }
#else
	LifetimeThread( b, TrjIdx_iter );
#endif // PTHREADS
}
Example #12
0
bool probe_hardware( int minor )
{
    int erc, trans;
    byte rx_buffer[256];
    int port = base_address[minor];
    int irq  = pclta_interrupt[minor];
    struct pclta_device * device;

    if( !port || !irq )
    	return 0;

    VERBOSE_MSG( "probing minor = %d, I/O = %#x-%#x, interrupt request = %d ... ",
        	minor, port, port+3, irq );
	
    if( 0 > check_region( port, 4 ) ) {
        VERBOSE_MSG( "error(%d) PCLTA_IOPERM.\n", PCLTA_IOPERM );
        return false;
    }

    init_hw( port, 0x00, CLK_10 ); // initialize device hardware, no IRQ

    if( ! wait_reset( port, 500 ) ) {
        VERBOSE_MSG( "error(%d) PCLTA_LRESET.\n", PCLTA_LRESET );
        return false;
    } // waiting to leave reset state

    setup_timeout( 200 );
    while( !pclta_timeout );
    // Why wait? Because, when PCLTA gets out of RESET state, it sets
    // status register BEFORE preparing uplink reset. So, I read the
    // packet of length 0 and get an error. Stupid!

	// wait for reset command response
    if( ! wait_uplink_buffer( port, 500, rx_buffer ) ) {
        VERBOSE_MSG( "error(%d) PCLTA_RESP.  \n", PCLTA_RESP );
        return false;
    }

	// make sure the reset was successful
    if( rx_buffer[0] != 1 || rx_buffer[1] != niRESET ) {
        VERBOSE_MSG( "error(%d) PCLTA_RESP. Reset not successfull. \n", PCLTA_RESP );
        return false;
    }

    // set up internal interrupt register
    write_byte_wait( port, CMD_XFER );
    write_byte_wait( port, 2 );
    write_byte_wait( port, niIRQENA );
    write_byte_wait( port, IRQPLRTY | RESET_ENABLE | DLREADY_ENABLE | DLPBA_ENABLE
	  		| DLBA_ENABLE | ULREADY_ENABLE );

    // write a command to get transciever status
    write_byte_wait( port, CMD_XFER );
    write_byte_wait( port, 1 );
    write_byte_wait( port, niSSTATUS );

	// wait for response
    if( ! wait_uplink_buffer( port, 500, rx_buffer ) ) {
        VERBOSE_MSG( "error(%d) PCLTA_STAT.\n", PCLTA_STAT );
        return false;
    }

	// get transceiver type
    trans = rx_buffer[2]>>3;
    if( ! *pclta_transceiver[trans] ) {
        VERBOSE_MSG( "error(%d) PCLTA_TSCV.\n", PCLTA_TSCV );
        return false; // transciever not supported
    }

	// register character device
    if( 0 > (pclta_major = register_chrdev( 0, "pclta", &pclta_fops )) ) {
        VERBOSE_MSG( "error(%d) PCLTA_MAJOR.\n", PCLTA_MAJOR );
        return false;
    }
    
    // request interrupt permission   OLD LOCATION
//    if( 0 > ( erc = request_irq( irq, pclta_interrupt, 0, "pclta", NULL ) ) ) {   SLOW INT
//    if( 0 > ( erc = request_irq( irq, pclta_interrupt,SA_INTERRUPT, "pclta", device ) ) ) {
//        VERBOSE_MSG( "error(%d) PCLTA_IRQPERM.\n", PCLTA_IRQPERM );
//        return false;
//    }
    
    // create device descriptor
    device = create_device( port, irq, pclta_clock[rx_buffer[2]>>3] );
    if( device == NULL ) {
        VERBOSE_MSG( "error(%d) PCLTA_CDEV.\n", PCLTA_CDEV );
        return false;
    }
    
        // request interrupt permission  NEW LOCATION SO WE HAVE DEVICE STRUCT
//    if( 0 > ( erc = request_irq( irq, pclta_interrupt, 0, "pclta", NULL ) ) ) {   SLOW INT
    if( 0 > ( erc = request_irq( irq, pclta_interrupt_handler,0, "pclta", device) ) ) {
        VERBOSE_MSG( "error(%d) PCLTA_IRQPERM.\n", PCLTA_IRQPERM );
        return false;
    }

    
    // set up pointers to device descriptor
    pclta_device_table[minor] = device;
    pclta_interrupt_table[minor] = device;
    
    // remember minor number
    device->minor = minor;
    
    // claim I/O space
    request_region( port, 4, "pclta" );
    
    // start up the interupts   removed 07/07 by karl.
//    init_hw( port,irq_mask[irq], CLK_10 ); // initialize device hardware, no IRQ

    
    DEBUG_MSG( "Transceiver type: %s", pclta_transceiver[trans] );
    MESSAGE("Device pclta%d installed.", minor );
    return true;
}