Esempio n. 1
0
void KinsolSolver::initialize(ComputeSystemFunction pComputeSystem,
                              double *pParameters, int pSize, void *pUserData)
{
    if (mSolver)
        // The solver has already been initialised, so reset things...

        reset();

    // Initialise the ODE solver itself

    OpenCOR::CoreSolver::CoreNlaSolver::initialize(pComputeSystem, pParameters, pSize);

    // Create some vectors

    mParametersVector = N_VMake_Serial(pSize, pParameters);
    mOnesVector = N_VNew_Serial(pSize);

    N_VConst(1.0, mOnesVector);

    // Create the KINSOL solver

    mSolver = KINCreate();

    // Use our own error handler

    KINSetErrHandlerFn(mSolver, errorHandler, this);

    // Initialise the KINSOL solver

    KINInit(mSolver, systemFunction, mParametersVector);

    // Set some user data

    mUserData = new KinsolSolverUserData(pUserData, pComputeSystem);

    KINSetUserData(mSolver, mUserData);

    // Set the linear solver

    KINDense(mSolver, pSize);
}
Esempio n. 2
0
cvode_mem *SOLVER(cvode, init, TARGET, SIMENGINE_STORAGE, solver_props *props){
  cvode_mem *mem = (cvode_mem*) malloc(props->num_models*sizeof(cvode_mem));
  unsigned int modelid;

  // Only need to create this buffer in the first memory space as we are using this only for scratch
  // and outside of the CVODE solver to compute the last outputs
  mem[0].k1 = (CDATAFORMAT*)malloc(props->statesize*props->num_models*sizeof(CDATAFORMAT));

  for(modelid=0; modelid<props->num_models; modelid++){
    // Set the modelid on a per memory structure basis
    mem[modelid].modelid = modelid;
    // Store solver properties
    mem[modelid].props = props;
    // Create intial value vector
    // This is done to avoid having the change the internal indexing within the flows and for the output_buffer
    mem[modelid].y0 = N_VMake_Serial(props->statesize, &(props->model_states[modelid*props->statesize]));
    // Create data structure for solver
    mem[modelid].cvmem = CVodeCreate(CV_BDF, CV_NEWTON);
    // Initialize CVODE
    if(CVodeInit(mem[modelid].cvmem, user_fun_wrapper, props->starttime, ((N_Vector)(mem[modelid].y0))) != CV_SUCCESS){
      fprintf(stderr, "Couldn't initialize CVODE");
    }
    // Set solver tolerances
    if(CVodeSStolerances(mem[modelid].cvmem, props->reltol, props->abstol) != CV_SUCCESS){
      fprintf(stderr, "Could not set CVODE tolerances");
    }
    // Set linear solver
    if(CVDense(mem[modelid].cvmem, mem[modelid].props->statesize) != CV_SUCCESS){
      fprintf(stderr, "Could not set CVODE linear solver");
    }
    // Set user data to contain pointer to memory structure for use in model_flows
    if(CVodeSetUserData(mem[modelid].cvmem, &mem[modelid]) != CV_SUCCESS){
      fprintf(stderr, "CVODE failed to initialize user data");
    }
  }

  return mem;
}
Esempio n. 3
0
void IdaSolver::initialize(const double &pVoiStart, const double &pVoiEnd,
                           const int &pStatesCount, const int &pCondVarCount,
                           double *pConstants, double *pRates, double *pStates,
                           double *pAlgebraic, double *pCondVar,
                           ComputeEssentialVariablesFunction pComputeEssentialVariables,
                           ComputeResidualsFunction pComputeResiduals,
                           ComputeRootInformationFunction pComputeRootInformation,
                           ComputeStateInformationFunction pComputeStateInformation)
{
    static const double VoiEpsilon = 1.0e-9;

    if (!mSolver) {
        // Initialise the ODE solver itself

        OpenCOR::CoreSolver::CoreDaeSolver::initialize(pVoiStart, pVoiEnd,
                                                       pStatesCount,
                                                       pCondVarCount,
                                                       pConstants, pRates,
                                                       pStates, pAlgebraic,
                                                       pCondVar,
                                                       pComputeEssentialVariables,
                                                       pComputeResiduals,
                                                       pComputeRootInformation,
                                                       pComputeStateInformation);

        // Retrieve some of the IDA properties

        if (mProperties.contains(MaximumStepProperty))
            mMaximumStep = mProperties.value(MaximumStepProperty).toDouble();
        else
            emit error(QObject::tr("the 'maximum step' property value could not be retrieved"));

        if (mProperties.contains(MaximumNumberOfStepsProperty))
            mMaximumNumberOfSteps = mProperties.value(MaximumNumberOfStepsProperty).toInt();
        else
            emit error(QObject::tr("the 'maximum number of steps' property value could not be retrieved"));

        if (mProperties.contains(RelativeToleranceProperty))
            mRelativeTolerance = mProperties.value(RelativeToleranceProperty).toDouble();
        else
            emit error(QObject::tr("the 'relative tolerance' property value could not be retrieved"));

        if (mProperties.contains(AbsoluteToleranceProperty))
            mAbsoluteTolerance = mProperties.value(AbsoluteToleranceProperty).toDouble();
        else
            emit error(QObject::tr("the 'absolute tolerance' property value could not be retrieved"));

        // Create the states vector

        mStatesVector = N_VMake_Serial(pStatesCount, pStates);
        mRatesVector  = N_VMake_Serial(pStatesCount, pRates);

        // Create the IDA solver

        mSolver = IDACreate();

        // Use our own error handler

        IDASetErrHandlerFn(mSolver, errorHandler, this);

        // Initialise the IDA solver

        IDAInit(mSolver, residualFunction, pVoiStart,
                mStatesVector, mRatesVector);

        IDARootInit(mSolver, pCondVarCount, rootFindingFunction);
        //---GRY--- NEED TO CHECK THAT OUR IDA CODE WORKS AS EXPECTED BY TRYING
        //          IT OUT ON A MODEL WHICH NEEDS ROOT FINDING (E.G. THE
        //          SAUCERMAN MODEL)...

        // Set some user data

        delete mUserData;   // Just in case the solver got initialised before

        mUserData = new IdaSolverUserData(pConstants, pAlgebraic, pCondVar,
                                          pComputeEssentialVariables,
                                          pComputeResiduals,
                                          pComputeRootInformation);

        IDASetUserData(mSolver, mUserData);

        // Set the linear solver

        IDADense(mSolver, pStatesCount);

        // Set the maximum step

        IDASetMaxStep(mSolver, mMaximumStep);

        // Set the maximum number of steps

        IDASetMaxNumSteps(mSolver, mMaximumNumberOfSteps);

        // Set the relative and absolute tolerances

        IDASStolerances(mSolver, mRelativeTolerance, mAbsoluteTolerance);

        // Compute the model's initial conditions
        // Note: this requires retrieving the model's state information, setting
        //       the IDA object's id vector and then calling IDACalcIC()...

        double *id = new double[pStatesCount];

        pComputeStateInformation(id);

        N_Vector idVector = N_VMake_Serial(pStatesCount, id);

        IDASetId(mSolver, idVector);
        IDACalcIC(mSolver, IDA_YA_YDP_INIT,
                  pVoiStart+((pVoiEnd-pVoiStart > 0)?VoiEpsilon:-VoiEpsilon));

        N_VDestroy_Serial(idVector);

        delete[] id;
    } else {
        // Reinitialise the IDA object

        IDAReInit(mSolver, pVoiStart, mStatesVector, mRatesVector);

        // Compute the model's new initial conditions

        IDACalcIC(mSolver, IDA_YA_YDP_INIT,
                  pVoiStart+((pVoiEnd-pVoiStart > 0)?VoiEpsilon:-VoiEpsilon));
    }
}
Esempio n. 4
0
void Arkode::initialize()
{
  _properties = dynamic_cast<ISystemProperties*>(_system);
  _continuous_system = dynamic_cast<IContinuous*>(_system);
  _event_system = dynamic_cast<IEvent*>(_system);
  _mixed_system = dynamic_cast<IMixedSystem*>(_system);
  _time_system = dynamic_cast<ITime*>(_system);
  IGlobalSettings* global_settings = dynamic_cast<ISolverSettings*>(_arkodesettings)->getGlobalSettings();
  // Kennzeichnung, dass initialize()() (vor der Integration) aufgerufen wurde
  _idid = 5000;
  _tLastEvent = 0.0;
  _event_n = 0;
  SolverDefaultImplementation::initialize();
  _dimSys = _continuous_system->getDimContinuousStates();
  _dimZeroFunc = _event_system->getDimZeroFunc();

  if (_dimSys == 0)
    _dimSys = 1; // introduce dummy state

  if (_dimSys <= 0)
  {
    _idid = -1;
    throw ModelicaSimulationError(SOLVER,"Cvode::initialize()");
  }
  else
  {
    // Allocate state vectors, stages and temporary arrays
    if (_z)
      delete[] _z;
    if (_zInit)
      delete[] _zInit;
    if (_zWrite)
      delete[] _zWrite;
    if (_zeroSign)
      delete[] _zeroSign;
    if (_absTol)
      delete[] _absTol;
  if(_delta)
    delete [] _delta;
    if(_deltaInv)
    delete [] _deltaInv;
    if(_ysave)
    delete [] _ysave;

    _z = new double[_dimSys];
    _zInit = new double[_dimSys];
    _zWrite = new double[_dimSys];
    _zeroSign = new int[_dimZeroFunc];
    _absTol = new double[_dimSys];
  _delta =new double[_dimSys];
    _deltaInv =new double[_dimSys];
  _ysave =new double[_dimSys];

    memset(_z, 0, _dimSys * sizeof(double));
    memset(_zInit, 0, _dimSys * sizeof(double));
  memset(_ysave, 0, _dimSys * sizeof(double));

    // Counter initialisieren
    _outStps = 0;

    if (_arkodesettings->getDenseOutput())
    {
      // Ausgabeschrittweite
      _hOut = global_settings->gethOutput();

    }

    // Allocate memory for the solver  //arkodeCreate
    _arkodeMem = ARKodeCreate();
    /*
    if (check_flag((void*) _cvodeMem, "CVodeCreate", 0))
    {
      _idid = -5;
      throw ModelicaSimulationError(SOLVER,"Cvode::initialize()");
    }
    */
    //
    // Make Cvode ready for integration
    //

    // Set initial values for CVODE
    _continuous_system->evaluateAll(IContinuous::CONTINUOUS);
    _continuous_system->getContinuousStates(_zInit);
    memcpy(_z, _zInit, _dimSys * sizeof(double));

    // Get nominal values
    _absTol[0] = 1.0; // in case of dummy state
    _continuous_system->getNominalStates(_absTol);
    for (int i = 0; i < _dimSys; i++)
      _absTol[i] *= dynamic_cast<ISolverSettings*>(_arkodesettings)->getATol();

    _ARK_y0 = N_VMake_Serial(_dimSys, _zInit);
    _ARK_y = N_VMake_Serial(_dimSys, _z);
    _ARK_yWrite = N_VMake_Serial(_dimSys, _zWrite);
    _ARK_absTol = N_VMake_Serial(_dimSys, _absTol);


    /*
    if (check_flag((void*) _CV_y0, "N_VMake_Serial", 0))
    {
      _idid = -5;
      throw ModelicaSimulationError(SOLVER,"Cvode::initialize()");
    }
    */
    // Initialize Cvode (Initial values are required)
    _idid = ARKodeInit(_arkodeMem, NULL, ARK_fCallback, _tCurrent, _ARK_y0);
    if (_idid < 0)
    {
      _idid = -5;
      throw ModelicaSimulationError(SOLVER,"Cvode::initialize()");
    }


    // Set Tolerances

    _idid = ARKodeSVtolerances(_arkodeMem, dynamic_cast<ISolverSettings*>(_arkodesettings)->getRTol(), _ARK_absTol);    // RTOL and ATOL
    if (_idid < 0)
      throw ModelicaSimulationError(SOLVER,"CVode::initialize()");

    // Set the pointer to user-defined data

    _idid = ARKodeSetUserData(_arkodeMem, _data);
    if (_idid < 0)
      throw ModelicaSimulationError(SOLVER,"Cvode::initialize()");

    _idid = ARKodeSetInitStep(_arkodeMem, 1e-6);    // INITIAL STEPSIZE
    if (_idid < 0)
      throw ModelicaSimulationError(SOLVER,"Cvode::initialize()");

    _idid = ARKodeSetMaxConvFails(_arkodeMem, 100);       // Maximale Fehler im Konvergenztest
    if (_idid < 0)
      throw ModelicaSimulationError(SOLVER,"CVoder::initialize()");

    _idid = ARKodeSetMinStep(_arkodeMem, dynamic_cast<ISolverSettings*>(_arkodesettings)->getLowerLimit());       // MINIMUM STEPSIZE
    if (_idid < 0)
      throw ModelicaSimulationError(SOLVER,"CVode::initialize()");

    _idid = ARKodeSetMaxStep(_arkodeMem, global_settings->getEndTime() / 10.0);       // MAXIMUM STEPSIZE
    if (_idid < 0)
      throw ModelicaSimulationError(SOLVER,"CVode::initialize()");

    _idid = ARKodeSetMaxNonlinIters(_arkodeMem, 5);      // Max number of iterations
    if (_idid < 0)
      throw ModelicaSimulationError(SOLVER,"CVode::initialize()");
    _idid = ARKodeSetMaxErrTestFails(_arkodeMem, 100);
    if (_idid < 0)
      throw ModelicaSimulationError(SOLVER,"CVode::initialize()");

    _idid = ARKodeSetMaxNumSteps(_arkodeMem, 1000);            // Max Number of steps
    if (_idid < 0)
      throw ModelicaSimulationError(SOLVER,"Cvode::initialize()");

    // Initialize linear solver
    /*
    #ifdef USE_SUNDIALS_LAPACK
      _idid = CVLapackDense(_cvodeMem, _dimSys);
    #else
    */
      _idid = ARKDense(_arkodeMem, _dimSys);
    /*
    #endif
    */
    if (_idid < 0)
      throw ModelicaSimulationError(SOLVER,"Cvode::initialize()");

  // Use own jacobian matrix
  // Check if Colored Jacobians are worth to use

  if (_idid < 0)
      throw ModelicaSimulationError(SOLVER,"ARKode::initialize()");

    if (_dimZeroFunc)
    {
      _idid = ARKodeRootInit(_arkodeMem, _dimZeroFunc, &ARK_ZerofCallback);

      memset(_zeroSign, 0, _dimZeroFunc * sizeof(int));
      _idid = ARKodeSetRootDirection(_arkodeMem, _zeroSign);
      if (_idid < 0)
        throw ModelicaSimulationError(SOLVER,"CVode::initialize()");
      memset(_zeroSign, -1, _dimZeroFunc * sizeof(int));
      memset(_zeroVal, -1, _dimZeroFunc * sizeof(int));

    }


    _arkode_initialized = true;

    //
    // CVODE is ready for integration
    //
    // BOOST_LOG_SEV(cvode_lg::get(), cvode_info) << "CVode initialized";
  }
}
Esempio n. 5
0
int dynamixMain (int argc, char * argv[]) {



  //// DECLARING VARIABLES


  // Struct of parameters
  PARAMETERS p;
  // CVode variables
  void * cvode_mem = NULL;			// pointer to block of CVode memory
  N_Vector y, yout;			// arrays of populations

  // arrays for energetic parameters
  realtype ** V = NULL;				// pointer to k-c coupling constants
  realtype * Vbridge = NULL;			// pointer to array of bridge coupling constants.
  // first element [0] is Vkb1, last [Nb] is VcbN
  realtype * Vnobridge = NULL;			// coupling constant when there is no bridge

  //// Setting defaults for parameters to be read from input
  //// done setting defaults

  int flag;
  realtype * k_pops = NULL;				// pointers to arrays of populations
  realtype * l_pops = NULL;
  realtype * c_pops = NULL;
  realtype * b_pops = NULL;
  realtype * ydata = NULL;				// pointer to ydata (contains all populations)
  realtype * wavefunction = NULL;			// (initial) wavefunction
  realtype * dm = NULL;					// density matrix
  realtype * dmt = NULL;				// density matrix in time
  realtype * wfnt = NULL;				// density matrix in time
  realtype * k_energies = NULL;				// pointers to arrays of energies
  realtype * c_energies = NULL;
  realtype * b_energies = NULL;
  realtype * l_energies = NULL;
  realtype t0 = 0.0;				// initial time
  realtype t = 0;
  realtype tret = 0;					// time returned by the solver
  time_t startRun;				// time at start of log
  time_t endRun;					// time at end of log
  struct tm * currentTime = NULL;			// time structure for localtime
#ifdef DEBUG
  FILE * realImaginary;				// file containing real and imaginary parts of the wavefunction
#endif
  FILE * log;					// log file with run times
  realtype * tkprob = NULL; 				// total probability in k, l, c, b states at each timestep
  realtype * tlprob = NULL;
  realtype * tcprob = NULL;
  realtype * tbprob = NULL;
  double ** allprob = NULL;				// populations in all states at all times
  realtype * times = NULL;
  realtype * qd_est = NULL;
  realtype * qd_est_diag = NULL;
  std::string inputFile = "ins/parameters.in";			// name of input file
  std::string cEnergiesInput = "ins/c_energies.in";
  std::string cPopsInput = "ins/c_pops.in";
  std::string bEnergiesInput = "ins/b_energies.in";
  std::string VNoBridgeInput = "ins/Vnobridge.in";
  std::string VBridgeInput = "ins/Vbridge.in";
  std::map<const std::string, bool> outs;	// map of output file names to bool

  // default output directory
  p.outputDir = "outs/";

  double summ = 0;			// sum variable

  // ---- process command line flags ---- //
  opterr = 0;
  int c;
  std::string insDir;
  /* process command line options */
  while ((c = getopt(argc, argv, "i:o:")) != -1) {
    switch (c) {
      case 'i':
	// check that it ends in a slash
	std::cerr << "[dynamix]: assigning input directory" << std::endl;
	insDir = optarg;
	if (strcmp(&(insDir.at(insDir.length() - 1)), "/")) {
	  std::cerr << "ERROR: option -i requires argument ("
	            << insDir << ") to have a trailing slash (/)." << std::endl;
	  return 1;
	}
	else {
	  // ---- assign input files ---- //
	  inputFile = insDir + "parameters.in";
	  cEnergiesInput = insDir + "c_energies.in";
	  cPopsInput = insDir + "c_pops.in";
	  bEnergiesInput = insDir + "b_energies.in";
	  VNoBridgeInput = insDir + "Vnobridge.in";
	  VBridgeInput = insDir + "Vbridge.in";
	}
	break;
      case 'o':
	std::cerr << "[dynamix]: assigning output directory" << std::endl;
	p.outputDir = optarg;
	break;
      case '?':
	if (optopt == 'i') {
	  fprintf(stderr, "Option -%c requires a directory argument.\n", optopt);
	}
	else if (isprint(optopt)) {
	  fprintf(stderr, "Unknown option -%c.\n", optopt);
	}
	else {
	  fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt);
	}
	return 1;
      default:
	continue;
    }
  }
  optind = 1;	// reset global variable counter for the next time this is run

  std::cerr << "[dynamix]: ARGUMENTS" << std::endl;
  for (int ii = 0; ii < argc; ii++) {
    std::cerr << "[dynamix]: " << argv[ii] << std::endl;
  }

  //// ASSIGN PARAMETERS FROM INPUT FILE


  // ---- TODO create output directory if it does not exist ---- //
  flag = mkdir(p.outputDir.c_str(), 0755);

  std::cerr << "Looking for inputs in all the " << inputFile << " places" << std::endl;
  assignParams(inputFile.c_str(), &p);

  // Decide which output files to make
#ifdef DEBUG
  std::cout << "Assigning outputs as specified in " << inputFile << "\n";
#endif
  assignOutputs(inputFile.c_str(), outs, &p);

#ifdef DEBUG
  // print out which outputs will be made
  for (std::map<const std::string, bool>::iterator it = outs.begin(); it != outs.end(); it++) {
    std::cout << "Output file: " << it->first << " will be created.\n";
  }
#endif

  // OPEN LOG FILE; PUT IN START TIME //
  if (isOutput(outs, "log.out")) {
    log = fopen("log.out", "w");			// note that this file is closed at the end of the program
  }
  time(&startRun);
  currentTime = localtime(&startRun);
  if (isOutput(outs, "log.out")) {
    fprintf(log, "Run started at %s\n", asctime(currentTime));
  }

  if (isOutput(outs, "log.out")) {
    // make a note about the laser intensity.
    fprintf(log,"The laser intensity is %.5e W/cm^2.\n\n",pow(p.pumpAmpl,2)*3.5094452e16);
  }


  //// READ DATA FROM INPUTS


  p.Nc = numberOfValuesInFile(cEnergiesInput.c_str());
  p.Nb = numberOfValuesInFile(bEnergiesInput.c_str());
  k_pops = new realtype [p.Nk];
  c_pops = new realtype [p.Nc];
  b_pops = new realtype [p.Nb];
  l_pops = new realtype [p.Nl];
  k_energies = new realtype [p.Nk];
  c_energies = new realtype [p.Nc];
  b_energies = new realtype [p.Nb];
  l_energies = new realtype [p.Nl];
  if (numberOfValuesInFile(cPopsInput.c_str()) != p.Nc) {
    fprintf(stderr, "ERROR [Inputs]: c_pops and c_energies not the same length.\n");
    return -1;
  }
  readArrayFromFile(c_energies, cEnergiesInput.c_str(), p.Nc);
  if (p.bridge_on) {
    if (p.bridge_on && (p.Nb < 1)) {
      std::cerr << "\nERROR: bridge_on but no bridge states.  The file b_energies.in is probably empty.\n";
      return -1;
    }
    p.Vbridge.resize(p.Nb+1);
    readArrayFromFile(b_energies, bEnergiesInput.c_str(), p.Nb);
    readVectorFromFile(p.Vbridge, VBridgeInput.c_str(), p.Nb + 1);
#ifdef DEBUG
    std::cout << "COUPLINGS:";
    for (int ii = 0; ii < p.Nb+1; ii++) {
      std::cout << " " << p.Vbridge[ii];
    }
    std::cout << std::endl;
#endif
  }
  else {
    p.Nb = 0;
    p.Vnobridge.resize(1);
    readVectorFromFile(p.Vnobridge, VNoBridgeInput.c_str(), 1);
  }

#ifdef DEBUG
  std::cout << "\nDone reading things from inputs.\n";
#endif


  //// PREPROCESS DATA FROM INPUTS


  // check torsion parameters, set up torsion spline
  if (p.torsion) {
#ifdef DEBUG
    std::cout << "Torsion is on." << std::endl;
#endif

    // error checking
    if (p.torsionSite > p.Nb) {
      std::cerr << "ERROR: torsion site (" << p.torsionSite
	<< ") is larger than number of bridge sites (" << p.Nb << ")." << std::endl;
      exit(-1);
    }
    else if (p.torsionSite < 0) {
      std::cerr << "ERROR: torsion site is less than zero." << std::endl;
      exit(-1);
    }

    if (!fileExists(p.torsionFile)) {
      std::cerr << "ERROR: torsion file " << p.torsionFile << " does not exist." << std::endl;
    }

    // create spline
    p.torsionV = new Spline(p.torsionFile.c_str());
    if (p.torsionV->getFirstX() != 0.0) {
      std::cerr << "ERROR: time in " << p.torsionFile << " should start at 0.0." << std::endl;
      exit(-1);
    }
    if (p.torsionV->getLastX() < p.tout) {
      std::cerr << "ERROR: time in " << p.torsionFile << " should be >= tout." << std::endl;
      exit(-1);
    }
  }


  // set number of processors for OpenMP
  //omp_set_num_threads(p.nproc);
  mkl_set_num_threads(p.nproc);

  p.NEQ = p.Nk+p.Nc+p.Nb+p.Nl;				// total number of equations set
  p.NEQ2 = p.NEQ*p.NEQ;				// number of elements in DM
#ifdef DEBUG
  std::cout << "\nTotal number of states: " << p.NEQ << std::endl;
  std::cout << p.Nk << " bulk, " << p.Nc << " QD, " << p.Nb << " bridge, " << p.Nl << " bulk VB.\n";
#endif
  tkprob = new realtype [p.numOutputSteps+1];	// total population on k, b, c at each timestep
  tcprob = new realtype [p.numOutputSteps+1];
  tbprob = new realtype [p.numOutputSteps+1];
  tlprob = new realtype [p.numOutputSteps+1];
  allprob = new double * [p.numOutputSteps+1];
  for (int ii = 0; ii <= p.numOutputSteps; ii++) {
    allprob[ii] = new double [p.NEQ];
  }
  // assign times.
  p.times.resize(p.numOutputSteps+1);
  for (int ii = 0; ii <= p.numOutputSteps; ii++) {
    p.times[ii] = float(ii)/p.numOutputSteps*p.tout;
  }
  qd_est = new realtype [p.numOutputSteps+1];
  qd_est_diag = new realtype [p.numOutputSteps+1];
  p.Ik = 0;					// set index start positions for each type of state
  p.Ic = p.Nk;
  p.Ib = p.Ic+p.Nc;
  p.Il = p.Ib+p.Nb;

  // assign bulk conduction and valence band energies
  // for RTA, bulk and valence bands have parabolic energies
  if (p.rta) {
    buildParabolicBand(k_energies, p.Nk, p.kBandEdge, CONDUCTION, &p);
    buildParabolicBand(l_energies, p.Nl, p.lBandTop, VALENCE, &p);
  }
  else {
    buildContinuum(k_energies, p.Nk, p.kBandEdge, p.kBandTop);
    buildContinuum(l_energies, p.Nl, p.kBandEdge - p.valenceBand - p.bulk_gap, p.kBandEdge - p.bulk_gap);
  }
  // calculate band width
  p.kBandWidth = k_energies[p.Nk - 1] - k_energies[0];


  //// BUILD INITIAL WAVEFUNCTION


  // bridge states (empty to start)
  initializeArray(b_pops, p.Nb, 0.0);

  // coefficients in bulk and other states depend on input conditions in bulk
  if (!p.rta) {
#ifdef DEBUG
    std::cout << "\ninitializing k_pops\n";
#endif
    if (p.bulk_constant) {
      initializeArray(k_pops, p.Nk, 0.0);
#ifdef DEBUG
      std::cout << "\ninitializing k_pops with constant probability in range of states\n";
#endif
      initializeArray(k_pops+p.Nk_first-1, p.Nk_final-p.Nk_first+1, 1.0);
      initializeArray(l_pops, p.Nl, 0.0);		// populate l states (all 0 to start off)
      initializeArray(c_pops, p.Nc, 0.0);		// QD states empty to start
    }
    else if (p.bulk_Gauss) {
      buildKPopsGaussian(k_pops, k_energies, p.kBandEdge,
	  p.bulkGaussSigma, p.bulkGaussMu, p.Nk);   // populate k states with FDD
      initializeArray(l_pops, p.Nl, 0.0);		// populate l states (all 0 to start off)
      initializeArray(c_pops, p.Nc, 0.0);		// QD states empty to start
    }
    else if (p.qd_pops) {
      readArrayFromFile(c_pops, cPopsInput.c_str(), p.Nc);	// QD populations from file
      initializeArray(l_pops, p.Nl, 0.0);		// populate l states (all 0 to start off)
      initializeArray(k_pops, p.Nk, 0.0);             // populate k states (all zero to start off)
    }
    else {
      initializeArray(k_pops, p.Nk, 0.0);             // populate k states (all zero to start off)
      initializeArray(l_pops, p.Nl, 1.0);		// populate l states (all populated to start off)
      initializeArray(c_pops, p.Nc, 0.0);		// QD states empty to start
    }
#ifdef DEBUG
    std::cout << "\nThis is k_pops:\n";
    for (int ii = 0; ii < p.Nk; ii++) {
      std::cout << k_pops[ii] << std::endl;
    }
    std::cout << "\n";
#endif
  }
  // with RTA, use different set of switches
  else {
    // bulk valence band
    if (p.VBPopFlag == POP_EMPTY) {
#ifdef DEBUG
      std::cout << "Initializing empty valence band" << std::endl;
#endif
      initializeArray(l_pops, p.Nl, 0.0);
    }
    else if (p.VBPopFlag == POP_FULL) {
#ifdef DEBUG
      std::cout << "Initializing full valence band" << std::endl;
#endif
      initializeArray(l_pops, p.Nl, 1.0);
    }
    else {
      std::cerr << "ERROR: unrecognized VBPopFlag " << p.VBPopFlag << std::endl;
    }

    // bulk conduction band
    if (p.CBPopFlag == POP_EMPTY) {
#ifdef DEBUG
      std::cout << "Initializing empty conduction band" << std::endl;
#endif
      initializeArray(k_pops, p.Nk, 0.0);
    }
    else if (p.CBPopFlag == POP_FULL) {
#ifdef DEBUG
      std::cout << "Initializing full conduction band" << std::endl;
#endif
      initializeArray(k_pops, p.Nk, 1.0);
    }
    else if (p.CBPopFlag == POP_CONSTANT) {
#ifdef DEBUG
      std::cout << "Initializing constant distribution in conduction band" << std::endl;
#endif
      initializeArray(k_pops, p.Nk, 0.0);
      initializeArray(k_pops, p.Nk, 1e-1); // FIXME
      initializeArray(k_pops+p.Nk_first-1, p.Nk_final-p.Nk_first+1, 1.0);
    }
    else if (p.CBPopFlag == POP_GAUSSIAN) {
#ifdef DEBUG
      std::cout << "Initializing Gaussian in conduction band" << std::endl;
#endif
      buildKPopsGaussian(k_pops, k_energies, p.kBandEdge,
	  p.bulkGaussSigma, p.bulkGaussMu, p.Nk);
    }
    else {
      std::cerr << "ERROR: unrecognized CBPopFlag " << p.CBPopFlag << std::endl;
    }

    //// QD
    if (p.QDPopFlag == POP_EMPTY) {
      initializeArray(c_pops, p.Nc, 0.0);
    }
    else if (p.QDPopFlag == POP_FULL) {
      initializeArray(c_pops, p.Nc, 1.0);
    }
    else {
      std::cerr << "ERROR: unrecognized QDPopFlag " << p.QDPopFlag << std::endl;
    }
  }

  // create empty wavefunction
  wavefunction = new realtype [2*p.NEQ];
  initializeArray(wavefunction, 2*p.NEQ, 0.0);

  // assign real parts of wavefunction coefficients (imaginary are zero)
  for (int ii = 0; ii < p.Nk; ii++) {
    wavefunction[p.Ik + ii] = k_pops[ii];
  }
  for (int ii = 0; ii < p.Nc; ii++) {
    wavefunction[p.Ic + ii] = c_pops[ii];
  }
  for (int ii = 0; ii < p.Nb; ii++) {
    wavefunction[p.Ib + ii] = b_pops[ii];
  }
  for (int ii = 0; ii < p.Nl; ii++) {
    wavefunction[p.Il + ii] = l_pops[ii];
  }

  if (isOutput(outs, "psi_start.out")) {
    outputWavefunction(wavefunction, p.NEQ);
  }

  // Give all coefficients a random phase
  if (p.random_phase) {
    float phi;
    // set the seed
    if (p.random_seed == -1) { srand(time(NULL)); }
    else { srand(p.random_seed); }
    for (int ii = 0; ii < p.NEQ; ii++) {
      phi = 2*3.1415926535*(float)rand()/(float)RAND_MAX;
      wavefunction[ii] = wavefunction[ii]*cos(phi);
      wavefunction[ii + p.NEQ] = wavefunction[ii + p.NEQ]*sin(phi);
    }
  }

#ifdef DEBUG
  // print out details of wavefunction coefficients
  std::cout << std::endl;
  for (int ii = 0; ii < p.Nk; ii++) {
    std::cout << "starting wavefunction: Re[k(" << ii << ")] = " << wavefunction[p.Ik + ii] << std::endl;
  }
  for (int ii = 0; ii < p.Nc; ii++) {
    std::cout << "starting wavefunction: Re[c(" << ii << ")] = " << wavefunction[p.Ic + ii] << std::endl;
  }
  for (int ii = 0; ii < p.Nb; ii++) {
    std::cout << "starting wavefunction: Re[b(" << ii << ")] = " << wavefunction[p.Ib + ii] << std::endl;
  }
  for (int ii = 0; ii < p.Nl; ii++) {
    std::cout << "starting wavefunction: Re[l(" << ii << ")] = " << wavefunction[p.Il + ii] << std::endl;
  }
  for (int ii = 0; ii < p.Nk; ii++) {
    std::cout << "starting wavefunction: Im[k(" << ii << ")] = " << wavefunction[p.Ik + ii + p.NEQ] << std::endl;
  }
  for (int ii = 0; ii < p.Nc; ii++) {
    std::cout << "starting wavefunction: Im[c(" << ii << ")] = " << wavefunction[p.Ic + ii + p.NEQ] << std::endl;
  }
  for (int ii = 0; ii < p.Nb; ii++) {
    std::cout << "starting wavefunction: Im[b(" << ii << ")] = " << wavefunction[p.Ib + ii + p.NEQ] << std::endl;
  }
  for (int ii = 0; ii < p.Nl; ii++) {
    std::cout << "starting wavefunction: Im[l(" << ii << ")] = " << wavefunction[p.Il + ii + p.NEQ] << std::endl;
  }
  std::cout << std::endl;
  summ = 0;
  for (int ii = 0; ii < 2*p.NEQ; ii++) {
    summ += pow(wavefunction[ii],2);
  }
  std::cout << "\nTotal population is " << summ << "\n\n";
#endif


  //// ASSEMBLE ARRAY OF ENERGIES


  // TODO TODO
  p.energies.resize(p.NEQ);
  for (int ii = 0; ii < p.Nk; ii++) {
    p.energies[p.Ik + ii] = k_energies[ii];
  }
  for (int ii = 0; ii < p.Nc; ii++) {
    p.energies[p.Ic + ii] = c_energies[ii];
  }
  for (int ii = 0; ii < p.Nb; ii++) {
    p.energies[p.Ib + ii] = b_energies[ii];
  }
  for (int ii = 0; ii < p.Nl; ii++) {
    p.energies[p.Il + ii] = l_energies[ii];
  }

#ifdef DEBUG
  for (int ii = 0; ii < p.NEQ; ii++) {
    std::cout << "p.energies[" << ii << "] is " << p.energies[ii] << "\n";
  }
#endif


  //// ASSIGN COUPLING CONSTANTS


  V = new realtype * [p.NEQ];
  for (int ii = 0; ii < p.NEQ; ii++) {
    V[ii] = new realtype [p.NEQ];
  }
  buildCoupling(V, &p, outs);

  if (isOutput(outs, "log.out")) {
    // make a note in the log about system timescales
    double tau = 0;		// fundamental system timescale
    if (p.Nk == 1) {
      fprintf(log, "\nThe timescale (tau) is undefined (Nk == 1).\n");
    }
    else {
      if (p.bridge_on) {
	if (p.scale_bubr) {
	  tau = 1.0/(2*p.Vbridge[0]*M_PI);
	}
	else {
	  tau = ((p.kBandTop - p.kBandEdge)/(p.Nk - 1))/(2*pow(p.Vbridge[0],2)*M_PI);
	}
      }
      else {
	if (p.scale_buqd) {
	  tau = 1.0/(2*p.Vnobridge[0]*M_PI);
	}
	else {
	  tau = ((p.kBandTop - p.kBandEdge)/(p.Nk - 1))/(2*pow(p.Vnobridge[0],2)*M_PI);
	}
      }
      fprintf(log, "\nThe timescale (tau) is %.9e a.u.\n", tau);
    }
  }

  //// CREATE DENSITY MATRIX
  if (! p.wavefunction) {
    // Create the initial density matrix
    dm = new realtype [2*p.NEQ2];
    initializeArray(dm, 2*p.NEQ2, 0.0);
#pragma omp parallel for
    for (int ii = 0; ii < p.NEQ; ii++) {
      // diagonal part
      dm[p.NEQ*ii + ii] = pow(wavefunction[ii],2) + pow(wavefunction[ii + p.NEQ],2);
      if (p.coherent) {
	// off-diagonal part
	for (int jj = 0; jj < ii; jj++) {
	  // real part of \rho_{ii,jj}
	  dm[p.NEQ*ii + jj] = wavefunction[ii]*wavefunction[jj] + wavefunction[ii+p.NEQ]*wavefunction[jj+p.NEQ];
	  // imaginary part of \rho_{ii,jj}
	  dm[p.NEQ*ii + jj + p.NEQ2] = wavefunction[ii]*wavefunction[jj+p.NEQ] - wavefunction[jj]*wavefunction[ii+p.NEQ];
	  // real part of \rho_{jj,ii}
	  dm[p.NEQ*jj + ii] = dm[p.NEQ*ii + jj];
	  // imaginary part of \rho_{jj,ii}
	  dm[p.NEQ*jj + ii + p.NEQ2] = -1*dm[p.NEQ*ii + jj + p.NEQ*p.NEQ];
	}
      }
    }

    // Create the array to store the density matrix in time
    dmt = new realtype [2*p.NEQ2*(p.numOutputSteps+1)];
    initializeArray(dmt, 2*p.NEQ2*(p.numOutputSteps+1), 0.0);

#ifdef DEBUG2
    // print out density matrix
    std::cout << "\nDensity matrix without normalization:\n\n";
    for (int ii = 0; ii < p.NEQ; ii++) {
      for (int jj = 0; jj < p.NEQ; jj++) {
	fprintf(stdout, "(%+.1e,%+.1e) ", dm[p.NEQ*ii + jj], dm[p.NEQ*ii + jj + p.NEQ2]);
      }
      fprintf(stdout, "\n");
    }
#endif

    // Normalize the DM so that populations add up to 1.
    // No normalization if RTA is on.
    if (!p.rta) {
      summ = 0.0;
      for (int ii = 0; ii < p.NEQ; ii++) {
	// assume here that diagonal elements are all real
	summ += dm[p.NEQ*ii + ii];
      }
      if ( summ == 0.0 ) {
	std::cerr << "\nFATAL ERROR [populations]: total population is 0!\n";
	return -1;
      }
      if (summ != 1.0) {
	// the variable 'summ' is now a multiplicative normalization factor
	summ = 1.0/summ;
	for (int ii = 0; ii < 2*p.NEQ2; ii++) {
	  dm[ii] *= summ;
	}
      }
#ifdef DEBUG
      std::cout << "\nThe normalization factor for the density matrix is " << summ << "\n\n";
#endif
    }

    // Error checking for total population; recount population first
    summ = 0.0;
    for (int ii = 0; ii < p.NEQ; ii++) {
      summ += dm[p.NEQ*ii + ii];
    }
    if ( fabs(summ-1.0) > 1e-12  && (!p.rta)) {
      std::cerr << "\nWARNING [populations]: After normalization, total population is not 1, it is " << summ << "!\n";
    }
#ifdef DEBUG
    std::cout << "\nAfter normalization, the sum of the populations in the density matrix is " << summ << "\n\n";
#endif
    // Add initial DM to parameters.
    p.startDM.resize(2*p.NEQ2);
    memcpy(&(p.startDM[0]), &(dm[0]), 2*p.NEQ2*sizeof(double));
  }
  // wavefunction
  else {

    // Create the array to store the wavefunction in time
    wfnt = new realtype [2*p.NEQ*(p.numOutputSteps+1)];
    initializeArray(wfnt, 2*p.NEQ*(p.numOutputSteps+1), 0.0);

    // normalize
    summ = 0.0;
    for (int ii = 0; ii < p.NEQ; ii++) {
      summ += pow(wavefunction[ii],2) + pow(wavefunction[ii+p.NEQ],2);
    }
#ifdef DEBUG
    std::cout << "Before normalization, the total population is " << summ << std::endl;
#endif
    summ = 1.0/sqrt(summ);
    for (int ii = 0; ii < 2*p.NEQ; ii++) {
      wavefunction[ii] *= summ;
    }

    // check total population
    summ = 0.0;
    for (int ii = 0; ii < p.NEQ; ii++) {
      summ += pow(wavefunction[ii],2) + pow(wavefunction[ii+p.NEQ],2);
    }
#ifdef DEBUG
    std::cout << "After normalization, the total population is " << summ << std::endl;
#endif
    if (fabs(summ - 1.0) > 1e-12) {
      std::cerr << "WARNING: wavefunction not normalized!  Total density is " << summ << std::endl;
    }

    // Add initial wavefunction to parameters.
    p.startWfn.resize(2*p.NEQ);
    memcpy(&(p.startWfn[0]), &(wavefunction[0]), 2*p.NEQ*sizeof(double));
  }


  //// BUILD HAMILTONIAN


  // //TODO TODO
#ifdef DEBUG
  fprintf(stderr, "Building Hamiltonian.\n");
#endif
  realtype * H = NULL;
  H = new realtype [p.NEQ2];
  for (int ii = 0; ii < p.NEQ2; ii++) {
    H[ii] = 0.0;
  }
  buildHamiltonian(H, p.energies, V, &p);
  // add Hamiltonian to p
  p.H.resize(p.NEQ2);
  for (int ii = 0; ii < p.NEQ2; ii++) {
    p.H[ii] = H[ii];
  }
  // create sparse version of H
  p.H_sp.resize(p.NEQ2);
  p.H_cols.resize(p.NEQ2);
  p.H_rowind.resize(p.NEQ2 + 1);
  int job [6] = {0, 0, 0, 2, p.NEQ2, 1};
  int info = 0;

  mkl_ddnscsr(&job[0], &(p.NEQ), &(p.NEQ), &(p.H)[0], &(p.NEQ), &(p.H_sp)[0],
      &(p.H_cols)[0], &(p.H_rowind)[0], &info);


  //// SET UP CVODE VARIABLES


#ifdef DEBUG
  std::cout << "\nCreating N_Vectors.\n";
  if (p.wavefunction) {
    std::cout << "\nProblem size is " << 2*p.NEQ << " elements.\n";
  }
  else {
    std::cout << "\nProblem size is " << 2*p.NEQ2 << " elements.\n";
  }
#endif
  // Creates N_Vector y with initial populations which will be used by CVode//
  if (p.wavefunction) {
    y = N_VMake_Serial(2*p.NEQ, wavefunction);
  }
  else {
    y = N_VMake_Serial(2*p.NEQ2, dm);
  }
  // put in t = 0 information
  if (! p.wavefunction) {
    updateDM(y, dmt, 0, &p);
  }
  else {
    updateWfn(y, wfnt, 0, &p);
  }
  // the vector yout has the same dimensions as y
  yout = N_VClone(y);

#ifdef DEBUG
  realImaginary = fopen("real_imaginary.out", "w");
#endif

  // Make plot files
  makePlots(outs, &p);

  // only do propagation if not just making plots
  if (! p.justPlots) {
    // Make outputs independent of time propagation
    computeGeneralOutputs(outs, &p);

    // create CVode object
    // this is a stiff problem, I guess?
#ifdef DEBUG
    std::cout << "\nCreating cvode_mem object.\n";
#endif
    cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
    flag = CVodeSetUserData(cvode_mem, (void *) &p);

#ifdef DEBUG
    std::cout << "\nInitializing CVode solver.\n";
#endif
    // initialize CVode solver //

    if (p.wavefunction) {
      //flag = CVodeInit(cvode_mem, &RHS_WFN, t0, y);
      flag = CVodeInit(cvode_mem, &RHS_WFN_SPARSE, t0, y);
    }
    else {
      if (p.kinetic) {
	flag = CVodeInit(cvode_mem, &RHS_DM_RELAX, t0, y);
      }
      else if (p.rta) {
	flag = CVodeInit(cvode_mem, &RHS_DM_RTA, t0, y);
	//flag = CVodeInit(cvode_mem, &RHS_DM_RTA_BLAS, t0, y);
      }
      else if (p.dephasing) {
	flag = CVodeInit(cvode_mem, &RHS_DM_dephasing, t0, y);
      }
      else {
	//flag = CVodeInit(cvode_mem, &RHS_DM, t0, y);
	flag = CVodeInit(cvode_mem, &RHS_DM_BLAS, t0, y);
      }
    }

#ifdef DEBUG
    std::cout << "\nSpecifying integration tolerances.\n";
#endif
    // specify integration tolerances //
    flag = CVodeSStolerances(cvode_mem, p.reltol, p.abstol);

#ifdef DEBUG
    std::cout << "\nAttaching linear solver module.\n";
#endif
    // attach linear solver module //
    if (p.wavefunction) {
      flag = CVDense(cvode_mem, 2*p.NEQ);
    }
    else {
      // Diagonal approximation to the Jacobian saves memory for large systems
      flag = CVDiag(cvode_mem);
    }

    //// CVODE TIME PROPAGATION


#ifdef DEBUG
    std::cout << "\nAdvancing the solution in time.\n";
#endif
    for (int ii = 1; ii <= p.numsteps; ii++) {
      t = (p.tout*((double) ii)/((double) p.numsteps));
      flag = CVode(cvode_mem, t, yout, &tret, 1);
#ifdef DEBUGf
      std::cout << std::endl << "CVode flag at step " << ii << ": " << flag << std::endl;
#endif
      if ((ii % (p.numsteps/p.numOutputSteps) == 0) || (ii == p.numsteps)) {
	// show progress in stdout
	if (p.progressStdout) {
	  fprintf(stdout, "\r%-.2lf percent done", ((double)ii/((double)p.numsteps))*100);
	  fflush(stdout);
	}
	// show progress in a file
	if (p.progressFile) {
	  std::ofstream progressFile("progress.tmp");
	  progressFile << ((double)ii/((double)p.numsteps))*100 << " percent done." << std::endl;
	  progressFile.close();
	}
	if (p.wavefunction) {
	  updateWfn(yout, wfnt, ii*p.numOutputSteps/p.numsteps, &p);
	}
	else {
	  updateDM(yout, dmt, ii*p.numOutputSteps/p.numsteps, &p);
	}
      }
    }

#ifdef DEBUG
    fclose(realImaginary);
#endif


    //// MAKE FINAL OUTPUTS


    // finalize log file //
    time(&endRun);
    currentTime = localtime(&endRun);
    if (isOutput(outs, "log.out")) {
      fprintf(log, "Final status of 'flag' variable: %d\n\n", flag);
      fprintf(log, "Run ended at %s\n", asctime(currentTime));
      fprintf(log, "Run took %.3g seconds.\n", difftime(endRun, startRun));
      fclose(log);					// note that the log file is opened after variable declaration
    }
    if (p.progressStdout) {
      printf("\nRun took %.3g seconds.\n", difftime(endRun, startRun));
    }

    // Compute density outputs.
#ifdef DEBUG
    std::cout << "Computing outputs..." << std::endl;
#endif
    if (p.wavefunction) {
      computeWfnOutput(wfnt, outs, &p);
    }
    else {
      computeDMOutput(dmt, outs, &p);
    }
#ifdef DEBUG
    std::cout << "done computing outputs" << std::endl;
#endif

    // do analytical propagation
    if (p.analytical && (! p.bridge_on)) {
      computeAnalyticOutputs(outs, &p);
    }
  }


  //// CLEAN UP


#ifdef DEBUG
  fprintf(stdout, "Deallocating N_Vectors.\n");
#endif
  // deallocate memory for N_Vectors //
  N_VDestroy_Serial(y);
  N_VDestroy_Serial(yout);

#ifdef DEBUG
  fprintf(stdout, "Freeing CVode memory.\n");
#endif
  // free solver memory //
  CVodeFree(&cvode_mem);

#ifdef DEBUG
  fprintf(stdout, "Freeing memory in main.\n");
#endif
  // delete all these guys
  delete [] tkprob;
  delete [] tlprob;
  delete [] tcprob;
  delete [] tbprob;
  for (int ii = 0; ii <= p.numOutputSteps; ii++) {
    delete [] allprob[ii];
  }
  delete [] allprob;
  delete [] k_pops;
  delete [] c_pops;
  delete [] b_pops;
  delete [] l_pops;
  if (p.bridge_on) {
    delete [] Vbridge;
  }
  else {
    delete [] Vnobridge;
  }
  delete [] k_energies;
  delete [] c_energies;
  delete [] b_energies;
  delete [] l_energies;
  delete [] wavefunction;
  delete [] H;
  for (int ii = 0; ii < p.NEQ; ii++) {
    delete [] V[ii];
  }
  delete [] V;
  if (p.wavefunction) {
    delete [] wfnt;
  }
  else {
    delete [] dm;
    delete [] dmt;
  }
  delete [] times;
  delete [] qd_est;
  delete [] qd_est_diag;

  std::cout << "whoo" << std::endl;

  return 0;
}
Esempio n. 6
0
void Ida::initialize()
{
  _properties = dynamic_cast<ISystemProperties*>(_system);
  _continuous_system = dynamic_cast<IContinuous*>(_system);
  _event_system = dynamic_cast<IEvent*>(_system);
  _mixed_system = dynamic_cast<IMixedSystem*>(_system);
  _time_system = dynamic_cast<ITime*>(_system);
  IGlobalSettings* global_settings = dynamic_cast<ISolverSettings*>(_idasettings)->getGlobalSettings();
  // Kennzeichnung, dass initialize()() (vor der Integration) aufgerufen wurde
  _idid = 5000;
  _tLastEvent = 0.0;
  _event_n = 0;
  SolverDefaultImplementation::initialize();

  _dimStates = _continuous_system->getDimContinuousStates();
  _dimZeroFunc = _event_system->getDimZeroFunc()+_event_system->getDimClock();
  _dimAE = _continuous_system->getDimAE();
   if(_dimAE>0)
		_dimSys=_dimAE+ _dimStates;
	else
		_dimSys=_dimStates;
  if (_dimStates <= 0)

  {
    _idid = -1;
    throw std::invalid_argument("Ida::initialize()");
  }
  else
  {
    // Allocate state vectors, stages and temporary arrays

   /*if (_z)
      delete[] _z;
    if (_zInit)
      delete[] _zInit;
    if (_zWrite)
      delete[] _zWrite;*/
    if (_y)
      delete[] _y;
    if (_yInit)
      delete[] _yInit;
    if (_yWrite)
      delete[] _yWrite;
    if (_ypWrite)
      delete[] _ypWrite;
    if (_yp)
      delete[] _yp;
    if (_dae_res)
      delete[] _dae_res;
    if (_zeroSign)
      delete[] _zeroSign;
    if (_absTol)
      delete[] _absTol;
    if(_delta)
      delete [] _delta;
    if(_deltaInv)
      delete [] _deltaInv;
    if(_ysave)
      delete [] _ysave;


	_y = new double[_dimSys];
	_yp = new double[_dimSys];
    _yInit = new double[_dimSys];
    _yWrite = new double[_dimSys];
	_ypWrite = new double[_dimSys];
	_dae_res = new double[_dimSys];
	/*
	_z = new double[_dimSys];
    _zInit = new double[_dimSys];
    _zWrite = new double[_dimSys];
	*/

    _zeroSign = new int[_dimZeroFunc];
    _absTol = new double[_dimSys];
    _delta =new double[_dimSys];
    _deltaInv =new double[_dimSys];
    _ysave =new double[_dimSys];

    memset(_y, 0, _dimSys * sizeof(double));
	memset(_yp, 0, _dimSys * sizeof(double));
    memset(_yInit, 0, _dimSys * sizeof(double));
    memset(_ysave, 0, _dimSys * sizeof(double));
	 std::fill_n(_absTol, _dimSys, 1.0);
    // Counter initialisieren
    _outStps = 0;

    if (_idasettings->getDenseOutput())
    {
      // Ausgabeschrittweite
      _hOut = global_settings->gethOutput();

    }

    // Allocate memory for the solver
    _idaMem = IDACreate();
    if (check_flag((void*) _idaMem, "IDACreate", 0))
    {
      _idid = -5;
      throw std::invalid_argument(/*_idid,_tCurrent,*/"Ida::initialize()");
    }

    //
    // Make Ida ready for integration
    //

    // Set initial values for IDA
    //_continuous_system->evaluateAll(IContinuous::CONTINUOUS);
   _continuous_system->getContinuousStates(_yInit);
    memcpy(_y, _yInit, _dimStates * sizeof(double));
    if(_dimAE>0)
	{
       _mixed_system->getAlgebraicDAEVars(_yInit+_dimStates);
	    memcpy(_y+_dimStates, _yInit+_dimStates, _dimAE * sizeof(double));
	  _continuous_system->getContinuousStates(_yp);
	}
    // Get nominal values
	 _continuous_system->getNominalStates(_absTol);
    for (int i = 0; i < _dimStates; i++)
	    _absTol[i] = dynamic_cast<ISolverSettings*>(_idasettings)->getATol();

    _CV_y0 = N_VMake_Serial(_dimSys, _yInit);
    _CV_y = N_VMake_Serial(_dimSys, _y);
    _CV_yp = N_VMake_Serial(_dimSys, _yp);
    _CV_yWrite = N_VMake_Serial(_dimSys, _yWrite);
	_CV_ypWrite = N_VMake_Serial(_dimSys, _ypWrite);
    _CV_absTol = N_VMake_Serial(_dimSys, _absTol);

    if (check_flag((void*) _CV_y0, "N_VMake_Serial", 0))
    {
      _idid = -5;
      throw std::invalid_argument("Ida::initialize()");
    }

	//is already initialized: calcFunction(_tCurrent, NV_DATA_S(_CV_y0), NV_DATA_S(_CV_yp),NV_DATA_S(_CV_yp));

    // Initialize Ida (Initial values are required)
    _idid = IDAInit(_idaMem, rhsFunctionCB, _tCurrent, _CV_y0, _CV_yp);
    if (_idid < 0)
    {
      _idid = -5;
      throw std::invalid_argument("Ida::initialize()");
    }
	_idid = IDASetErrHandlerFn(_idaMem, errOutputIDA, _data);
	 if (_idid < 0)
      throw std::invalid_argument("IDA::initialize()");
    // Set Tolerances
    _idid = IDASVtolerances(_idaMem, dynamic_cast<ISolverSettings*>(_idasettings)->getRTol(), _CV_absTol);    // RTOL and ATOL
    if (_idid < 0)
      throw std::invalid_argument("IDA::initialize()");

    // Set the pointer to user-defined data
    _idid = IDASetUserData(_idaMem, _data);
    if (_idid < 0)
      throw std::invalid_argument("IDA::initialize()");

    _idid = IDASetInitStep(_idaMem, 1e-6);    // INITIAL STEPSIZE
    if (_idid < 0)
      throw std::invalid_argument("Ida::initialize()");


    _idid = IDASetMaxStep(_idaMem, global_settings->getEndTime() / 10.0);       // MAXIMUM STEPSIZE
    if (_idid < 0)
      throw std::invalid_argument("IDA::initialize()");

    _idid = IDASetMaxNonlinIters(_idaMem, 5);      // Max number of iterations
    if (_idid < 0)
      throw std::invalid_argument("IDA::initialize()");
    _idid = IDASetMaxErrTestFails(_idaMem, 100);
    if (_idid < 0)
      throw std::invalid_argument("IDA::initialize()");

    _idid = IDASetMaxNumSteps(_idaMem, 1e3);            // Max Number of steps
    if (_idid < 0)
      throw std::invalid_argument(/*_idid,_tCurrent,*/"IDA::initialize()");

    // Initialize linear solver
    _idid = IDADense(_idaMem, _dimSys);
    if (_idid < 0)
      throw std::invalid_argument("IDA::initialize()");
    if(_dimAE>0)
	{
	    _idid = IDASetSuppressAlg(_idaMem, TRUE);
        double* tmp = new double[_dimSys];
	    std::fill_n(tmp, _dimStates, 1.0);
	    std::fill_n(tmp+_dimStates, _dimAE, 0.0);
	   _idid = IDASetId(_idaMem, N_VMake_Serial(_dimSys,tmp));
	    delete [] tmp;
	    if (_idid < 0)
         throw std::invalid_argument("IDA::initialize()");
	}

  // Use own jacobian matrix
  //_idid = CVDlsSetDenseJacFn(_idaMem, &jacobianFunctionCB);
  //if (_idid < 0)
  //    throw std::invalid_argument("IDA::initialize()");

    if (_dimZeroFunc)
    {
      _idid = IDARootInit(_idaMem, _dimZeroFunc, &zeroFunctionCB);

      memset(_zeroSign, 0, _dimZeroFunc * sizeof(int));
      _idid = IDASetRootDirection(_idaMem, _zeroSign);
      if (_idid < 0)
        throw std::invalid_argument(/*_idid,_tCurrent,*/"IDA::initialize()");
      memset(_zeroSign, -1, _dimZeroFunc * sizeof(int));
      memset(_zeroVal, -1, _dimZeroFunc * sizeof(int));

    }


    _ida_initialized = true;

    //
    // IDA is ready for integration
    //
    // BOOST_LOG_SEV(ida_lg::get(), ida_info) << "IDA initialized";
  }
}
Esempio n. 7
0
void CvodeSolver::initialize(const double &pVoiStart,
                             const int &pRatesStatesCount, double *pConstants,
                             double *pRates, double *pStates,
                             double *pAlgebraic,
                             ComputeRatesFunction pComputeRates)
{
    if (!mSolver) {
        // Retrieve some of the CVODE properties

        double maximumStep = MaximumStepDefaultValue;
        int maximumNumberOfSteps = MaximumNumberOfStepsDefaultValue;
        QString integrationMethod = IntegrationMethodDefaultValue;
        QString iterationType = IterationTypeDefaultValue;
        QString linearSolver = LinearSolverDefaultValue;
        QString preconditioner = PreconditionerDefaultValue;
        int upperHalfBandwidth = UpperHalfBandwidthDefaultValue;
        int lowerHalfBandwidth = LowerHalfBandwidthDefaultValue;
        double relativeTolerance = RelativeToleranceDefaultValue;
        double absoluteTolerance = AbsoluteToleranceDefaultValue;

        if (mProperties.contains(MaximumStepId)) {
            maximumStep = mProperties.value(MaximumStepId).toDouble();
        } else {
            emit error(QObject::tr("the 'maximum step' property value could not be retrieved"));

            return;
        }

        if (mProperties.contains(MaximumNumberOfStepsId)) {
            maximumNumberOfSteps = mProperties.value(MaximumNumberOfStepsId).toInt();
        } else {
            emit error(QObject::tr("the 'maximum number of steps' property value could not be retrieved"));

            return;
        }

        if (mProperties.contains(IntegrationMethodId)) {
            integrationMethod = mProperties.value(IntegrationMethodId).toString();
        } else {
            emit error(QObject::tr("the 'integration method' property value could not be retrieved"));

            return;
        }

        if (mProperties.contains(IterationTypeId)) {
            iterationType = mProperties.value(IterationTypeId).toString();

            if (!iterationType.compare(NewtonIteration)) {
                // We are dealing with a Newton iteration, so retrieve and check
                // its linear solver

                if (mProperties.contains(LinearSolverId)) {
                    linearSolver = mProperties.value(LinearSolverId).toString();

                    bool needUpperAndLowerHalfBandwidths = false;

                    if (   !linearSolver.compare(DenseLinearSolver)
                        || !linearSolver.compare(DiagonalLinearSolver)) {
                        // We are dealing with a dense/diagonal linear solver,
                        // so nothing more to do
                    } else if (!linearSolver.compare(BandedLinearSolver)) {
                        // We are dealing with a banded linear solver, so we
                        // need both an upper and a lower half bandwidth

                        needUpperAndLowerHalfBandwidths = true;
                    } else {
                        // We are dealing with a GMRES/Bi-CGStab/TFQMR linear
                        // solver, so retrieve and check its preconditioner

                        if (mProperties.contains(PreconditionerId)) {
                            preconditioner = mProperties.value(PreconditionerId).toString();
                        } else {
                            emit error(QObject::tr("the 'preconditioner' property value could not be retrieved"));

                            return;
                        }

                        if (!preconditioner.compare(BandedPreconditioner)) {
                            // We are dealing with a banded preconditioner, so
                            // we need both an upper and a lower half bandwidth

                            needUpperAndLowerHalfBandwidths = true;
                        }
                    }

                    if (needUpperAndLowerHalfBandwidths) {
                        if (mProperties.contains(UpperHalfBandwidthId)) {
                            upperHalfBandwidth = mProperties.value(UpperHalfBandwidthId).toInt();

                            if (   (upperHalfBandwidth < 0)
                                || (upperHalfBandwidth >= pRatesStatesCount)) {
                                emit error(QObject::tr("the 'upper half-bandwidth' property must have a value between 0 and %1").arg(pRatesStatesCount-1));

                                return;
                            }
                        } else {
                            emit error(QObject::tr("the 'upper half-bandwidth' property value could not be retrieved"));

                            return;
                        }

                        if (mProperties.contains(LowerHalfBandwidthId)) {
                            lowerHalfBandwidth = mProperties.value(LowerHalfBandwidthId).toInt();

                            if (   (lowerHalfBandwidth < 0)
                                || (lowerHalfBandwidth >= pRatesStatesCount)) {
                                emit error(QObject::tr("the 'lower half-bandwidth' property must have a value between 0 and %1").arg(pRatesStatesCount-1));

                                return;
                            }
                        } else {
                            emit error(QObject::tr("the 'lower half-bandwidth' property value could not be retrieved"));

                            return;
                        }
                    }
                } else {
                    emit error(QObject::tr("the 'linear solver' property value could not be retrieved"));

                    return;
                }
            }
        } else {
            emit error(QObject::tr("the 'iteration type' property value could not be retrieved"));

            return;
        }

        if (mProperties.contains(RelativeToleranceId)) {
            relativeTolerance = mProperties.value(RelativeToleranceId).toDouble();

            if (relativeTolerance < 0) {
                emit error(QObject::tr("the 'relative tolerance' property must have a value greater than or equal to 0"));

                return;
            }
        } else {
            emit error(QObject::tr("the 'relative tolerance' property value could not be retrieved"));

            return;
        }

        if (mProperties.contains(AbsoluteToleranceId)) {
            absoluteTolerance = mProperties.value(AbsoluteToleranceId).toDouble();

            if (absoluteTolerance < 0) {
                emit error(QObject::tr("the 'absolute tolerance' property must have a value greater than or equal to 0"));

                return;
            }
        } else {
            emit error(QObject::tr("the 'absolute tolerance' property value could not be retrieved"));

            return;
        }

        if (mProperties.contains(InterpolateSolutionId)) {
            mInterpolateSolution = mProperties.value(InterpolateSolutionId).toBool();
        } else {
            emit error(QObject::tr("the 'interpolate solution' property value could not be retrieved"));

            return;
        }

        // Initialise the ODE solver itself

        OpenCOR::Solver::OdeSolver::initialize(pVoiStart, pRatesStatesCount,
                                               pConstants, pRates, pStates,
                                               pAlgebraic, pComputeRates);

        // Create the states vector

        mStatesVector = N_VMake_Serial(pRatesStatesCount, pStates);

        // Create the CVODE solver

        bool newtonIteration = !iterationType.compare(NewtonIteration);

        mSolver = CVodeCreate(!integrationMethod.compare(BdfMethod)?CV_BDF:CV_ADAMS,
                              newtonIteration?CV_NEWTON:CV_FUNCTIONAL);

        // Use our own error handler

        CVodeSetErrHandlerFn(mSolver, errorHandler, this);

        // Initialise the CVODE solver

        CVodeInit(mSolver, rhsFunction, pVoiStart, mStatesVector);

        // Set some user data

        mUserData = new CvodeSolverUserData(pConstants, pAlgebraic,
                                            pComputeRates);

        CVodeSetUserData(mSolver, mUserData);

        // Set the maximum step

        CVodeSetMaxStep(mSolver, maximumStep);

        // Set the maximum number of steps

        CVodeSetMaxNumSteps(mSolver, maximumNumberOfSteps);

        // Set the linear solver, if needed

        if (newtonIteration) {
            if (!linearSolver.compare(DenseLinearSolver)) {
                CVDense(mSolver, pRatesStatesCount);
            } else if (!linearSolver.compare(BandedLinearSolver)) {
                CVBand(mSolver, pRatesStatesCount, upperHalfBandwidth, lowerHalfBandwidth);
            } else if (!linearSolver.compare(DiagonalLinearSolver)) {
                CVDiag(mSolver);
            } else {
                // We are dealing with a GMRES/Bi-CGStab/TFQMR linear solver

                if (!preconditioner.compare(BandedPreconditioner)) {
                    if (!linearSolver.compare(GmresLinearSolver))
                        CVSpgmr(mSolver, PREC_LEFT, 0);
                    else if (!linearSolver.compare(BiCgStabLinearSolver))
                        CVSpbcg(mSolver, PREC_LEFT, 0);
                    else
                        CVSptfqmr(mSolver, PREC_LEFT, 0);

                    CVBandPrecInit(mSolver, pRatesStatesCount, upperHalfBandwidth, lowerHalfBandwidth);
                } else {
                    if (!linearSolver.compare(GmresLinearSolver))
                        CVSpgmr(mSolver, PREC_NONE, 0);
                    else if (!linearSolver.compare(BiCgStabLinearSolver))
                        CVSpbcg(mSolver, PREC_NONE, 0);
                    else
                        CVSptfqmr(mSolver, PREC_NONE, 0);
                }
            }
        }

        // Set the relative and absolute tolerances

        CVodeSStolerances(mSolver, relativeTolerance, absoluteTolerance);
    } else {
        // Reinitialise the CVODE object

        CVodeReInit(mSolver, pVoiStart, mStatesVector);
    }
}
Esempio n. 8
0
int cvode_init(solver_props *props){
  assert(props->statesize > 0);

  cvode_mem *mem = (cvode_mem*) malloc(props->num_models*sizeof(cvode_mem));
  unsigned int modelid;

  props->mem = mem;

  for(modelid=0; modelid<props->num_models; modelid++){
    // Set location to store the value of the next states
    mem[modelid].next_states = &(props->next_states[modelid*props->statesize]);
    mem[modelid].props = props;
    // Set the modelid on a per memory structure basis
    mem[modelid].modelid = modelid;
    // Create intial value vector
    // This is done to avoid having the change the internal indexing within the flows and for the output_buffer
    mem[modelid].y0 = N_VMake_Serial(props->statesize, mem[modelid].next_states);
    // Create data structure for solver
    //    mem[modelid].cvmem = CVodeCreate(CV_BDF, CV_NEWTON);
    mem[modelid].cvmem = CVodeCreate(props->cvode.lmm, props->cvode.iter);
    
    // Initialize CVODE
    if(CVodeInit(mem[modelid].cvmem, user_fun_wrapper, props->starttime, mem[modelid].y0) != CV_SUCCESS){
      PRINTF( "Couldn't initialize CVODE");
    }
    // Set CVODE error handler
    if(CVodeSetErrHandlerFn(mem[modelid].cvmem, cvode_err_handler, mem)){
      PRINTF( "Couldn't set CVODE error handler");
    }
    // Set solver tolerances
    if(CVodeSStolerances(mem[modelid].cvmem, props->reltol, props->abstol) != CV_SUCCESS){
      PRINTF( "Could not set CVODE tolerances");
    }
    // Set maximum order
    if(CVodeSetMaxOrd(mem[modelid].cvmem, props->cvode.max_order) != CV_SUCCESS) {
      PRINTF( "Could not set CVODE maximum order");
    }
    // Set linear solver
    switch (props->cvode.solv) {
    case CVODE_DENSE:
      if(CVDense(mem[modelid].cvmem, mem[modelid].props->statesize) != CV_SUCCESS){
	PRINTF( "Could not set CVODE DENSE linear solver");
      }
      break;
    case CVODE_DIAG:
      if(CVDiag(mem[modelid].cvmem) != CV_SUCCESS){
	PRINTF( "Could not set CVODE DIAG linear solver");
      }
      break;
    case CVODE_BAND:
      if(CVBand(mem[modelid].cvmem, mem[modelid].props->statesize, mem[modelid].props->cvode.upperhalfbw, mem[modelid].props->cvode.lowerhalfbw) != CV_SUCCESS){
	PRINTF( "Could not set CVODE BAND linear solver");
      }
      break;
    default:
      PRINTF( "No valid CVODE solver passed");
      }

    // Set user data to contain pointer to memory structure for use in model_flows
    if(CVodeSetUserData(mem[modelid].cvmem, &mem[modelid]) != CV_SUCCESS){
      PRINTF( "CVODE failed to initialize user data");
    }
  }

  return 0;
}
Esempio n. 9
0
bool kinsol_solve(void) {
	double fnormtol;
	N_Vector y, scale, constraints;
	int mset, flag;
	void *kmem;

	y = scale = constraints = NULL;
	kmem = NULL;

	/* Create vectors for solution, scales, and constraints */

	y = N_VMake_Serial(nvariables, variables);
	if (y == NULL) goto cleanup;

	scale = N_VNew_Serial(nvariables);
	if (scale == NULL) goto cleanup;

	constraints = N_VNew_Serial(nvariables);
	if (constraints == NULL) goto cleanup;

	/* Initialize and allocate memory for KINSOL */

	kmem = KINCreate();
	if (kmem == NULL) goto cleanup;

	flag = KINInit(kmem, _f, y); 
	if (flag < 0) goto cleanup;

	// This constrains metabolites >= 0
	N_VConst_Serial(1.0, constraints);
	flag = KINSetConstraints(kmem, constraints);
	if (flag < 0) goto cleanup;

	fnormtol  = ARGS.ABSTOL; 
	flag = KINSetFuncNormTol(kmem, fnormtol);
	if (flag < 0) goto cleanup;

	//scsteptol = ARGS.RELTOL;
	//flag = KINSetScaledStepTol(kmem, scsteptol);
	//if (flag < 0) goto cleanup;

	/* Attach dense linear solver */

	flag = KINDense(kmem, nvariables);
	if (flag < 0) goto cleanup;

	flag = KINDlsSetDenseJacFn(kmem, _dfdy);
	if (flag < 0) goto cleanup;

	/* Indicate exact Newton */

	//This makes sure that the user-supplied Jacobian gets evaluated onevery step.
	mset = 1;
	flag = KINSetMaxSetupCalls(kmem, mset);
	if (flag < 0) goto cleanup;

	/* Initial guess is the intial variable concentrations */

	/* Call KINSol to solve problem */

	N_VConst_Serial(1.0,scale);
	flag = KINSol(kmem,           /* KINSol memory block */
	              y,              /* initial guess on input; solution vector */
	              KIN_NONE, /* basic Newton iteration */
	              scale,          /* scaling vector, for the variable cc */
	              scale);         /* scaling vector for function values fval */
	if((ARGS.MODE != ABC) and (ARGS.MODE != ABCSIM) and (ARGS.MODE != Prior))
		OUT_nums();
	if (flag < 0) goto cleanup;


	N_VDestroy_Serial(y);
	N_VDestroy_Serial(scale);
	N_VDestroy_Serial(constraints);
	KINFree(&kmem);

	return true;
	
	 cleanup:
	error("Could not integrate!\n");
	if (y!=NULL) N_VDestroy_Serial(y);
	if (scale!=NULL) N_VDestroy_Serial(scale);
	if (constraints!=NULL) N_VDestroy_Serial(constraints);
	if (kmem!=NULL) KINFree(&kmem);
	return false;
}
Esempio n. 10
0
void CvodeSolver::initialize(const double &pVoiStart, const int &pStatesCount,
                             double *pConstants, double *pStates,
                             double *pRates, double *pAlgebraic,
                             ComputeRatesFunction pComputeRates)
{
    if (!mSolver) {
        // Initialise the ODE solver itself

        OpenCOR::CoreSolver::CoreOdeSolver::initialize(pVoiStart, pStatesCount,
                                                       pConstants, pStates,
                                                       pRates, pAlgebraic,
                                                       pComputeRates);

        // Retrieve some of the CVODE properties

        if (mProperties.contains(MaximumStepProperty)) {
            mMaximumStep = mProperties.value(MaximumStepProperty).toDouble();
        } else {
            emit error(QObject::tr("the 'maximum step' property value could not be retrieved"));

            return;
        }

        if (mProperties.contains(MaximumNumberOfStepsProperty)) {
            mMaximumNumberOfSteps = mProperties.value(MaximumNumberOfStepsProperty).toInt();
        } else {
            emit error(QObject::tr("the 'maximum number of steps' property value could not be retrieved"));

            return;
        }

        if (mProperties.contains(RelativeToleranceProperty)) {
            mRelativeTolerance = mProperties.value(RelativeToleranceProperty).toDouble();
        } else {
            emit error(QObject::tr("the 'relative tolerance' property value could not be retrieved"));

            return;
        }

        if (mProperties.contains(AbsoluteToleranceProperty)) {
            mAbsoluteTolerance = mProperties.value(AbsoluteToleranceProperty).toDouble();
        } else {
            emit error(QObject::tr("the 'absolute tolerance' property value could not be retrieved"));

            return;
        }

        // Create the states vector

        mStatesVector = N_VMake_Serial(pStatesCount, pStates);

        // Create the CVODE solver

        mSolver = CVodeCreate(CV_BDF, CV_NEWTON);

        // Use our own error handler

        CVodeSetErrHandlerFn(mSolver, errorHandler, this);

        // Initialise the CVODE solver

        CVodeInit(mSolver, rhsFunction, pVoiStart, mStatesVector);

        // Set some user data

        delete mUserData;   // Just in case the solver got initialised before

        mUserData = new CvodeSolverUserData(pConstants, pAlgebraic,
                                            pComputeRates);

        CVodeSetUserData(mSolver, mUserData);

        // Set the linear solver

        CVDense(mSolver, pStatesCount);

        // Set the maximum step

        CVodeSetMaxStep(mSolver, mMaximumStep);

        // Set the maximum number of steps

        CVodeSetMaxNumSteps(mSolver, mMaximumNumberOfSteps);

        // Set the relative and absolute tolerances

        CVodeSStolerances(mSolver, mRelativeTolerance, mAbsoluteTolerance);
    } else {
        // Reinitialise the CVODE object

        CVodeReInit(mSolver, pVoiStart, mStatesVector);
    }
}