<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/*
$Log: AliT0Preprocessor.cxx,v $
Revision 1.8  2007/12/07 15:22:51  alla
bug fixed by Alberto

Revision 1.7  2007/12/06 16:35:24  alla
new bugs fixed by Tomek

Revision 1.5  2007/11/23 19:28:52  alla
bug fixed

Version 2.1  2007/11/21
Preprocessor storing data to OCDB (T.Malkiewicz)

Version 1.1  2006/10
Preliminary test version (T.Malkiewicz)
*/
// T0 preprocessor:
// 1) takes data from DCS and passes it to the class AliTOFDataDCS
// for processing and writes the result to the Reference DB.
// 2) takes data form DAQ (both from Laser Calibration and Physics runs),
// processes it, and stores either to OCDB or to Reference DB.

#include "AliT0Preprocessor.h"
#include "AliT0DataDCS.h"
#include "AliT0CalibWalk.h"
#include "AliT0CalibTimeEq.h"

#include "AliCDBMetaData.h"
#include "AliDCSValue.h"
#include "AliLog.h"

#include <TTimeStamp.h>
#include <TFile.h>
#include <TObjString.h>
#include <TNamed.h>
#include "AliT0Dqclass.h"

ClassImp(AliT0Preprocessor)

//____________________________________________________
AliT0Preprocessor::AliT0Preprocessor(AliShuttleInterface* shuttle) :
  AliPreprocessor("T00", shuttle),
  fData(0)
{
  //constructor
}
//____________________________________________________

AliT0Preprocessor::~AliT0Preprocessor()
{
  //destructor
  delete fData;
  fData = 0;
}
//____________________________________________________

void AliT0Preprocessor::Initialize(Int_t run, UInt_t startTime, UInt_t endTime)
{
  // Creates AliT0DataDCS object
  AliPreprocessor::Initialize(run, startTime, endTime);
  AliInfo(Form("\n\tRun %d \n\tStartTime %s \n\tEndTime %s", run, TTimeStamp(startTime).AsString(), TTimeStamp(endTime).AsString()));
  fData = new AliT0DataDCS(fRun, fStartTime, fEndTime);
}
//____________________________________________________

UInt_t AliT0Preprocessor::Process(TMap* dcsAliasMap )
{
  // T0 preprocessor return codes:
  // return=0 : all ok
  // return=1 : no DCS input data
  // return=2 : failed to store DCS data
  // return=3 : no Laser data (Walk correction)
  // return=4 : failed to store OCDB time equalized data
  // return=5 : no DAQ input for OCDB
  // return=6 : failed to retrieve DAQ data from OCDB
  // return=7 : failed to store T0 OCDB data

	Bool_t resultDCSMap=kFALSE;
	Bool_t resultDCSStore=kFALSE;
	Bool_t resultLaser=kFALSE;
	Bool_t resultOnline=kFALSE;

        if(!dcsAliasMap)
        {
          Log("No DCS input data");
          return 1;
        }
        else
        {
	 /*
          resultDCSMap=fData->ProcessData(*dcsAliasMap);
          if(!resultDCSMap)
          {
            Log("Error when processing DCS data");
            return 2;// return error Code for processed DCS data not stored
          }
          else
          {
            AliCDBMetaData metaDataDCS;
            metaDataDCS.SetBeamPeriod(0);
            metaDataDCS.SetResponsible("Tomasz Malkiewicz");
            metaDataDCS.SetComment("This preprocessor fills an AliTODataDCS object.");
            AliInfo("Storing DCS Data");
            resultDCSStore = Store("Calib","DCSData",fData, &metaDataDCS);
            if (!resultDCSStore)
            {
              Log("Some problems occurred while storing DCS data results in ReferenceDB");
              return 2;// return error Code for processed DCS data not stored
            }

          }
	  */
        }

        // processing DAQ

        TString runType = GetRunType();

        if(runType == "STANDALONE")
        {
          TList* list = GetFileSources(kDAQ, "LASER");
          if (list)
          {
            TIter iter(list);
            TObjString *source;
            while ((source = dynamic_cast<TObjString *> (iter.Next())))
            {
              const char *laserFile = GetFile(kDAQ, "LASER", source->GetName());
              if (laserFile)
              {
                Log(Form("File with Id LASER found in source %s!", source->GetName()));
                AliT0CalibWalk *laser = new AliT0CalibWalk();
                laser->MakeWalkCorrGraph(laserFile);
                AliCDBMetaData metaData;
                metaData.SetBeamPeriod(0);
                metaData.SetResponsible("Tomek&Michal");
                metaData.SetComment("Walk correction from laser runs.");
		resultLaser=Store("Calib","Slewing_Walk", laser, &metaData, 0, 1);
                delete laser;
              }
              else
              {
                Log(Form("Could not find file with Id LASER in source %s!", source->GetName()));
                return 1;
              }
            }
            if (!resultLaser)
            {
              Log("No Laser Data stored");
              return 3;//return error code for failure in storing Laser Data
            }
          } else {
	  	Log("No sources found for id LASER!");
		return 1;
	  }
        }
        else if(runType == "PHYSICS")
        {
          TList* listPhys = GetFileSources(kDAQ, "PHYSICS");
          if (listPhys)
          {
            TIter iter(listPhys);
            TObjString *sourcePhys;
            while ((sourcePhys = dynamic_cast<TObjString *> (iter.Next())))
            {
              const char *filePhys = GetFile(kDAQ, "PHYSICS", sourcePhys->GetName());
              if (filePhys)
              {
                AliT0CalibTimeEq *online = new AliT0CalibTimeEq();
                online->Reset();
                online->ComputeOnlineParams(filePhys);
                AliCDBMetaData metaData;
                metaData.SetBeamPeriod(0);
                metaData.SetResponsible("Tomek&Michal");
                metaData.SetComment("Time equalizing result.");
                resultOnline = Store("Calib","TimeDelay", online, &metaData, 0, 1);
                delete online;
              }
              else
              {
                Log(Form("Could not find file with Id PHYSICS in source %s!", sourcePhys->GetName()));
                return 1;
              }
            }
            if (!resultOnline)
            {
              Log("No Laser Data stored");
              return 4;//return error code for failure in storing OCDB Data
            }
          } else {
	  	Log("No sources found for id PHYSICS!");
		return 1;
	  }
        }

  return 0;
}
<commit_msg> remove DSC data from preprocessor<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/*
$Log: AliT0Preprocessor.cxx,v $
Revision 1.8  2007/12/07 15:22:51  alla
bug fixed by Alberto

Revision 1.7  2007/12/06 16:35:24  alla
new bugs fixed by Tomek

Revision 1.5  2007/11/23 19:28:52  alla
bug fixed

Version 2.1  2007/11/21
Preprocessor storing data to OCDB (T.Malkiewicz)

Version 1.1  2006/10
Preliminary test version (T.Malkiewicz)
*/
// T0 preprocessor:
// 1) takes data from DCS and passes it to the class AliTOFDataDCS
// for processing and writes the result to the Reference DB.
// 2) takes data form DAQ (both from Laser Calibration and Physics runs),
// processes it, and stores either to OCDB or to Reference DB.

#include "AliT0Preprocessor.h"
#include "AliT0DataDCS.h"
#include "AliT0CalibWalk.h"
#include "AliT0CalibTimeEq.h"

#include "AliCDBMetaData.h"
#include "AliDCSValue.h"
#include "AliLog.h"

#include <TTimeStamp.h>
#include <TFile.h>
#include <TObjString.h>
#include <TNamed.h>
#include "AliT0Dqclass.h"

ClassImp(AliT0Preprocessor)

//____________________________________________________
AliT0Preprocessor::AliT0Preprocessor(AliShuttleInterface* shuttle) :
  AliPreprocessor("T00", shuttle),
  fData(0)
{
  //constructor
}
//____________________________________________________

AliT0Preprocessor::~AliT0Preprocessor()
{
  //destructor
  delete fData;
  fData = 0;
}
//____________________________________________________

void AliT0Preprocessor::Initialize(Int_t run, UInt_t startTime, UInt_t endTime)
{
  // Creates AliT0DataDCS object
  AliPreprocessor::Initialize(run, startTime, endTime);
  AliInfo(Form("\n\tRun %d \n\tStartTime %s \n\tEndTime %s", run, TTimeStamp(startTime).AsString(), TTimeStamp(endTime).AsString()));
  fData = new AliT0DataDCS(fRun, fStartTime, fEndTime);
}
//____________________________________________________

UInt_t AliT0Preprocessor::Process(TMap* dcsAliasMap )
{
  // T0 preprocessor return codes:
  // return=0 : all ok
  // return=1 : no DCS input data
  // return=2 : failed to store DCS data
  // return=3 : no Laser data (Walk correction)
  // return=4 : failed to store OCDB time equalized data
  // return=5 : no DAQ input for OCDB
  // return=6 : failed to retrieve DAQ data from OCDB
  // return=7 : failed to store T0 OCDB data

	Bool_t resultDCSMap=kFALSE;
	Bool_t resultDCSStore=kFALSE;
	Bool_t resultLaser=kFALSE;
	Bool_t resultOnline=kFALSE;

        if(!dcsAliasMap)
        {
          Log("No DCS input data");
        //  return 1;
        }
        else
        {
	 /*
          resultDCSMap=fData->ProcessData(*dcsAliasMap);
          if(!resultDCSMap)
          {
            Log("Error when processing DCS data");
            return 2;// return error Code for processed DCS data not stored
          }
          else
          {
            AliCDBMetaData metaDataDCS;
            metaDataDCS.SetBeamPeriod(0);
            metaDataDCS.SetResponsible("Tomasz Malkiewicz");
            metaDataDCS.SetComment("This preprocessor fills an AliTODataDCS object.");
            AliInfo("Storing DCS Data");
            resultDCSStore = Store("Calib","DCSData",fData, &metaDataDCS);
            if (!resultDCSStore)
            {
              Log("Some problems occurred while storing DCS data results in ReferenceDB");
              return 2;// return error Code for processed DCS data not stored
            }

          }
	  */
	  Log("No DCS input data");
        }

        // processing DAQ

        TString runType = GetRunType();

        if(runType == "STANDALONE")
        {
          TList* list = GetFileSources(kDAQ, "LASER");
          if (list)
          {
            TIter iter(list);
            TObjString *source;
            while ((source = dynamic_cast<TObjString *> (iter.Next())))
            {
              const char *laserFile = GetFile(kDAQ, "LASER", source->GetName());
              if (laserFile)
              {
                Log(Form("File with Id LASER found in source %s!", source->GetName()));
                AliT0CalibWalk *laser = new AliT0CalibWalk();
                laser->MakeWalkCorrGraph(laserFile);
                AliCDBMetaData metaData;
                metaData.SetBeamPeriod(0);
                metaData.SetResponsible("Tomek&Michal");
                metaData.SetComment("Walk correction from laser runs.");
		resultLaser=Store("Calib","Slewing_Walk", laser, &metaData, 0, 1);
                delete laser;
              }
              else
              {
                Log(Form("Could not find file with Id LASER in source %s!", source->GetName()));
                return 1;
              }
            }
            if (!resultLaser)
            {
              Log("No Laser Data stored");
              return 3;//return error code for failure in storing Laser Data
            }
          } else {
	  	Log("No sources found for id LASER!");
		return 1;
	  }
        }
        else if(runType == "PHYSICS")
        {
          TList* listPhys = GetFileSources(kDAQ, "PHYSICS");
          if (listPhys)
          {
            TIter iter(listPhys);
            TObjString *sourcePhys;
            while ((sourcePhys = dynamic_cast<TObjString *> (iter.Next())))
            {
              const char *filePhys = GetFile(kDAQ, "PHYSICS", sourcePhys->GetName());
              if (filePhys)
              {
                AliT0CalibTimeEq *online = new AliT0CalibTimeEq();
                online->Reset();
                online->ComputeOnlineParams(filePhys);
                AliCDBMetaData metaData;
                metaData.SetBeamPeriod(0);
                metaData.SetResponsible("Tomek&Michal");
                metaData.SetComment("Time equalizing result.");
                resultOnline = Store("Calib","TimeDelay", online, &metaData, 0, 1);
                delete online;
              }
              else
              {
                Log(Form("Could not find file with Id PHYSICS in source %s!", sourcePhys->GetName()));
                return 1;
              }
            }
            if (!resultOnline)
            {
              Log("No Laser Data stored");
              return 4;//return error code for failure in storing OCDB Data
            }
          } else {
	  	Log("No sources found for id PHYSICS!");
		return 1;
	  }
        }

  return 0;
}
<|endoftext|>


<commit_before>#define __TUPLE_NAMESPACE foo

#include <tuple>
#include <iostream>
#include <cassert>

int main()
{
  using type0 = foo::tuple<>;
  assert(std::tuple_size<type0>::value == 0);
  assert((std::is_empty<std::tuple_element<0,type0>>::value == true));

  assert(type0{} == type0{});
  assert(!(type0{} != type0{}));
  assert(!(type0{} < type0{}));
  assert(!(type0{} > type0{}));

  using type1 = foo::tuple<int>;
  assert(std::tuple_size<type1>::value == 1);
  assert((
    std::is_same<
      std::tuple_element_t<0,type1>,
      int
    >::value
  ));

  type1 t1;
  assert(std::get<0>(t1) == 0);

  type1 t2(13);
  assert(std::get<0>(t2) == 13);

  assert(t1 <= t2);
  assert(t1 <  t2);

  assert(t2 >= t2);
  assert(t2 >  t1);

  assert(t1 == t1);
  assert(t1 <= t1);
  assert(t1 >= t1);

  using type2 = foo::tuple<int, float>;
  assert(std::tuple_size<type2>::value == 2);
  assert((
    std::is_same<
      std::tuple_element_t<0,type2>,
      int
    >::value
  ));
  assert((
    std::is_same<
      std::tuple_element_t<1,type2>,
      float
    >::value
  ));

  type2 t3;
  assert(std::get<0>(t3) == 0);
  assert(std::get<1>(t3) == 0);

  type2 t4(13,7);
  assert(std::get<0>(t4) == 13);
  assert(std::get<1>(t4) == 7);

  assert((
    std::is_same<
      decltype(std::get<0>(t3)),
      int&
    >::value
  ));

  assert((
    std::is_same<
      decltype(std::get<1>(t3)),
      float&
    >::value
  ));

  assert((
    std::is_same<
      decltype(std::get<0>(static_cast<const type2&>(t3))),
      const int&
    >::value
  ));

  assert((
    std::is_same<
      decltype(std::get<1>(static_cast<const type2&>(t3))),
      const float&
    >::value
  ));

  assert((
    std::is_same<
      decltype(std::get<0>(std::move(t3))),
      int&&
    >::value
  ));

  assert((
    std::is_same<
      decltype(std::get<1>(std::move(t3))),
      float&&
    >::value
  ));

  using type3 = foo::tuple<int,int,int>;
  type3 t5(1,2,3);
  assert(std::get<0>(t5) == 1);
  assert(std::get<1>(t5) == 2);
  assert(std::get<2>(t5) == 3);

  type3 t6{};
  assert(std::get<0>(t6) == 0);
  assert(std::get<1>(t6) == 0);
  assert(std::get<2>(t6) == 0);

  assert(t5 != t6);
  assert(t5 >  t6);
  assert(t6 <  t5);
  assert(t5 >= t6);
  assert(t6 <= t5);

  t6 = t5;
  assert(std::get<0>(t6) == 1);
  assert(std::get<1>(t6) == 2);
  assert(std::get<2>(t6) == 3);

  assert(t5 == t6);
  assert(t5 <= t6);
  assert(t5 >= t6);

  using type4 = foo::tuple<type3,type3>;
  type4 t7(type3(1,2,3), type3(4,5,6));
  assert(std::get<0>(std::get<0>(t7)) == 1);
  assert(std::get<1>(std::get<0>(t7)) == 2);
  assert(std::get<2>(std::get<0>(t7)) == 3);

  assert(std::get<0>(std::get<1>(t7)) == 4);
  assert(std::get<1>(std::get<1>(t7)) == 5);
  assert(std::get<2>(std::get<1>(t7)) == 6);

  type3 t8(1,2,3);
  assert(std::get<0>(t5) == 1);
  assert(std::get<1>(t5) == 2);
  assert(std::get<2>(t5) == 3);

  int a, b, c;
  foo::tie(a,b,c) = t5;
  assert(a == 1);
  assert(b == 2);
  assert(c == 3);

  assert(foo::tie(a,b,c) == t5);
  assert(foo::tie(a,b,c) <= t5);
  assert(foo::tie(a,b,c) >= t5);

  auto t9 = foo::make_tuple(std::string("hi"));
  foo::tuple<std::string> t10;
  t10 = std::move(t9);
  assert(std::get<0>(t9) == "");
  assert(std::get<0>(t10) == "hi");

  assert(foo::make_tuple(1,2,3) < foo::make_tuple(1,2,4));
  assert(foo::make_tuple(1,2,4) > foo::make_tuple(1,2,3));

  return 0;
}

<commit_msg>ensures that tuple<tuple<int,int,int>&>::operator=(tuple<tuple<int,int,int>&>) has not been deleted<commit_after>#define __TUPLE_NAMESPACE foo

#include <tuple>
#include <iostream>
#include <cassert>

int main()
{
  using type0 = foo::tuple<>;
  assert(std::tuple_size<type0>::value == 0);
  assert((std::is_empty<std::tuple_element<0,type0>>::value == true));

  assert(type0{} == type0{});
  assert(!(type0{} != type0{}));
  assert(!(type0{} < type0{}));
  assert(!(type0{} > type0{}));

  using type1 = foo::tuple<int>;
  assert(std::tuple_size<type1>::value == 1);
  assert((
    std::is_same<
      std::tuple_element_t<0,type1>,
      int
    >::value
  ));

  type1 t1;
  assert(std::get<0>(t1) == 0);

  type1 t2(13);
  assert(std::get<0>(t2) == 13);

  assert(t1 <= t2);
  assert(t1 <  t2);

  assert(t2 >= t2);
  assert(t2 >  t1);

  assert(t1 == t1);
  assert(t1 <= t1);
  assert(t1 >= t1);

  using type2 = foo::tuple<int, float>;
  assert(std::tuple_size<type2>::value == 2);
  assert((
    std::is_same<
      std::tuple_element_t<0,type2>,
      int
    >::value
  ));
  assert((
    std::is_same<
      std::tuple_element_t<1,type2>,
      float
    >::value
  ));

  type2 t3;
  assert(std::get<0>(t3) == 0);
  assert(std::get<1>(t3) == 0);

  type2 t4(13,7);
  assert(std::get<0>(t4) == 13);
  assert(std::get<1>(t4) == 7);

  assert((
    std::is_same<
      decltype(std::get<0>(t3)),
      int&
    >::value
  ));

  assert((
    std::is_same<
      decltype(std::get<1>(t3)),
      float&
    >::value
  ));

  assert((
    std::is_same<
      decltype(std::get<0>(static_cast<const type2&>(t3))),
      const int&
    >::value
  ));

  assert((
    std::is_same<
      decltype(std::get<1>(static_cast<const type2&>(t3))),
      const float&
    >::value
  ));

  assert((
    std::is_same<
      decltype(std::get<0>(std::move(t3))),
      int&&
    >::value
  ));

  assert((
    std::is_same<
      decltype(std::get<1>(std::move(t3))),
      float&&
    >::value
  ));

  using type3 = foo::tuple<int,int,int>;
  type3 t5(1,2,3);
  assert(std::get<0>(t5) == 1);
  assert(std::get<1>(t5) == 2);
  assert(std::get<2>(t5) == 3);

  type3 t6{};
  assert(std::get<0>(t6) == 0);
  assert(std::get<1>(t6) == 0);
  assert(std::get<2>(t6) == 0);

  assert(t5 != t6);
  assert(t5 >  t6);
  assert(t6 <  t5);
  assert(t5 >= t6);
  assert(t6 <= t5);

  t6 = t5;
  assert(std::get<0>(t6) == 1);
  assert(std::get<1>(t6) == 2);
  assert(std::get<2>(t6) == 3);

  assert(t5 == t6);
  assert(t5 <= t6);
  assert(t5 >= t6);

  using type4 = foo::tuple<type3,type3>;
  type4 t7(type3(1,2,3), type3(4,5,6));
  assert(std::get<0>(std::get<0>(t7)) == 1);
  assert(std::get<1>(std::get<0>(t7)) == 2);
  assert(std::get<2>(std::get<0>(t7)) == 3);

  assert(std::get<0>(std::get<1>(t7)) == 4);
  assert(std::get<1>(std::get<1>(t7)) == 5);
  assert(std::get<2>(std::get<1>(t7)) == 6);

  type3 t8(1,2,3);
  assert(std::get<0>(t5) == 1);
  assert(std::get<1>(t5) == 2);
  assert(std::get<2>(t5) == 3);

  int a, b, c;
  foo::tie(a,b,c) = t5;
  assert(a == 1);
  assert(b == 2);
  assert(c == 3);

  assert(foo::tie(a,b,c) == t5);
  assert(foo::tie(a,b,c) <= t5);
  assert(foo::tie(a,b,c) >= t5);

  auto t9 = foo::make_tuple(std::string("hi"));
  foo::tuple<std::string> t10;
  t10 = std::move(t9);
  assert(std::get<0>(t9) == "");
  assert(std::get<0>(t10) == "hi");

  assert(foo::make_tuple(1,2,3) < foo::make_tuple(1,2,4));
  assert(foo::make_tuple(1,2,4) > foo::make_tuple(1,2,3));

  auto x = foo::tie(b);
  x = x;  // ensure that tuple<tuple<int,int,int>&>::operator=(tuple<tuple<int,int,int>&>) has not been deleted

  return 0;
}

<|endoftext|>


<commit_before>#include <iostream>
#include <list>
#include <cstring>
#include <csignal>
#include <cstddef>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include "service.h"
#include "ev++.h"
#include "control.h"
#include "dinit-log.h"

#ifdef __linux__
#include <sys/klog.h>
#endif

/* TODO: prevent services from respawning too quickly */
/* TODO: optional automatic restart of services */

/*
 * "simpleinit" from util-linux package handles signals as follows:
 * SIGTSTP - spawn no more gettys (in preparation for shutdown etc).
 *          In dinit terms this should probably mean "no more auto restarts"
 *          (for any service). (Actually the signal acts as a toggle, if
 *          respawn is disabled it will be re-enabled and init will
 *          act as if SIGHUP had also been sent)
 * SIGTERM - kill spawned gettys (which are still alive)
 *          Interestingly, simpleinit just sends a SIGTERM to the gettys.
 *          "shutdown" however has already sent SIGTERM to every process...
 * "/sbin/initctl -r" - rollback services (ran by "shutdown"/halt etc)
 *           shouldn't return until all services have been stopped.
 *           shutdown calls this *after* sending SIGTERM to all processes.
 *           I guess this allows user processes, if any are still around,
 *           to die before (or just as) the services fall out from underneath
 *           them. On the other hand it largely subverts the ordered service
 *           shutdown that init provides.
 * SIGQUIT - init will exec() shutdown. shutdown will detect that it is
 *           running as pid 1 and will just loop and reap child processes.
 *           This is used by shutdown so that init will not hang on to its
 *           inode, allowing the filesystem to be re-mounted readonly
 *           (this is only an issue if the init binary has been unlinked,
 *           since it's then holding an inode which can't be maintained
 *           when the filesystem is unmounted).
 *
 * Not sent by shutdown:
 * SIGHUP -  re-read inittab and spawn any new getty entries
 * SIGINT - (ctrl+alt+del handler) - fork & exec "reboot"
 *
 * On the contrary dinit currently uses:
 * SIGTERM - roll back services and then fork/exec /sbin/halt
 * SIGINT - roll back services and then fork/exec /sbin/reboot
 * SIGQUIT - exec() /sbin/shutdown as per above.
 *
 * It's an open question about whether dinit should roll back services *before*
 * running halt/reboot, since those commands should prompt rollback of services
 * anyway. But it seems safe to do so.
 */

static bool got_sigterm = false;

static ServiceSet *service_set;

static bool am_system_init = false; // true if we are the system init process
static bool do_reboot = false; // whether to reboot (instead of halting)

static bool control_socket_open = false;
int active_control_conns = 0;

static void sigint_reboot_cb(struct ev_loop *loop, ev_signal *w, int revents);
static void sigquit_cb(struct ev_loop *loop, ev_signal *w, int revents);
static void sigterm_cb(struct ev_loop *loop, ev_signal *w, int revents);

void open_control_socket(struct ev_loop *loop);

struct ev_io control_socket_io;

int main(int argc, char **argv)
{
    using namespace std;

    am_system_init = (getpid() == 1);

    if (am_system_init) {
        // setup STDIN, STDOUT, STDERR so that we can use them
        int onefd = open("/dev/console", O_RDONLY, 0);
        dup2(onefd, 0);
        int twofd = open("/dev/console", O_RDWR, 0);
        dup2(twofd, 1);
        dup2(twofd, 2);
    }

    /* Set up signal handlers etc */
    /* SIG_CHILD is ignored by default: good */
    /* sigemptyset(&sigwait_set); */
    /* sigaddset(&sigwait_set, SIGCHLD); */
    /* sigaddset(&sigwait_set, SIGINT); */
    /* sigaddset(&sigwait_set, SIGTERM); */
    /* sigprocmask(SIG_BLOCK, &sigwait_set, NULL); */

    /* list of services to start */
    list<const char *> services_to_start;

    /* service directory name */
    const char * service_dir = "/etc/dinit.d";

    // Arguments, if given, specify a list of services to start.
    // If we are running as init (PID=1), the kernel gives us any command line
    // arguments it was given but didn't recognize, including "single" (usually
    // for "boot to single user mode" aka just start the shell). We can treat
    // them as service names. In the worst case we can't find any of the named
    // services, and so we'll start the "boot" service by default.
    if (argc > 1) {
      for (int i = 1; i < argc; i++) {
        if (argv[i][0] == '-') {
            // An option...
            if (strcmp(argv[i], "--services-dir") == 0 ||
                    strcmp(argv[i], "-d") == 0) {
                ++i;
                if (i < argc) {
                    service_dir = argv[i];
                }
                else {
                    // error TODO
                }
            }
            else if (strcmp(argv[i], "--help") == 0) {
                cout << "dinit, an init with dependency management" << endl;
                cout << " --help                         : display help" << endl;
                cout << " --services-dir <dir>, -d <dir> : set base directory for service description files (-d <dir>)" << endl;
                cout << " <service-name>                 : start service with name <service-name>" << endl;
                return 0;
            }
            else {
                // unrecognized
                if (! am_system_init) {
                    cerr << "Unrecognized option: " << argv[i] << endl;
                    return 1;
                }
            }
        }
        else {
            // LILO puts "auto" on the kernel command line for unattended boots; we'll filter it.
            if (! am_system_init || strcmp(argv[i], "auto") != 0) {
                services_to_start.push_back(argv[i]);
            }
        }
      }
    }

    if (services_to_start.empty()) {
        services_to_start.push_back("boot");
    }

    // Set up signal handlers
    ev_signal sigint_ev_signal;
    if (am_system_init) {
      ev_signal_init(&sigint_ev_signal, sigint_reboot_cb, SIGINT);
    }
    else {
      ev_signal_init(&sigint_ev_signal, sigterm_cb, SIGINT);
    }

    ev_signal sigquit_ev_signal;
    if (am_system_init) {
        // PID 1: SIGQUIT exec's shutdown
        ev_signal_init(&sigquit_ev_signal, sigquit_cb, SIGQUIT);
    }
    else {
        // Otherwise: SIGQUIT terminates dinit
        ev_signal_init(&sigquit_ev_signal, sigterm_cb, SIGQUIT);
    }

    ev_signal sigterm_ev_signal;
    ev_signal_init(&sigterm_ev_signal, sigterm_cb, SIGTERM);

    /* Set up libev */
    struct ev_loop *loop = ev_default_loop(EVFLAG_AUTO /* | EVFLAG_SIGNALFD */);
    ev_signal_start(loop, &sigint_ev_signal);
    ev_signal_start(loop, &sigquit_ev_signal);
    ev_signal_start(loop, &sigterm_ev_signal);

    // Try to open control socket (may fail due to readonly filesystem)
    open_control_socket(loop);

#ifdef __linux__
    if (am_system_init) {
        // Disable non-critical kernel output to console
        klogctl(6 /* SYSLOG_ACTION_CONSOLE_OFF */, nullptr, 0);
    }
#endif

    /* start requested services */
    service_set = new ServiceSet(service_dir);
    for (list<const char *>::iterator i = services_to_start.begin();
            i != services_to_start.end();
            ++i) {
        try {
            service_set->startService(*i);
        }
        catch (ServiceNotFound &snf) {
            log(LogLevel::ERROR, "Could not find service description: ", snf.serviceName);
        }
        catch (ServiceLoadExc &sle) {
            log(LogLevel::ERROR, "Problem loading service description: ", sle.serviceName);
        }
    }

    event_loop:

    // Process events until all services have terminated.
    while (service_set->count_active_services() != 0 || active_control_conns != 0) {
        ev_loop(loop, EVLOOP_ONESHOT);
    }

    if (am_system_init) {
        logMsgBegin(LogLevel::INFO, "No more active services.");
        if (do_reboot) {
            logMsgEnd(" Will reboot.");
        }
        else if (got_sigterm) {
            logMsgEnd(" Will halt.");
        }
        else {
            logMsgEnd(" Re-initiating boot sequence.");
        }
    }

    if (am_system_init) {
        if (do_reboot) {
            // TODO log error from fork
            if (fork() == 0) {
                execl("/sbin/reboot", "/sbin/reboot", (char *) 0);
            }
        }
        else if (got_sigterm) {
            // TODO log error from fork
            if (fork() == 0) {
                execl("/sbin/halt", "/sbin/halt", (char *) 0);
            }
        }
        else {
            // Hmmmmmm.
            // It could be that we started in single user mode, and the
            // user has now exited the shell. We'll try and re-start the
            // boot process...
            try {
                service_set->startService("boot");
                goto event_loop; // yes, the "evil" goto
            }
            catch (...) {
                // Now WTF do we do? try to reboot
                log(LogLevel::ERROR, "Could not start 'boot' service; rebooting.");
                if (fork() == 0) {
                    execl("/sbin/reboot", "/sbin/reboot", (char *) 0);
                }
            }
        }

        // PID 1 should never exit:
        while (true) {
            pause();
        }
    }

    return 0;
}

// Callback for control socket
static void control_socket_cb(struct ev_loop *loop, ev_io *w, int revents)
{
    // TODO limit the number of active connections. Keep a tally, and disable the
    // control connection listening socket watcher if it gets high, and re-enable
    // it once it falls below the maximum.

    // Accept a connection
    int sockfd = w->fd;

    int newfd = accept4(sockfd, nullptr, nullptr, SOCK_NONBLOCK | SOCK_CLOEXEC);

    if (newfd != -1) {
        try {
            new ControlConn(loop, service_set, newfd);  // will delete itself when it's finished
        }
        catch (std::bad_alloc &bad_alloc_exc) {
            log(LogLevel::ERROR, "Accepting control connection: Out of memory");
            close(newfd);
        }
    }
}

void open_control_socket(struct ev_loop *loop)
{
    if (! control_socket_open) {
        // TODO make this use a per-user address if PID != 1, and make the address
        // overridable from the command line

        const char * saddrname = "/dev/dinitctl";
        struct sockaddr_un name;

        if (am_system_init) {
            unlink(saddrname);
        }

        name.sun_family = AF_UNIX;
        strcpy(name.sun_path, saddrname); // TODO make this safe for long names
        int namelen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(saddrname);

        int sockfd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
        if (sockfd == -1) {
            log(LogLevel::ERROR, "Error creating control socket: ", strerror(errno));
            return;
        }

        if (bind(sockfd, (struct sockaddr *) &name, namelen) == -1) {
            log(LogLevel::ERROR, "Error binding control socket: ", strerror(errno));
            close(sockfd);
            return;
        }

        // No connections can be made until we listen, so it is fine to change the permissions now
        // (and anyway there is no way to atomically create the socket and set permissions):
        if (chmod(saddrname, S_IRUSR | S_IWUSR) == -1) {
            log(LogLevel::ERROR, "Error setting control socket permissions: ", strerror(errno));
            close(sockfd);
            return;
        }

        if (listen(sockfd, 10) == -1) {
            log(LogLevel::ERROR, "Error listening on control socket: ", strerror(errno));
            close(sockfd);
            return;
        }

        control_socket_open = true;
        ev_io_init(&control_socket_io, control_socket_cb, sockfd, EV_READ);
        ev_io_start(loop, &control_socket_io);
    }
}

/* handle SIGINT signal (generated by kernel when ctrl+alt+del pressed) */
static void sigint_reboot_cb(struct ev_loop *loop, ev_signal *w, int revents)
{
    do_reboot = true;
    log_to_console = true;
    service_set->stop_all_services();
}

/* handle SIGQUIT (if we are system init) */
static void sigquit_cb(struct ev_loop *loop, ev_signal *w, int revents)
{
    // This allows remounting the filesystem read-only if the dinit binary has been
    // unlinked. In that case the kernel holds the binary open, so that it can't be
    // properly removed.
    execl("/sbin/shutdown", "/sbin/shutdown", (char *) 0);
    log(LogLevel::ERROR, "Error executing /sbin/shutdown: ", strerror(errno));
}

/* handle SIGTERM - stop all services */
static void sigterm_cb(struct ev_loop *loop, ev_signal *w, int revents)
{
    got_sigterm = true;
    log_to_console = true;
    service_set->stop_all_services();
}
<commit_msg>Remove functional TODO comments.<commit_after>#include <iostream>
#include <list>
#include <cstring>
#include <csignal>
#include <cstddef>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include "service.h"
#include "ev++.h"
#include "control.h"
#include "dinit-log.h"

#ifdef __linux__
#include <sys/klog.h>
#endif

/*
 * "simpleinit" from util-linux package handles signals as follows:
 * SIGTSTP - spawn no more gettys (in preparation for shutdown etc).
 *          In dinit terms this should probably mean "no more auto restarts"
 *          (for any service). (Actually the signal acts as a toggle, if
 *          respawn is disabled it will be re-enabled and init will
 *          act as if SIGHUP had also been sent)
 * SIGTERM - kill spawned gettys (which are still alive)
 *          Interestingly, simpleinit just sends a SIGTERM to the gettys.
 *          "shutdown" however has already sent SIGTERM to every process...
 * "/sbin/initctl -r" - rollback services (ran by "shutdown"/halt etc)
 *           shouldn't return until all services have been stopped.
 *           shutdown calls this *after* sending SIGTERM to all processes.
 *           I guess this allows user processes, if any are still around,
 *           to die before (or just as) the services fall out from underneath
 *           them. On the other hand it largely subverts the ordered service
 *           shutdown that init provides.
 * SIGQUIT - init will exec() shutdown. shutdown will detect that it is
 *           running as pid 1 and will just loop and reap child processes.
 *           This is used by shutdown so that init will not hang on to its
 *           inode, allowing the filesystem to be re-mounted readonly
 *           (this is only an issue if the init binary has been unlinked,
 *           since it's then holding an inode which can't be maintained
 *           when the filesystem is unmounted).
 *
 * Not sent by shutdown:
 * SIGHUP -  re-read inittab and spawn any new getty entries
 * SIGINT - (ctrl+alt+del handler) - fork & exec "reboot"
 *
 * On the contrary dinit currently uses:
 * SIGTERM - roll back services and then fork/exec /sbin/halt
 * SIGINT - roll back services and then fork/exec /sbin/reboot
 * SIGQUIT - exec() /sbin/shutdown as per above.
 *
 * It's an open question about whether dinit should roll back services *before*
 * running halt/reboot, since those commands should prompt rollback of services
 * anyway. But it seems safe to do so.
 */

static bool got_sigterm = false;

static ServiceSet *service_set;

static bool am_system_init = false; // true if we are the system init process
static bool do_reboot = false; // whether to reboot (instead of halting)

static bool control_socket_open = false;
int active_control_conns = 0;

static void sigint_reboot_cb(struct ev_loop *loop, ev_signal *w, int revents);
static void sigquit_cb(struct ev_loop *loop, ev_signal *w, int revents);
static void sigterm_cb(struct ev_loop *loop, ev_signal *w, int revents);

void open_control_socket(struct ev_loop *loop);

struct ev_io control_socket_io;

int main(int argc, char **argv)
{
    using namespace std;

    am_system_init = (getpid() == 1);

    if (am_system_init) {
        // setup STDIN, STDOUT, STDERR so that we can use them
        int onefd = open("/dev/console", O_RDONLY, 0);
        dup2(onefd, 0);
        int twofd = open("/dev/console", O_RDWR, 0);
        dup2(twofd, 1);
        dup2(twofd, 2);
    }

    /* Set up signal handlers etc */
    /* SIG_CHILD is ignored by default: good */
    /* sigemptyset(&sigwait_set); */
    /* sigaddset(&sigwait_set, SIGCHLD); */
    /* sigaddset(&sigwait_set, SIGINT); */
    /* sigaddset(&sigwait_set, SIGTERM); */
    /* sigprocmask(SIG_BLOCK, &sigwait_set, NULL); */

    /* list of services to start */
    list<const char *> services_to_start;

    /* service directory name */
    const char * service_dir = "/etc/dinit.d";

    // Arguments, if given, specify a list of services to start.
    // If we are running as init (PID=1), the kernel gives us any command line
    // arguments it was given but didn't recognize, including "single" (usually
    // for "boot to single user mode" aka just start the shell). We can treat
    // them as service names. In the worst case we can't find any of the named
    // services, and so we'll start the "boot" service by default.
    if (argc > 1) {
      for (int i = 1; i < argc; i++) {
        if (argv[i][0] == '-') {
            // An option...
            if (strcmp(argv[i], "--services-dir") == 0 ||
                    strcmp(argv[i], "-d") == 0) {
                ++i;
                if (i < argc) {
                    service_dir = argv[i];
                }
                else {
                    // error TODO
                }
            }
            else if (strcmp(argv[i], "--help") == 0) {
                cout << "dinit, an init with dependency management" << endl;
                cout << " --help                         : display help" << endl;
                cout << " --services-dir <dir>, -d <dir> : set base directory for service description files (-d <dir>)" << endl;
                cout << " <service-name>                 : start service with name <service-name>" << endl;
                return 0;
            }
            else {
                // unrecognized
                if (! am_system_init) {
                    cerr << "Unrecognized option: " << argv[i] << endl;
                    return 1;
                }
            }
        }
        else {
            // LILO puts "auto" on the kernel command line for unattended boots; we'll filter it.
            if (! am_system_init || strcmp(argv[i], "auto") != 0) {
                services_to_start.push_back(argv[i]);
            }
        }
      }
    }

    if (services_to_start.empty()) {
        services_to_start.push_back("boot");
    }

    // Set up signal handlers
    ev_signal sigint_ev_signal;
    if (am_system_init) {
      ev_signal_init(&sigint_ev_signal, sigint_reboot_cb, SIGINT);
    }
    else {
      ev_signal_init(&sigint_ev_signal, sigterm_cb, SIGINT);
    }

    ev_signal sigquit_ev_signal;
    if (am_system_init) {
        // PID 1: SIGQUIT exec's shutdown
        ev_signal_init(&sigquit_ev_signal, sigquit_cb, SIGQUIT);
    }
    else {
        // Otherwise: SIGQUIT terminates dinit
        ev_signal_init(&sigquit_ev_signal, sigterm_cb, SIGQUIT);
    }

    ev_signal sigterm_ev_signal;
    ev_signal_init(&sigterm_ev_signal, sigterm_cb, SIGTERM);

    /* Set up libev */
    struct ev_loop *loop = ev_default_loop(EVFLAG_AUTO /* | EVFLAG_SIGNALFD */);
    ev_signal_start(loop, &sigint_ev_signal);
    ev_signal_start(loop, &sigquit_ev_signal);
    ev_signal_start(loop, &sigterm_ev_signal);

    // Try to open control socket (may fail due to readonly filesystem)
    open_control_socket(loop);

#ifdef __linux__
    if (am_system_init) {
        // Disable non-critical kernel output to console
        klogctl(6 /* SYSLOG_ACTION_CONSOLE_OFF */, nullptr, 0);
    }
#endif

    /* start requested services */
    service_set = new ServiceSet(service_dir);
    for (list<const char *>::iterator i = services_to_start.begin();
            i != services_to_start.end();
            ++i) {
        try {
            service_set->startService(*i);
        }
        catch (ServiceNotFound &snf) {
            log(LogLevel::ERROR, "Could not find service description: ", snf.serviceName);
        }
        catch (ServiceLoadExc &sle) {
            log(LogLevel::ERROR, "Problem loading service description: ", sle.serviceName);
        }
    }

    event_loop:

    // Process events until all services have terminated.
    while (service_set->count_active_services() != 0 || active_control_conns != 0) {
        ev_loop(loop, EVLOOP_ONESHOT);
    }

    if (am_system_init) {
        logMsgBegin(LogLevel::INFO, "No more active services.");
        if (do_reboot) {
            logMsgEnd(" Will reboot.");
        }
        else if (got_sigterm) {
            logMsgEnd(" Will halt.");
        }
        else {
            logMsgEnd(" Re-initiating boot sequence.");
        }
    }

    if (am_system_init) {
        if (do_reboot) {
            // TODO log error from fork
            if (fork() == 0) {
                execl("/sbin/reboot", "/sbin/reboot", (char *) 0);
            }
        }
        else if (got_sigterm) {
            // TODO log error from fork
            if (fork() == 0) {
                execl("/sbin/halt", "/sbin/halt", (char *) 0);
            }
        }
        else {
            // Hmmmmmm.
            // It could be that we started in single user mode, and the
            // user has now exited the shell. We'll try and re-start the
            // boot process...
            try {
                service_set->startService("boot");
                goto event_loop; // yes, the "evil" goto
            }
            catch (...) {
                // Now WTF do we do? try to reboot
                log(LogLevel::ERROR, "Could not start 'boot' service; rebooting.");
                if (fork() == 0) {
                    execl("/sbin/reboot", "/sbin/reboot", (char *) 0);
                }
            }
        }

        // PID 1 should never exit:
        while (true) {
            pause();
        }
    }

    return 0;
}

// Callback for control socket
static void control_socket_cb(struct ev_loop *loop, ev_io *w, int revents)
{
    // TODO limit the number of active connections. Keep a tally, and disable the
    // control connection listening socket watcher if it gets high, and re-enable
    // it once it falls below the maximum.

    // Accept a connection
    int sockfd = w->fd;

    int newfd = accept4(sockfd, nullptr, nullptr, SOCK_NONBLOCK | SOCK_CLOEXEC);

    if (newfd != -1) {
        try {
            new ControlConn(loop, service_set, newfd);  // will delete itself when it's finished
        }
        catch (std::bad_alloc &bad_alloc_exc) {
            log(LogLevel::ERROR, "Accepting control connection: Out of memory");
            close(newfd);
        }
    }
}

void open_control_socket(struct ev_loop *loop)
{
    if (! control_socket_open) {
        // TODO make this use a per-user address if PID != 1, and make the address
        // overridable from the command line

        const char * saddrname = "/dev/dinitctl";
        struct sockaddr_un name;

        if (am_system_init) {
            unlink(saddrname);
        }

        name.sun_family = AF_UNIX;
        strcpy(name.sun_path, saddrname); // TODO make this safe for long names
        int namelen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(saddrname);

        int sockfd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
        if (sockfd == -1) {
            log(LogLevel::ERROR, "Error creating control socket: ", strerror(errno));
            return;
        }

        if (bind(sockfd, (struct sockaddr *) &name, namelen) == -1) {
            log(LogLevel::ERROR, "Error binding control socket: ", strerror(errno));
            close(sockfd);
            return;
        }

        // No connections can be made until we listen, so it is fine to change the permissions now
        // (and anyway there is no way to atomically create the socket and set permissions):
        if (chmod(saddrname, S_IRUSR | S_IWUSR) == -1) {
            log(LogLevel::ERROR, "Error setting control socket permissions: ", strerror(errno));
            close(sockfd);
            return;
        }

        if (listen(sockfd, 10) == -1) {
            log(LogLevel::ERROR, "Error listening on control socket: ", strerror(errno));
            close(sockfd);
            return;
        }

        control_socket_open = true;
        ev_io_init(&control_socket_io, control_socket_cb, sockfd, EV_READ);
        ev_io_start(loop, &control_socket_io);
    }
}

/* handle SIGINT signal (generated by kernel when ctrl+alt+del pressed) */
static void sigint_reboot_cb(struct ev_loop *loop, ev_signal *w, int revents)
{
    do_reboot = true;
    log_to_console = true;
    service_set->stop_all_services();
}

/* handle SIGQUIT (if we are system init) */
static void sigquit_cb(struct ev_loop *loop, ev_signal *w, int revents)
{
    // This allows remounting the filesystem read-only if the dinit binary has been
    // unlinked. In that case the kernel holds the binary open, so that it can't be
    // properly removed.
    execl("/sbin/shutdown", "/sbin/shutdown", (char *) 0);
    log(LogLevel::ERROR, "Error executing /sbin/shutdown: ", strerror(errno));
}

/* handle SIGTERM - stop all services */
static void sigterm_cb(struct ev_loop *loop, ev_signal *w, int revents)
{
    got_sigterm = true;
    log_to_console = true;
    service_set->stop_all_services();
}
<|endoftext|>


<commit_before>#include <iostream>
using namespace std;
// ROOT
#include <TTree.h>
#include <TFile.h>
#include <TMath.h>
#include <TGraph.h>
using namespace TMath;
// UNIC
#include <UNIC/Units.h>
#include <UNIC/Constants.h>
using namespace UNIC;
// MAD
#include <MAD/GeCrystal.h>
using namespace MAD;
// thin flat infinite plasma sheet
int main(int argc, char** argv)
{
   double dt=1e-7*ns; // large dt causes E to decrease too fast
   double dx=0.1*nm; // large dx may cause asymmetry
   double Ee=10000*volt/cm;

   //double mean=0, sigma=5*um, height=0.05/nm/nm; // Si
   double mean=0, sigma=3*nm, height=8e-8/nm/nm; // Ge
   bool norm;

   GeCrystal ge;
   double epsilon=ge.Epsilon()*epsilon0;
   double Q=Abs(electron_charge);
   //double De=100*cm2/s, Dh=50*cm2/s;

   // initialize arrays
   const int N = 500;
   // p and n are number densities
   double x[2*N+1], p[2*N+1], n[2*N+1], E[2*N+1];
   for (int i=0; i<2*N+1; i++) {
      x[i]=(i-N)*dx;
      p[i]=n[i]=height*Gaus(x[i],mean=0,sigma,norm=kTRUE);
      E[i]=Ee;
   }
   // slopes
   double dp[2*N+1], dn[2*N+1], dE[2*N+1];
   for (int i=1; i<2*N; i++) {
      dp[i] = (p[i+1]-p[i-1])/2;
      dn[i] = (n[i+1]-n[i-1])/2;
      dE[i] = (E[i+1]-E[i-1])/2;
   }
   dp[2*N] = dp[0] = 0;
   dn[2*N] = dn[0] = 0;
   dE[2*N] = dE[0] = 0;
   double d2p[2*N+1], d2n[2*N+1];
   for (int i=1; i<2*N; i++) {
      d2p[i] = (dp[i+1]-dp[i-1])/2;
      d2n[i] = (dn[i+1]-dn[i-1])/2;
   }
   d2p[2*N] = d2p[0] = 0;
   d2n[2*N] = d2n[0] = 0;

   double phi[2*N+1]; // weighting potential
   for (int i=0; i<2*N+1; i++) phi[i]=float(i)/2/N;

   // output
   TFile *output = new TFile("sheet.root","recreate");
   TTree *t = new TTree("t","time slices");
   t->Branch("x",x,Form("x[%d]/D",2*N+1));
   t->Branch("p",p,Form("p[%d]/D",2*N+1));
   t->Branch("n",n,Form("n[%d]/D",2*N+1));
   t->Branch("E",E,Form("E[%d]/D",2*N+1));
   t->Branch("dp",dp,Form("dp[%d]/D",2*N+1));
   t->Branch("dn",dn,Form("dn[%d]/D",2*N+1));
   t->Branch("dE",dE,Form("dE[%d]/D",2*N+1));
   t->Branch("d2p",d2p,Form("d2p[%d]/D",2*N+1));
   t->Branch("d2n",d2n,Form("d2n[%d]/D",2*N+1));
   t->Branch("dx",&dx,"dx/D");
   t->Branch("dt",&dt,"dt/D");
   // save units into tree
   double CM3=cm3, CM=cm, UM=um, V=volt, SEC=s, NS=ns, NM=nm;
   t->Branch("cm3",&CM3,"cm3/D");
   t->Branch("V",&V,"V/D");
   t->Branch("cm",&CM,"cm/D");
   t->Branch("um",&UM,"um/D");
   t->Branch("nm",&NM,"nm/D");
   t->Branch("ns",&NS,"ns/D");
   t->Branch("s",&SEC,"s/D");
   t->Branch("eps",&epsilon,"eps/D");
   t->Branch("q",&Q,"q/D");

   int iStep=0, nSteps = 100;
   double time[1000]={0}, charge[1000]={0};

   // evolve
   if (argc>1) nSteps = atoi(argv[1]);
   //double mu_e=1350*cm2/volt/s; // Si
   //double mu_h=1350*cm2/volt/s; // Si
   double mu_e=40000*cm2/volt/s; // Ge
   double mu_h=40000*cm2/volt/s; // Ge
   t->Branch("mue",&mu_e,"mue/D");
   t->Branch("muh",&mu_h,"muh/D");
   while (iStep<nSteps) {
      t->Fill();
      // update charge
      for (int i=0; i<2*N+1; i++) {
         charge[iStep]+=(p[i]-n[i])*phi[i];
      }
      time[iStep]=iStep*dt;
      // update electron and hole distributions
      for (int i=0; i<2*N+1; i++) {
	      double dn_dt = mu_e*(dn[i]/dx*E[i]+n[i]*dE[i]/dx);
	      double dp_dt =-mu_h*(dp[i]/dx*E[i]+p[i]*dE[i]/dx);
         //dn_dt+=De*d2n[i]/dx/dx;
         //dp_dt+=Dh*d2p[i]/dx/dx;
	      n[i]+=dn_dt*dt;
	      p[i]+=dp_dt*dt;
      }
      // update electric field distribution
      for (int i=0; i<2*N+1; i++) {
         E[i]=0;
         for (int j=0; j<i; j++) E[i]+=p[j]-n[j];
         for (int j=i+1; j<2*N+1; j++) E[i]+=n[j]-p[j];
         E[i]/=(2*epsilon/Q/dx);
         E[i]+=Ee;
         if (E[i]<0) E[i]=0; // large dt may over evolve things
      }
      // update slopes
      for (int i=1; i<2*N; i++) {
         dp[i] = (p[i+1]-p[i-1])/2;
         dn[i] = (n[i+1]-n[i-1])/2;
         dE[i] = (E[i+1]-E[i-1])/2;
      }
      dp[2*N] = dp[0] = 0;
      dn[2*N] = dn[0] = 0;
      dE[2*N] = dE[0] = 0;
      // update second derivative
      for (int i=1; i<2*N; i++) {
         d2p[i] = (dp[i+1]-dp[i-1])/2;
         d2n[i] = (dn[i+1]-dn[i-1])/2;
      }
      d2p[2*N] = d2p[0] = 0;
      d2n[2*N] = d2n[0] = 0;

      iStep++;
   }
   t->Write("t",6);

   TGraph *g = new TGraph(nSteps,time,charge);
   g->Write("g");

   output->Close();

   return 0;
}
<commit_msg>started to mix course and fine grids<commit_after>#include <iostream>
using namespace std;
// ROOT
#include <TTree.h>
#include <TFile.h>
#include <TMath.h>
#include <TGraph.h>
using namespace TMath;
// UNIC
#include <UNIC/Units.h>
#include <UNIC/Constants.h>
using namespace UNIC;
// MAD
#include <MAD/GeCrystal.h>
using namespace MAD;

// parameters
double dx;
double dt=5e-7*ns; // large dt causes E to decrease too fast
double Ee=1000*volt/cm;
double R=1.97e-7*cm, mean=0, sigma=R/3, height=84./(Pi()*R*R);

const int Nmidd = 50; // # of points in (0,5*sigma)
const int Nwing = 95; // # of points in (5*sigma, 100*sigma)
const int Ntotal = 2*(Nmidd + Nwing) + 1;

GeCrystal ge;
double epsilon=ge.Epsilon()*epsilon0;
double Q=Abs(electron_charge);

// df at i
double d(double *f, int i)
{
   if (i<1 || i>Ntotal-1) return 0;
   return (f[i+1]-f[i-1])/2; // 2 points
   //if (i<2 || i>Ntotal-2) return 0;
   //return (-f[i+2]+8*f[i+1]-8*f[i-1]+f[i-2])/12; // 4
   //if (i<4 || i>Ntotal-4) return 0;
   //return (-f[i+4]-8*f[i+2]+128*f[i+1]-128*f[i-1]+8*f[i-2]+f[i-4])/180; // 6
}

// thin flat infinite plasma sheet
int main(int argc, char** argv)
{
   // initialize arrays
   double x[Ntotal], E[Ntotal], p[Ntotal], n[Ntotal], pE[Ntotal], nE[Ntotal];
   for (int i=0; i<=Nwing; i++) { // wings
      dx = sigma;
      x[i]=-100*sigma + i*dx;
      x[Ntotal-1-i]= 100*sigma - i*dx;
      p[i]=n[i]=height*Gaus(x[i],mean=0,sigma,kTRUE);
      p[Ntotal-1-i]=height*Gaus(x[Ntotal-1-i],mean=0,sigma,kTRUE);
      n[Ntotal-1-i]=height*Gaus(x[Ntotal-1-i],mean=0,sigma,kTRUE);
      E[i]=E[Ntotal-1-i]=Ee;
      pE[i]=p[i]*E[i];
      nE[i]=n[i]*E[i];
      pE[Ntotal-1-i]=p[Ntotal-1-i]*E[Ntotal-1-i];
      nE[Ntotal-1-i]=n[Ntotal-1-i]*E[Ntotal-1-i];
   }
   for (int i=Nwing+1; i<Ntotal-Nwing; i++) { // middle
      dx = sigma/10;
      x[i]=x[Nwing] + (i-Nwing)*dx;
      p[i]=n[i]=height*Gaus(x[i],mean=0,sigma,kTRUE);
      E[i]=Ee;
      pE[i]=p[i]*E[i];
      nE[i]=n[i]*E[i];
   }

   // output
   TFile *output = new TFile("sheet.root","recreate");
   TTree *t = new TTree("t","time slices");
   t->Branch("x",x,Form("x[%d]/D",Ntotal));
   t->Branch("p",p,Form("p[%d]/D",Ntotal));
   t->Branch("n",n,Form("n[%d]/D",Ntotal));
   t->Branch("E",E,Form("E[%d]/D",Ntotal));
   t->Branch("dt",&dt,"dt/D");
   // save units into tree
   double V=volt, nanosec=ns, nanometer=nm;
   t->Branch("V",&V,"V/D");
   t->Branch("nm",&nanometer,"nm/D");
   t->Branch("ns",&nanosec,"ns/D");

   // evolve
   int iStep=0, nSteps = 100;
   if (argc>1) nSteps = atoi(argv[1]);
   while (iStep<nSteps) {
      t->Fill();
      for (int i=0; i<Ntotal; i++) {
         if (i==Ntotal-1) dx = x[i]-x[i-1];
         else if (i==Nwing || i==Ntotal-1-Nwing) dx = (x[i+1]-x[i-1])/2;
         else dx = (x[i+1]-x[i]);
         double dn_dt = ge.Mu('e', n[i])*d(nE,i)/dx;
         double dp_dt =-ge.Mu('h', p[i])*d(pE,i)/dx;
         double dE_dt = E[i]*(-ge.Mu('e',n[i])*n[i]-ge.Mu('h',p[i])*p[i])/epsilon/Q;
         n[i]+=dn_dt*dt;
         p[i]+=dp_dt*dt;
         E[i]+=dE_dt*dt;
      }
      iStep++;
   }
   t->Write("t",6);

   output->Close();

   return 0;
}
<|endoftext|>


<commit_before>#include "common/common.h"
#include "common/input_output.h"
#include "common/parser.h"
#include "common/generation.h"
ChVector<> lpos(0, 0, 0);
ChQuaternion<> quat(1, 0, 0, 0);

//all dimensions are in millimeters, milligrams
real container_width = 5;		//width of area with particles
real container_length = 25;		//length of area that roller will go over		1194mm maximum
real container_thickness = .25;     //thickness of container walls
real container_height = 2;		//height of the outer walls
real container_friction = 0;
real floor_friction = .2;
real spacer_width = 1;
real spacer_height = 1;

real roller_overlap = 1; 		//amount that roller goes over the container area
real roller_length = 2.5-.25;			//length of the roller
real roller_radius = 76.2 / 2.0;			//radius of roller
real roller_omega = 0;
real roller_velocity = -127;
real roller_mass = 1;
real roller_friction = .2;
real roller_cohesion = 0;
real particle_radius = .058 / 2.0;
real particle_std_dev = .015 / 2.0;
real particle_mass = .05;
real particle_density = 0.446;
real particle_layer_thickness = particle_radius * 6;
real particle_friction = .1;
real gravity = -9810;			//acceleration due to gravity
real timestep = .00002;			//step size
real time_to_run = 1;			//length of simulation
real current_time = 0;

int num_steps = time_to_run / timestep;
int max_iteration = 15;
int tolerance = 0;

string data_folder = "data/sls";
ChSharedBodyPtr ROLLER;
real ang = 0;

template<class T>
void RunTimeStep(T* mSys, const int frame) {
	ChVector<> roller_pos = ROLLER->GetPos();

	ROLLER->SetPos(ChVector<>(0, roller_radius + particle_layer_thickness + container_thickness, roller_pos.z + roller_velocity * timestep));
	ROLLER->SetPos_dt(ChVector<>(0, 0, roller_velocity));
	roller_omega = roller_velocity / roller_radius;
	ang += roller_omega * timestep;
	if (ang >= 2 * CH_C_PI) {
		ang = 0;
	}

	Quaternion q1;
	q1.Q_from_AngY(ang);
	Quaternion q2;
	q1 = Q_from_AngX(-ang);

	ChQuaternion<> roller_quat;
	roller_quat.Q_from_AngAxis(PI / 2.0, ChVector<>(0, 0, 1));

	ROLLER->SetRot(q1 % roller_quat);
	ROLLER->SetWvel_loc(Vector(0, roller_omega, 0));

}
int main(int argc, char* argv[]) {
	bool visualize = false;
	int threads = 0;

	if (argc > 1) {
		threads = atoi(argv[1]);
		omp_set_num_threads(threads);

		visualize = atoi(argv[2]);
		//visualize
		//distribution_type
		//min_radius
		//max_radius
		//mass
		//friction
		//cohesion
		//layer_thickness
		//roller_velocity
		//roller_omega
		//roller_friction
		//roller_cohesion

	}

	//cout << "Mass, Radius, Friction_Sphere, Friction_Plate, Data Folder, create_particle_plate all_three_kinds, particle configuration" << endl;
	//string solver_string = "ACCELERATED_PROJECTED_GRADIENT_DESCENT";
	//=========================================================================================================
	ChSystemGPU * system_gpu = new ChSystemGPU;
	system_gpu->SetIntegrationType(ChSystem::INT_ANITESCU);

	//=========================================================================================================

	system_gpu->SetMaxiter(max_iteration);
	system_gpu->SetIterLCPmaxItersSpeed(max_iteration);
	((ChLcpSolverGPU *) (system_gpu->GetLcpSolverSpeed()))->SetMaxIteration(max_iteration);
	system_gpu->SetTol(0);
	system_gpu->SetTolSpeeds(0);
	((ChLcpSolverGPU *) (system_gpu->GetLcpSolverSpeed()))->SetTolerance(0);
	((ChLcpSolverGPU *) (system_gpu->GetLcpSolverSpeed()))->SetCompliance(0, 0, 0);
	((ChLcpSolverGPU *) (system_gpu->GetLcpSolverSpeed()))->SetContactRecoverySpeed(300);
	((ChLcpSolverGPU *) (system_gpu->GetLcpSolverSpeed()))->SetSolverType(ACCELERATED_PROJECTED_GRADIENT_DESCENT);
	((ChCollisionSystemGPU *) (system_gpu->GetCollisionSystem()))->SetCollisionEnvelope(particle_radius * .05);
	((ChCollisionSystemGPU *) (system_gpu->GetCollisionSystem()))->setBinsPerAxis(R3(40, 20, 200));
	((ChCollisionSystemGPU *) (system_gpu->GetCollisionSystem()))->setBodyPerBin(100, 50);
	system_gpu->Set_G_acc(ChVector<>(0, gravity, 0));
	system_gpu->SetStep(timestep);

	//=========================================================================================================
	system_gpu->Set_G_acc(ChVector<>(0, gravity, 0));
	system_gpu->SetStep(timestep);
	//=========================================================================================================

	ChSharedBodyPtr PLATE = ChSharedBodyPtr(new ChBody(new ChCollisionModelGPU));
	ChSharedBodyPtr L = ChSharedBodyPtr(new ChBody(new ChCollisionModelGPU));
	ChSharedBodyPtr R = ChSharedBodyPtr(new ChBody(new ChCollisionModelGPU));
	ChSharedBodyPtr F = ChSharedBodyPtr(new ChBody(new ChCollisionModelGPU));
	ChSharedBodyPtr B = ChSharedBodyPtr(new ChBody(new ChCollisionModelGPU));
	ChSharedBodyPtr SPACER_L = ChSharedBodyPtr(new ChBody(new ChCollisionModelGPU));
	ChSharedBodyPtr SPACER_R = ChSharedBodyPtr(new ChBody(new ChCollisionModelGPU));

	ChSharedPtr<ChMaterialSurface> material_plate;
	material_plate = ChSharedPtr<ChMaterialSurface>(new ChMaterialSurface);
	material_plate->SetFriction(floor_friction);

	InitObject(PLATE, 100000, ChVector<>(0, 0, 0), quat, material_plate, true, true, -20, -20);

	ChSharedPtr<ChMaterialSurface> material;
	material = ChSharedPtr<ChMaterialSurface>(new ChMaterialSurface);
	material->SetFriction(container_friction);

	//InitObject(L, 100000, Vector(-container_width + container_thickness, container_height, 0), quat, material, true, true, -20, -20);
	//InitObject(R, 100000, Vector(container_width - container_thickness, container_height, 0), quat, material, true, true, -20, -20);
	//InitObject(F, 100000, Vector(0, container_height, -container_length + container_thickness), quat, material, true, true, -20, -20);
	//InitObject(B, 100000, Vector(0, container_height, container_length - container_thickness), quat, material, true, true, -20, -20);
	//InitObject(SPACER_L, 100000, Vector(-container_width + container_thickness * 2 + spacer_width, container_thickness + spacer_height, 0), quat, material, true, true, -20, -20);
	//InitObject(SPACER_R, 100000, Vector(container_width - container_thickness * 2 - spacer_width, container_thickness + spacer_height, 0), quat, material, true, true, -20, -20);

	AddCollisionGeometry(PLATE, BOX, ChVector<>(container_width, container_thickness, container_length), lpos, quat);
	AddCollisionGeometry(PLATE, BOX, Vector(container_thickness, container_height, container_length), Vector(-container_width + container_thickness, container_height, 0), quat);
	AddCollisionGeometry(PLATE, BOX, Vector(container_thickness, container_height, container_length),  Vector(container_width - container_thickness, container_height, 0), quat);
	AddCollisionGeometry(PLATE, BOX, Vector(container_width, container_height, container_thickness), Vector(0, container_height, -container_length + container_thickness), quat);
	AddCollisionGeometry(PLATE, BOX, Vector(container_width, container_height, container_thickness), Vector(0, container_height, container_length - container_thickness), quat);
	//AddCollisionGeometry(SPACER_L, BOX, Vector(spacer_width, spacer_height, container_length), lpos, quat);
	//AddCollisionGeometry(SPACER_R, BOX, Vector(spacer_width, spacer_height, container_length), lpos, quat);

	FinalizeObject(PLATE, (ChSystemGPU *) system_gpu);
	//FinalizeObject(L, (ChSystemGPU *) system_gpu);
	//FinalizeObject(R, (ChSystemGPU *) system_gpu);
	//FinalizeObject(F, (ChSystemGPU *) system_gpu);
	//FinalizeObject(B, (ChSystemGPU *) system_gpu);
	//FinalizeObject(SPACER_L, (ChSystemGPU *) system_gpu);
	//FinalizeObject(SPACER_R, (ChSystemGPU *) system_gpu);

	ROLLER = ChSharedBodyPtr(new ChBody(new ChCollisionModelGPU));
	ChQuaternion<> roller_quat;
	roller_quat.Q_from_AngAxis(PI / 2.0, ChVector<>(0, 0, 1));

	ChSharedPtr<ChMaterialSurface> material_roller;
	material_roller = ChSharedPtr<ChMaterialSurface>(new ChMaterialSurface);
	material_roller->SetFriction(roller_friction);

	InitObject(ROLLER, 1000, ChVector<>(0, roller_radius + particle_layer_thickness + container_thickness, container_length + roller_radius/3.0), roller_quat, material_roller, true, false, -20, -20);
	AddCollisionGeometry(ROLLER, CYLINDER, ChVector<>(roller_radius, roller_length * 2, roller_radius), lpos, quat);
	FinalizeObject(ROLLER, (ChSystemGPU *) system_gpu);
	//68
	int3 num_per_dir = I3(68 * 2, 6, 540 * 2);
	//num_per_dir = I3(1, 8, 440);
	num_per_dir = I3(74, 8,440);
	ParticleGenerator layer_gen(system_gpu);
	layer_gen.SetDensity(particle_density);
	layer_gen.SetRadius(R3(particle_radius));
	layer_gen.SetNormalDistribution(particle_radius, particle_std_dev);
	layer_gen.material->SetFriction(particle_friction);
	layer_gen.addPerturbedVolume(R3(0, .7, 0), SPHERE, num_per_dir, R3(.1, .1, .1), R3(0));
	num_per_dir = I3(74, 30, 50);
	//num_per_dir = I3(1, 30, 50);
	layer_gen.addPerturbedVolume(R3(0, 2.8, 15), SPHERE, num_per_dir, R3(.1, .1, .1), R3(0));

	//=========================================================================================================
	//////Rendering specific stuff:
	if (visualize) {
		ChOpenGLManager * window_manager = new ChOpenGLManager();
		ChOpenGL openGLView(window_manager, system_gpu, 800, 600, 0, 0, "Test_Solvers");
		openGLView.render_camera->camera_pos = Vector(-50, 0, -50);
		openGLView.render_camera->look_at = Vector(0, 0, 0);
		openGLView.SetCustomCallback(RunTimeStep);
		openGLView.StartSpinning(window_manager);
		window_manager->CallGlutMainLoop();
	}
	//=========================================================================================================
	stringstream ss_m;
	ss_m << data_folder << "/" << "timing.txt";
	string timing_file_name = ss_m.str();
	ofstream ofile(timing_file_name.c_str());
	ofile.close();
	int file = 0;
	for (int i = 0; i < num_steps; i++) {
		cout << "step " << i;
		cout << " Residual: " << ((ChLcpSolverGPU *) (system_gpu->GetLcpSolverSpeed()))->GetResidual();
		cout << " ITER: " << ((ChLcpSolverGPU *) (system_gpu->GetLcpSolverSpeed()))->GetTotalIterations();
		cout << " OUTPUT STEP: Time= " << current_time << " bodies= " << system_gpu->GetNbodies() << " contacts= " << system_gpu->GetNcontacts() << " step time=" << system_gpu->GetTimerStep()
				<< " lcp time=" << system_gpu->GetTimerLcp() << " CDbroad time=" << system_gpu->GetTimerCollisionBroad() << " CDnarrow time=" << system_gpu->GetTimerCollisionNarrow() << " Iterations="
				<< ((ChLcpSolverGPU*) (system_gpu->GetLcpSolverSpeed()))->GetTotalIterations() << "\n";
		//TimingFile(system_gpu, timing_file_name, current_time);
		system_gpu->DoStepDynamics(timestep);
		RunTimeStep(system_gpu, i);
		int save_every = 1.0 / timestep / 6000.0;     //save data every n steps
		if (i % save_every == 0) {
			stringstream ss;
			cout << "Frame: " << file << endl;
			ss << data_folder << "/" << file << ".txt";
			DumpAllObjectsWithGeometryPovray(system_gpu, ss.str());
			//output.ExportData(ss.str());
			file++;
		}
		current_time += timestep;
	}
	stringstream ss;
	//ss << data_folder << "/" << particle_friction << "_" << plate_friction << "_" << create_particle_plate << ".txt";

	//DumpAllObjectsWithGeometry(system_gpu, ss.str());
	return 0;
}

<commit_msg>Added AABB inactive pruning to help with instability<commit_after>#include "common/common.h"
#include "common/input_output.h"
#include "common/parser.h"
#include "common/generation.h"
ChVector<> lpos(0, 0, 0);
ChQuaternion<> quat(1, 0, 0, 0);

//all dimensions are in millimeters, milligrams
real container_width = 5;		//width of area with particles
real container_length = 25;		//length of area that roller will go over		1194mm maximum
real container_thickness = .25;     //thickness of container walls
real container_height = 2;		//height of the outer walls
real container_friction = 0;
real floor_friction = .2;
real spacer_width = 1;
real spacer_height = 1;

real roller_overlap = 1; 		//amount that roller goes over the container area
real roller_length = 2.5-.25;			//length of the roller
real roller_radius = 76.2 / 2.0;			//radius of roller
real roller_omega = 0;
real roller_velocity = -127;
real roller_mass = 1;
real roller_friction = .2;
real roller_cohesion = 0;
real particle_radius = .058 / 2.0;
real particle_std_dev = .015 / 2.0;
real particle_mass = .05;
real particle_density = 0.446;
real particle_layer_thickness = particle_radius * 6;
real particle_friction = .1;
real gravity = -9810;			//acceleration due to gravity
real timestep = .00001;			//step size
real time_to_run = 1;			//length of simulation
real current_time = 0;

int num_steps = time_to_run / timestep;
int max_iteration = 15;
int tolerance = 0;

string data_folder = "data/sls";
ChSharedBodyPtr ROLLER;
real ang = 0;

template<class T>
void RunTimeStep(T* mSys, const int frame) {
	ChVector<> roller_pos = ROLLER->GetPos();

	ROLLER->SetPos(ChVector<>(0, roller_radius + particle_layer_thickness + container_thickness, roller_pos.z + roller_velocity * timestep));
	ROLLER->SetPos_dt(ChVector<>(0, 0, roller_velocity));
	roller_omega = roller_velocity / roller_radius;
	ang += roller_omega * timestep;
	if (ang >= 2 * CH_C_PI) {
		ang = 0;
	}

	Quaternion q1;
	q1.Q_from_AngY(ang);
	Quaternion q2;
	q1 = Q_from_AngX(-ang);

	ChQuaternion<> roller_quat;
	roller_quat.Q_from_AngAxis(PI / 2.0, ChVector<>(0, 0, 1));

	ROLLER->SetRot(q1 % roller_quat);
	ROLLER->SetWvel_loc(Vector(0, roller_omega, 0));

}
int main(int argc, char* argv[]) {
	bool visualize = false;
	int threads = 0;

	if (argc > 1) {
		threads = atoi(argv[1]);
		omp_set_num_threads(threads);

		visualize = atoi(argv[2]);
		//visualize
		//distribution_type
		//min_radius
		//max_radius
		//mass
		//friction
		//cohesion
		//layer_thickness
		//roller_velocity
		//roller_omega
		//roller_friction
		//roller_cohesion

	}

	//cout << "Mass, Radius, Friction_Sphere, Friction_Plate, Data Folder, create_particle_plate all_three_kinds, particle configuration" << endl;
	//string solver_string = "ACCELERATED_PROJECTED_GRADIENT_DESCENT";
	//=========================================================================================================
	ChSystemGPU * system_gpu = new ChSystemGPU;
	system_gpu->SetIntegrationType(ChSystem::INT_ANITESCU);

	//=========================================================================================================

	system_gpu->SetMaxiter(max_iteration);
	system_gpu->SetIterLCPmaxItersSpeed(max_iteration);
	((ChLcpSolverGPU *) (system_gpu->GetLcpSolverSpeed()))->SetMaxIteration(max_iteration);
	system_gpu->SetTol(0);
	system_gpu->SetTolSpeeds(0);
	((ChLcpSolverGPU *) (system_gpu->GetLcpSolverSpeed()))->SetTolerance(0);
	((ChLcpSolverGPU *) (system_gpu->GetLcpSolverSpeed()))->SetCompliance(0, 0, 0);
	((ChLcpSolverGPU *) (system_gpu->GetLcpSolverSpeed()))->SetContactRecoverySpeed(300);
	((ChLcpSolverGPU *) (system_gpu->GetLcpSolverSpeed()))->SetSolverType(ACCELERATED_PROJECTED_GRADIENT_DESCENT);
	((ChCollisionSystemGPU *) (system_gpu->GetCollisionSystem()))->SetCollisionEnvelope(particle_radius * .05);
	((ChCollisionSystemGPU *) (system_gpu->GetCollisionSystem()))->setBinsPerAxis(R3(40, 20, 200));
	((ChCollisionSystemGPU *) (system_gpu->GetCollisionSystem()))->setBodyPerBin(100, 50);
	system_gpu->Set_G_acc(ChVector<>(0, gravity, 0));
	system_gpu->SetStep(timestep);

	//=========================================================================================================
	system_gpu->Set_G_acc(ChVector<>(0, gravity, 0));
	system_gpu->SetStep(timestep);
	//=========================================================================================================
	 ((ChSystemGPU*) system_gpu)->SetAABB(R3(-6,-3,-30), R3(6,5,30));

	ChSharedBodyPtr PLATE = ChSharedBodyPtr(new ChBody(new ChCollisionModelGPU));
	ChSharedBodyPtr L = ChSharedBodyPtr(new ChBody(new ChCollisionModelGPU));
	ChSharedBodyPtr R = ChSharedBodyPtr(new ChBody(new ChCollisionModelGPU));
	ChSharedBodyPtr F = ChSharedBodyPtr(new ChBody(new ChCollisionModelGPU));
	ChSharedBodyPtr B = ChSharedBodyPtr(new ChBody(new ChCollisionModelGPU));
	ChSharedBodyPtr SPACER_L = ChSharedBodyPtr(new ChBody(new ChCollisionModelGPU));
	ChSharedBodyPtr SPACER_R = ChSharedBodyPtr(new ChBody(new ChCollisionModelGPU));

	ChSharedPtr<ChMaterialSurface> material_plate;
	material_plate = ChSharedPtr<ChMaterialSurface>(new ChMaterialSurface);
	material_plate->SetFriction(floor_friction);

	InitObject(PLATE, 100000, ChVector<>(0, 0, 0), quat, material_plate, true, true, -20, -20);

	ChSharedPtr<ChMaterialSurface> material;
	material = ChSharedPtr<ChMaterialSurface>(new ChMaterialSurface);
	material->SetFriction(container_friction);

	//InitObject(L, 100000, Vector(-container_width + container_thickness, container_height, 0), quat, material, true, true, -20, -20);
	//InitObject(R, 100000, Vector(container_width - container_thickness, container_height, 0), quat, material, true, true, -20, -20);
	//InitObject(F, 100000, Vector(0, container_height, -container_length + container_thickness), quat, material, true, true, -20, -20);
	//InitObject(B, 100000, Vector(0, container_height, container_length - container_thickness), quat, material, true, true, -20, -20);
	//InitObject(SPACER_L, 100000, Vector(-container_width + container_thickness * 2 + spacer_width, container_thickness + spacer_height, 0), quat, material, true, true, -20, -20);
	//InitObject(SPACER_R, 100000, Vector(container_width - container_thickness * 2 - spacer_width, container_thickness + spacer_height, 0), quat, material, true, true, -20, -20);

	AddCollisionGeometry(PLATE, BOX, ChVector<>(container_width, container_thickness, container_length), lpos, quat);
	AddCollisionGeometry(PLATE, BOX, Vector(container_thickness, container_height, container_length), Vector(-container_width + container_thickness, container_height, 0), quat);
	AddCollisionGeometry(PLATE, BOX, Vector(container_thickness, container_height, container_length),  Vector(container_width - container_thickness, container_height, 0), quat);
	AddCollisionGeometry(PLATE, BOX, Vector(container_width, container_height, container_thickness), Vector(0, container_height, -container_length + container_thickness), quat);
	AddCollisionGeometry(PLATE, BOX, Vector(container_width, container_height, container_thickness), Vector(0, container_height, container_length - container_thickness), quat);
	//AddCollisionGeometry(SPACER_L, BOX, Vector(spacer_width, spacer_height, container_length), lpos, quat);
	//AddCollisionGeometry(SPACER_R, BOX, Vector(spacer_width, spacer_height, container_length), lpos, quat);

	FinalizeObject(PLATE, (ChSystemGPU *) system_gpu);
	//FinalizeObject(L, (ChSystemGPU *) system_gpu);
	//FinalizeObject(R, (ChSystemGPU *) system_gpu);
	//FinalizeObject(F, (ChSystemGPU *) system_gpu);
	//FinalizeObject(B, (ChSystemGPU *) system_gpu);
	//FinalizeObject(SPACER_L, (ChSystemGPU *) system_gpu);
	//FinalizeObject(SPACER_R, (ChSystemGPU *) system_gpu);

	ROLLER = ChSharedBodyPtr(new ChBody(new ChCollisionModelGPU));
	ChQuaternion<> roller_quat;
	roller_quat.Q_from_AngAxis(PI / 2.0, ChVector<>(0, 0, 1));

	ChSharedPtr<ChMaterialSurface> material_roller;
	material_roller = ChSharedPtr<ChMaterialSurface>(new ChMaterialSurface);
	material_roller->SetFriction(roller_friction);

	InitObject(ROLLER, 1000, ChVector<>(0, roller_radius + particle_layer_thickness + container_thickness, container_length + roller_radius/3.0), roller_quat, material_roller, true, false, -20, -20);
	AddCollisionGeometry(ROLLER, CYLINDER, ChVector<>(roller_radius, roller_length * 2, roller_radius), lpos, quat);
	FinalizeObject(ROLLER, (ChSystemGPU *) system_gpu);
	//68
	int3 num_per_dir = I3(68 * 2, 6, 540 * 2);
	//num_per_dir = I3(1, 8, 440);
	num_per_dir = I3(74, 8,440);
	ParticleGenerator layer_gen(system_gpu);
	layer_gen.SetDensity(particle_density);
	layer_gen.SetRadius(R3(particle_radius));
	layer_gen.SetNormalDistribution(particle_radius, particle_std_dev);
	layer_gen.material->SetFriction(particle_friction);
	layer_gen.addPerturbedVolume(R3(0, .7, 0), SPHERE, num_per_dir, R3(.1, .1, .1), R3(0));
	num_per_dir = I3(74, 30, 50);
	//num_per_dir = I3(1, 30, 50);
	layer_gen.addPerturbedVolume(R3(0, 2.8, 15), SPHERE, num_per_dir, R3(.1, .1, .1), R3(0));

	//=========================================================================================================
	//////Rendering specific stuff:
	if (visualize) {
		ChOpenGLManager * window_manager = new ChOpenGLManager();
		ChOpenGL openGLView(window_manager, system_gpu, 800, 600, 0, 0, "Test_Solvers");
		openGLView.render_camera->camera_pos = Vector(-50, 0, -50);
		openGLView.render_camera->look_at = Vector(0, 0, 0);
		openGLView.SetCustomCallback(RunTimeStep);
		openGLView.StartSpinning(window_manager);
		window_manager->CallGlutMainLoop();
	}
	//=========================================================================================================
	stringstream ss_m;
	ss_m << data_folder << "/" << "timing.txt";
	string timing_file_name = ss_m.str();
	ofstream ofile(timing_file_name.c_str());
	ofile.close();
	int file = 0;
	for (int i = 0; i < num_steps; i++) {
		cout << "step " << i;
		cout << " Residual: " << ((ChLcpSolverGPU *) (system_gpu->GetLcpSolverSpeed()))->GetResidual();
		cout << " ITER: " << ((ChLcpSolverGPU *) (system_gpu->GetLcpSolverSpeed()))->GetTotalIterations();
		cout << " OUTPUT STEP: Time= " << current_time << " bodies= " << system_gpu->GetNbodies() << " contacts= " << system_gpu->GetNcontacts() << " step time=" << system_gpu->GetTimerStep()
				<< " lcp time=" << system_gpu->GetTimerLcp() << " CDbroad time=" << system_gpu->GetTimerCollisionBroad() << " CDnarrow time=" << system_gpu->GetTimerCollisionNarrow() << " Iterations="
				<< ((ChLcpSolverGPU*) (system_gpu->GetLcpSolverSpeed()))->GetTotalIterations() << "\n";
		//TimingFile(system_gpu, timing_file_name, current_time);
		system_gpu->DoStepDynamics(timestep);
		RunTimeStep(system_gpu, i);
		int save_every = 1.0 / timestep / 6000.0;     //save data every n steps
		if (i % save_every == 0) {
			stringstream ss;
			cout << "Frame: " << file << endl;
			ss << data_folder << "/" << file << ".txt";
			DumpAllObjectsWithGeometryPovray(system_gpu, ss.str());
			//output.ExportData(ss.str());
			file++;
		}
		current_time += timestep;
	}
	stringstream ss;
	//ss << data_folder << "/" << particle_friction << "_" << plate_friction << "_" << create_particle_plate << ".txt";

	//DumpAllObjectsWithGeometry(system_gpu, ss.str());
	return 0;
}

<|endoftext|>


<commit_before>#pragma once

#include <string>
#include <tuple>
#include <optional>
#include <variant>
#include <functional>
#include <string_view>
#include <vector>
#include <ostream>
#include <iostream>

namespace apc
{
    using namespace std;

    namespace res
    {
        struct NilOk {};

        struct Error
        {
            virtual std::string description(size_t offset) = 0;
            virtual Error& previous() = 0;
            virtual bool is_nil()
            {
                return false;
            }

            void print_trace(std::ostream& out = std::cerr)
            {
                out << description(0) << std::endl;
            }
        };

        struct NilErr : Error
        {
            virtual string description(size_t offset = 0) override
            {
                return "NilErr";
            }

            virtual Error& previous() override
            {
                static NilErr global;

                return global;
            }

            virtual bool is_nil() override
            {
                return true;
            }
        };

        struct EOI
        {
            vector<string> trace;

            EOI() : trace() {}
            EOI(string&& s) : trace{s} {}
            EOI(string& s) : trace{s} {}

            void print_trace(ostream& out = cerr) const
            {
                out << "End of input" << endl;

                for (auto iter = trace.crbegin(); iter != trace.crend(); iter++)
                {
                    out << "\tIn " << *iter << endl;
                }
            }
        };

        template< typename T, typename I >
        struct Ok
        {
            T res;
            I pos;

            Ok(T res, I pos) : res(move(res)), pos(move(pos)) {}
        };

        template< typename E, typename I >
        struct Err
        {
            E err;
            I pos;

            Err(E err, I pos) : err(move(err)), pos(move(pos)) {}
        };

        template< typename T, typename I >
        Ok<T, I> ok(T t, I i)
        {
            return Ok<T, I>(move(t), move(i));
        }

        template< typename E, typename I >
        Err<E, I> err(E e, I i)
        {
            return Err<E, I>(move(e), move(i));
        }

        template< typename T, typename E, typename I >
        using Result = variant<Ok<T, I>, Err<E, I>, EOI>;

        template< typename T, typename E, typename I >
        bool is_ok(const Result<T, E, I>& res)
        {
            return holds_alternative<Ok<T, I>>(res);
        }

        template< typename T, typename E, typename I >
        bool is_err(const Result<T, E, I>& res)
        {
            return holds_alternative<Err<E, I>>(res);
        }

        template< typename T, typename E, typename I >
        bool is_eoi(const Result<T, E, I>& res)
        {
            return holds_alternative<EOI>(res);
        }

        template< typename T, typename E, typename I >
        Ok<T, I>& unwrap_ok(Result<T, E, I>& res)
        {
            return get<Ok<T, I>>(res);
        }

        template< typename T, typename E, typename I >
        Ok<T, I> unwrap_ok(Result<T, E, I>&& res)
        {
            return get<Ok<T, I>>(move(res));
        }

        template< typename T, typename E, typename I >
        const Ok<T, I>& unwrap_ok(const Result<T, E, I>& res)
        {
            return get<Ok<T, I>>(res);
        }

        template< typename T, typename E, typename I >
        Err<E, I>& unwrap_err(Result<T, E, I>& res)
        {
            return get<Err<E, I>>(res);
        }

        template< typename T, typename E, typename I >
        Err<E, I> unwrap_err(Result<T, E, I>&& res)
        {
            return get<Err<E, I>>(move(res));
        }

        template< typename T, typename E, typename I >
        const Err<E, I>& unwrap_err(const Result<T, E, I>& res)
        {
            return get<Err<E, I>>(res);
        }

        template< typename T, typename E, typename I >
        EOI& unwrap_eoi(Result<T, E, I>& res)
        {
            return get<EOI>(res);
        }

        template< typename T, typename E, typename I >
        EOI unwrap_eoi(Result<T, E, I>&& res)
        {
            return get<EOI>(move(res));
        }

        template< typename T, typename E, typename I >
        const EOI& unwrap_eoi(const Result<T, E, I>& res)
        {
            return get<EOI>(res);
        }

        template< typename T, typename E, typename I,
                  typename MOK, typename MERR, typename MEOI >
        void match (Result<T, E, I> res,
                    MOK match_ok,
                    MERR match_err,
                    MEOI match_eoi
            )
        {

            if (is_ok(res))
            {
                match_ok(unwrap_ok(move(res)));
            }
            else if (is_err(res))
            {
                match_err(unwrap_err(move(res)));
            }
            else
            {
                match_eoi(unwrap_eoi(move(res)));
            }
        }

        template< typename T, typename T1, typename E, typename E1, typename I,
                  typename MOK, typename MERR, typename MEOI >
        Result<T1, E1, I> match (Result<T, E, I> res,
                                 MOK match_ok,
                                 MERR match_err,
                                 MEOI match_eoi
            )
        {

            if (is_ok(res))
            {
                return match_ok(unwrap_ok(move(res)));
            }
            else if (is_err(res))
            {
                return match_err(unwrap_err(move(res)));
            }
            else
            {
                return match_eoi(unwrap_eoi(move(res)));
            }
        }
    }
}
<commit_msg>NilErr not returns itself instead of a static<commit_after>#pragma once

#include <string>
#include <tuple>
#include <optional>
#include <variant>
#include <functional>
#include <string_view>
#include <vector>
#include <ostream>
#include <iostream>

namespace apc
{
    using namespace std;

    namespace res
    {
        struct NilOk {};

        struct Error
        {
            virtual std::string description(size_t offset) = 0;
            virtual Error& previous() = 0;
            virtual bool is_nil()
            {
                return false;
            }

            void print_trace(std::ostream& out = std::cerr)
            {
                out << description(0) << std::endl;
            }
        };

        struct NilErr : Error
        {
            virtual string description(size_t offset = 0) override
            {
                return "NilErr";
            }

            virtual Error& previous() override
            {
                return *this;
            }

            virtual bool is_nil() override
            {
                return true;
            }
        };

        struct EOI
        {
            vector<string> trace;

            EOI() : trace() {}
            EOI(string&& s) : trace{s} {}
            EOI(string& s) : trace{s} {}

            void print_trace(ostream& out = cerr) const
            {
                out << "End of input" << endl;

                for (auto iter = trace.crbegin(); iter != trace.crend(); iter++)
                {
                    out << "\tIn " << *iter << endl;
                }
            }
        };

        template< typename T, typename I >
        struct Ok
        {
            T res;
            I pos;

            Ok(T res, I pos) : res(move(res)), pos(move(pos)) {}
        };

        template< typename E, typename I >
        struct Err
        {
            E err;
            I pos;

            Err(E err, I pos) : err(move(err)), pos(move(pos)) {}
        };

        template< typename T, typename I >
        Ok<T, I> ok(T t, I i)
        {
            return Ok<T, I>(move(t), move(i));
        }

        template< typename E, typename I >
        Err<E, I> err(E e, I i)
        {
            return Err<E, I>(move(e), move(i));
        }

        template< typename T, typename E, typename I >
        using Result = variant<Ok<T, I>, Err<E, I>, EOI>;

        template< typename T, typename E, typename I >
        bool is_ok(const Result<T, E, I>& res)
        {
            return holds_alternative<Ok<T, I>>(res);
        }

        template< typename T, typename E, typename I >
        bool is_err(const Result<T, E, I>& res)
        {
            return holds_alternative<Err<E, I>>(res);
        }

        template< typename T, typename E, typename I >
        bool is_eoi(const Result<T, E, I>& res)
        {
            return holds_alternative<EOI>(res);
        }

        template< typename T, typename E, typename I >
        Ok<T, I>& unwrap_ok(Result<T, E, I>& res)
        {
            return get<Ok<T, I>>(res);
        }

        template< typename T, typename E, typename I >
        Ok<T, I> unwrap_ok(Result<T, E, I>&& res)
        {
            return get<Ok<T, I>>(move(res));
        }

        template< typename T, typename E, typename I >
        const Ok<T, I>& unwrap_ok(const Result<T, E, I>& res)
        {
            return get<Ok<T, I>>(res);
        }

        template< typename T, typename E, typename I >
        Err<E, I>& unwrap_err(Result<T, E, I>& res)
        {
            return get<Err<E, I>>(res);
        }

        template< typename T, typename E, typename I >
        Err<E, I> unwrap_err(Result<T, E, I>&& res)
        {
            return get<Err<E, I>>(move(res));
        }

        template< typename T, typename E, typename I >
        const Err<E, I>& unwrap_err(const Result<T, E, I>& res)
        {
            return get<Err<E, I>>(res);
        }

        template< typename T, typename E, typename I >
        EOI& unwrap_eoi(Result<T, E, I>& res)
        {
            return get<EOI>(res);
        }

        template< typename T, typename E, typename I >
        EOI unwrap_eoi(Result<T, E, I>&& res)
        {
            return get<EOI>(move(res));
        }

        template< typename T, typename E, typename I >
        const EOI& unwrap_eoi(const Result<T, E, I>& res)
        {
            return get<EOI>(res);
        }

        template< typename T, typename E, typename I,
                  typename MOK, typename MERR, typename MEOI >
        void match (Result<T, E, I> res,
                    MOK match_ok,
                    MERR match_err,
                    MEOI match_eoi
            )
        {

            if (is_ok(res))
            {
                match_ok(unwrap_ok(move(res)));
            }
            else if (is_err(res))
            {
                match_err(unwrap_err(move(res)));
            }
            else
            {
                match_eoi(unwrap_eoi(move(res)));
            }
        }

        template< typename T, typename T1, typename E, typename E1, typename I,
                  typename MOK, typename MERR, typename MEOI >
        Result<T1, E1, I> match (Result<T, E, I> res,
                                 MOK match_ok,
                                 MERR match_err,
                                 MEOI match_eoi
            )
        {

            if (is_ok(res))
            {
                return match_ok(unwrap_ok(move(res)));
            }
            else if (is_err(res))
            {
                return match_err(unwrap_err(move(res)));
            }
            else
            {
                return match_eoi(unwrap_eoi(move(res)));
            }
        }
    }
}
<|endoftext|>


<commit_before>#include <iostream>
using namespace std;
// ROOT
#include <TTree.h>
#include <TFile.h>
#include <TMath.h>
using namespace TMath;
// UNIC
#include <UNIC/Units.h>
#include <UNIC/Constants.h>
using namespace UNIC;
#include <MAD/GeCrystal.h>
using namespace MAD;
// infinite thin flat plasma sheet
int main(int argc, char** argv)
{
   double dt=0.1;//ns
   double dx=1;//nm
   double Ee=100;//volt/cm

   double mean=0, sigma=100,/*nm*/ height=1e22;//1/nm2
   bool norm;

   double epsilon=16.2*8.854187817620e-14;//C/V/cm
   double Q=1.60217657e-19;//C

   // initialize arrays
   const int N = 100;
   // p and n are number densities
   double x[2*N+1], p[2*N+1], n[2*N+1], E[2*N+1];
   for (int i=0; i<2*N+1; i++) {
      x[i]=(i-N)*dx;
      p[i]=n[i]=height*Gaus(x[i],mean=0,sigma,norm=kTRUE);
      E[i]=Ee;
   }
   double dp[2*N+1], dn[2*N+1], dE[2*N+1];
   for (int i=0; i<2*N; i++) {
      dp[i] = p[i+1]-p[i];
      dn[i] = n[i+1]-n[i];
      dE[i] = E[i+1]-E[i];
   }
   dp[2*N] = p[2*N]-p[2*N-1];
   dn[2*N] = n[2*N]-n[2*N-1];
   dE[2*N] = E[2*N]-E[2*N-1];

   // output
   TFile *output = new TFile("sheet.root","recreate");
   TTree *t = new TTree("t","time slices");
   t->Branch("x",x,Form("x[%d]/D",2*N+1));
   t->Branch("p",p,Form("p[%d]/D",2*N+1));
   t->Branch("n",n,Form("n[%d]/D",2*N+1));
   t->Branch("E",E,Form("E[%d]/D",2*N+1));
   t->Branch("dp",dp,Form("dp[%d]/D",2*N+1));
   t->Branch("dn",dn,Form("dn[%d]/D",2*N+1));
   t->Branch("dE",dE,Form("dE[%d]/D",2*N+1));

   // evolve
   int iStep=0, nSteps = 100;
   if (argc>1) nSteps = atoi(argv[1]);
   while (iStep<nSteps) {
      t->Fill();
      // update electron and hole distributions
      for (int i=0; i<2*N+1; i++) {
         double mu_e = 1;//cm2/(Vs)
	      double mu_h = 1;//cm2/(Vs)
	      double dn_dt = mu_e*(dn[i]/dx*E[i]+n[i]*dE[i]/dx);
	      double dp_dt = -mu_h*(dp[i]/dx*E[i]+p[i]*dE[i]/dx);
	      n[i]+=dn_dt*dt;
	      p[i]+=dp_dt*dt;
      }
      // update electric field distribution
      for (int i=0; i<2*N+1; i++) {
         E[i]=0;
         for (int j=0; j<i; j++) E[i]+=p[j]-n[j];
         for (int j=i+1; j<2*N+1; j++) E[i]+=n[j]-p[j];
         E[i]/=(2*epsilon/Q/dx/1e-7);
         E[i]+=Ee;
      }
      // update slopes
      for (int i=0; i<2*N; i++) {
         dp[i] = p[i+1]-p[i];
         dn[i] = n[i+1]-n[i];
         dE[i] = E[i+1]-E[i];
      }
      dp[2*N] = p[2*N]-p[2*N-1];
      dn[2*N] = n[2*N]-n[2*N-1];
      dE[2*N] = E[2*N]-E[2*N-1];
      iStep++;
   }
   t->Write("t",6);
   output->Close();

   return 0;
}

<commit_msg>introduced diffusion and mobility calculated regarding plasma zone as metal<commit_after>#include <iostream>
using namespace std;
// ROOT
#include <TTree.h>
#include <TFile.h>
#include <TMath.h>
using namespace TMath;
// UNIC
#include <UNIC/Units.h>
#include <UNIC/Constants.h>
using namespace UNIC;
// MAD
#include <MAD/GeCrystal.h>
using namespace MAD;
// thin flat infinite plasma sheet
int main(int argc, char** argv)
{
   double dt=1e-1;//ns
   double dx=1;//nm
   double Ee=100;//volt/cm

   double mean=0, sigma=10,/*nm*/ height=25;//1/nm2
   bool norm;

   double epsilon=16.2*8.854187817620e-14;//C/V/cm
   double Q=1.60217657e-19;//C
   double De=100, Dh=50;//cm2/s

   // initialize arrays
   const int N = 100;
   // p and n are number densities
   double x[2*N+1], p[2*N+1], n[2*N+1], E[2*N+1];
   for (int i=0; i<2*N+1; i++) {
      x[i]=(i-N)*dx;
      p[i]=n[i]=height*Gaus(x[i],mean=0,sigma,norm=kTRUE); //1/nm3
      E[i]=Ee;
   }
   double dp[2*N+1], dn[2*N+1], dE[2*N+1];
   for (int i=0; i<2*N; i++) {
      dp[i] = p[i+1]-p[i];
      dn[i] = n[i+1]-n[i];
      dE[i] = E[i+1]-E[i];
   }
   dp[2*N] = p[2*N]-p[2*N-1];
   dn[2*N] = n[2*N]-n[2*N-1];
   dE[2*N] = E[2*N]-E[2*N-1];
   double d2p[2*N+1], d2n[2*N+1];
   for (int i=0; i<2*N; i++) {
      d2p[i] = dp[i+1]-dp[i];
      d2n[i] = dn[i+1]-dn[i];
   }
   d2p[2*N] = dp[2*N]-dp[2*N-1];
   d2n[2*N] = dn[2*N]-dn[2*N-1];

   // output
   TFile *output = new TFile("sheet.root","recreate");
   TTree *t = new TTree("t","time slices");
   t->Branch("x",x,Form("x[%d]/D",2*N+1));
   t->Branch("p",p,Form("p[%d]/D",2*N+1));
   t->Branch("n",n,Form("n[%d]/D",2*N+1));
   t->Branch("E",E,Form("E[%d]/D",2*N+1));
   t->Branch("dp",dp,Form("dp[%d]/D",2*N+1));
   t->Branch("dn",dn,Form("dn[%d]/D",2*N+1));
   t->Branch("dE",dE,Form("dE[%d]/D",2*N+1));
   t->Branch("d2p",d2p,Form("d2p[%d]/D",2*N+1));
   t->Branch("d2n",d2n,Form("d2n[%d]/D",2*N+1));

   // evolve
   int iStep=0, nSteps = 100;
   if (argc>1) nSteps = atoi(argv[1]);
   double mu_e=40000;
   double mu_h=40000;
   while (iStep<nSteps) {
      t->Fill();
      // update electron and hole distributions
      for (int i=0; i<2*N+1; i++) {
         if (n[i]>1e-3)
            mu_e = 2.14e36/Power(n[i]*1e21,1.82);//cm2/(Vs)
         if (p[i]>1e-3)
            mu_h = 2.14e36/Power(p[i]*1e21,1.82);//cm2/(Vs)
	      double dn_dt = mu_e*(dn[i]/dx*E[i]+n[i]*dE[i]/dx); // 1e7/nm3/s
	      double dp_dt = -mu_h*(dp[i]/dx*E[i]+p[i]*dE[i]/dx);
         dn_dt+=De*d2n[i]/dx/dx/1e7; // 1e7/nm3/s
         dp_dt+=Dh*d2p[i]/dx/dx/1e7;
	      n[i]+=dn_dt*dt;
	      p[i]+=dp_dt*dt;
      }
      // update electric field distribution
      for (int i=0; i<2*N+1; i++) {
         E[i]=0;
         for (int j=0; j<i; j++) E[i]+=p[j]-n[j];
         for (int j=i+1; j<2*N+1; j++) E[i]+=n[j]-p[j];
         E[i]/=(2*epsilon/Q/dx/1e-7);
         E[i]+=Ee;
      }
      // update slopes
      for (int i=0; i<2*N; i++) {
         dp[i] = p[i+1]-p[i];
         dn[i] = n[i+1]-n[i];
         dE[i] = E[i+1]-E[i];
      }
      dp[2*N] = p[2*N]-p[2*N-1];
      dn[2*N] = n[2*N]-n[2*N-1];
      dE[2*N] = E[2*N]-E[2*N-1];
      // update second derivative
      for (int i=0; i<2*N; i++) {
         d2p[i] = dp[i+1]-dp[i];
         d2n[i] = dn[i+1]-dn[i];
      }
      d2p[2*N] = dp[2*N]-dp[2*N-1];
      d2n[2*N] = dn[2*N]-dn[2*N-1];
      iStep++;
   }
   t->Write("t",6);
   output->Close();

   return 0;
}
<|endoftext|>