2019-12-15 19:32:14 +01:00
class excitationTypes {
2020-06-10 15:18:39 +02:00
static get Valence ( ) { return new excitationType ( 1 << 1 , new description ( "Valence" ) ) }
2020-03-20 11:09:48 +01:00
static get Rydberg ( ) { return new excitationType ( 1 << 2 , new description ( "Rydberg" ) ) }
2020-06-10 15:18:39 +02:00
static get PiPis ( ) { return new excitationType ( 1 << 3 , new description ( String . raw ` \p i \r ightarrow \p i^ \s tar ` , true ) ) }
static get nPis ( ) { return new excitationType ( 1 << 4 , new description ( String . raw ` n \r ightarrow \p i^ \s tar ` , true ) ) }
2020-03-08 16:17:04 +01:00
static get Single ( ) { return new excitationType ( 1 << 5 , new description ( "Single" ) ) }
static get Double ( ) { return new excitationType ( 1 << 6 , new description ( "Double" ) ) }
2020-06-10 15:18:39 +02:00
static get SingletSinglet ( ) { return new excitationType ( 1 << 7 , new description ( String . raw ` \m athrm{Singlet} \r ightarrow \m athrm{Singlet} ` , true ) ) }
static get SingletTriplet ( ) { return new excitationType ( 1 << 8 , new description ( String . raw ` \m athrm{Singlet} \r ightarrow \m athrm{Triplet} ` , true ) ) }
static get DoubletDoublet ( ) { return new excitationType ( 1 << 9 , new description ( String . raw ` \m athrm{Doublet} \r ightarrow \m athrm{Doublet} ` , true ) ) }
2020-01-07 10:22:33 +01:00
// Max bit shifts is 31 because int are int32 So 1 << 31 are -2147483648
2020-06-10 15:18:39 +02:00
static get Others ( ) { return new excitationType ( 1 << 31 , new description ( "Others" ) ) }
static get All ( ) { return EnumUltils . getAll ( this , excitationType ) }
static GetFlags ( value ) { return EnumUltils . GetFlags ( value , this , excitationType ) }
2020-01-28 17:25:49 +01:00
}
2020-06-10 15:18:39 +02:00
class EnumUltils {
static getAll ( enumClass , valueType ) {
2020-01-06 14:35:29 +01:00
var lst = [ ]
2020-01-28 17:25:49 +01:00
for ( const prop of Object . getOwnPropertyNames ( enumClass ) ) {
2020-01-06 14:35:29 +01:00
if ( prop != "All" ) {
2020-01-28 17:25:49 +01:00
const value = enumClass [ prop ]
if ( trueTypeOf ( value ) == valueType . name ) {
2020-01-06 14:35:29 +01:00
lst . push ( [ prop , value ] )
2019-12-16 13:49:41 +01:00
}
2020-01-06 14:35:29 +01:00
}
2019-12-16 13:49:41 +01:00
}
return lst
}
2020-06-10 15:18:39 +02:00
static GetFlags ( value , enumClass , valueType ) {
return this . getAll ( enumClass , valueType ) . filter ( ( x ) => { value & x [ 1 ] } )
2019-12-16 13:49:41 +01:00
}
2019-12-15 19:32:14 +01:00
}
2020-01-27 11:09:35 +01:00
2020-03-08 16:17:04 +01:00
class description {
2020-06-10 15:18:39 +02:00
constructor ( string , isLaTeX = false ) {
2020-03-08 16:17:04 +01:00
this . string = string
2020-06-10 15:18:39 +02:00
this . isLaTeX = isLaTeX
2020-03-08 16:17:04 +01:00
}
}
class DescribedValueBase {
constructor ( value , description ) {
2020-01-06 14:35:29 +01:00
this . Value = value ;
2020-03-08 16:17:04 +01:00
this . description = description
2019-12-15 19:32:14 +01:00
}
2020-01-06 14:35:29 +01:00
valueOf ( ) {
2019-12-16 13:49:41 +01:00
return this . Value ;
}
2019-12-01 18:14:45 +01:00
}
2020-01-27 11:09:35 +01:00
2020-06-10 15:18:39 +02:00
class excitationType extends DescribedValueBase {
2020-01-27 11:09:35 +01:00
}
2020-06-10 15:18:39 +02:00
class VertExcitationKind extends DescribedValueBase {
2020-01-27 11:09:35 +01:00
}
2019-08-28 11:59:18 +02:00
class code {
2019-09-26 20:25:51 +02:00
constructor ( name , version ) {
this . name = name ;
this . version = version ;
2019-09-03 15:36:32 +02:00
} ;
2019-09-26 20:25:51 +02:00
toString ( ) {
var str = this . name ;
2019-09-03 15:36:32 +02:00
if ( this . version ) {
2019-09-26 20:25:51 +02:00
str = str + ' (' + this . version + ')' ;
2019-09-03 15:36:32 +02:00
}
return str ;
2019-08-28 11:59:18 +02:00
}
2019-09-19 15:05:07 +02:00
static fromString ( str ) {
2019-09-26 20:25:51 +02:00
var vals = str . split ( "," )
if ( vals . length >= 2 ) {
return new code ( vals [ 0 ] , vals [ 1 ] ) ;
2019-09-19 15:05:07 +02:00
} else {
2019-09-26 20:25:51 +02:00
return new code ( vals [ 0 ] , null ) ;
2019-09-19 15:05:07 +02:00
}
}
2019-08-28 11:59:18 +02:00
}
2019-09-17 17:19:00 +02:00
class method {
2020-01-06 14:35:29 +01:00
constructor ( name , basis = null ) {
2019-09-26 20:25:51 +02:00
this . name = name ;
this . basis = basis ;
2019-09-03 15:36:32 +02:00
}
2019-09-19 15:05:07 +02:00
static fromString ( str ) {
2019-09-26 20:25:51 +02:00
var vals = str . split ( "," )
2019-11-24 19:40:57 +01:00
if ( vals . length == 2 ) {
return new method ( vals [ 0 ] , vals [ 1 ] ) ;
}
else {
return new method ( vals [ 0 ] , null )
2019-09-26 09:32:03 +02:00
}
2019-09-19 15:05:07 +02:00
}
2020-06-10 15:18:39 +02:00
toString ( separator = "/" ) {
2019-09-26 20:25:51 +02:00
var str = this . name ;
2019-09-28 14:38:14 +02:00
if ( this . basis ) {
2020-02-20 11:54:50 +01:00
str = str + separator + this . basis ;
2019-09-03 15:36:32 +02:00
}
return str ;
2019-08-22 10:34:07 +02:00
}
2020-01-06 14:35:29 +01:00
get isTBE ( ) {
2020-01-03 17:12:43 +01:00
return /^TBE/ . test ( this . name )
}
2019-08-22 10:34:07 +02:00
}
2019-09-26 20:25:51 +02:00
class state {
constructor ( number , multiplicity , symetry ) {
this . number = number ;
this . multiplicity = multiplicity ;
this . symetry = symetry ;
2019-09-03 15:36:32 +02:00
} ;
2019-09-26 20:25:51 +02:00
toString ( ) {
var str = this . number + ' ^' + this . multiplicity + this . symetry ;
2019-09-03 15:36:32 +02:00
return str ;
} ;
toLaTeX ( ) {
2019-11-12 15:27:53 +01:00
var tex = String . raw ` ${ this . number } \: ^{ ${ this . multiplicity } } \m athrm{ ${ this . symetry } } ` ;
2019-09-03 15:36:32 +02:00
return tex ;
} ;
2019-08-22 10:34:07 +02:00
}
2019-09-26 09:32:03 +02:00
2019-09-26 20:25:51 +02:00
class excitationBase {
2020-01-06 14:35:29 +01:00
constructor ( initial , final , type = '' , T1 = null ) {
2019-09-26 20:25:51 +02:00
this . initial = initial ;
this . final = final
2020-06-10 15:18:39 +02:00
this . type = new excitationType ( 0 , new description ( type , true ) )
2020-03-31 14:24:01 +02:00
if ( type ) {
2019-12-10 13:55:32 +01:00
const tys = type . split ( ";" )
const arrow = String . raw ` \r ightarrow `
for ( const ty of tys ) {
if ( ty . includes ( arrow ) ) {
const [ initialt , finalt ] = ty . split ( arrow , 2 )
2020-01-06 14:35:29 +01:00
const initialts = initialt . split ( "," ) . map ( x => x . trim ( ) )
const finalts = finalt . split ( "," ) . map ( x => x . trim ( ) )
2020-01-08 16:30:55 +01:00
if ( initialts . length == 2 && finalts . length == 2 ) {
2020-01-06 14:35:29 +01:00
this . type . Value = this . type | excitationTypes . Double
2019-12-03 11:32:14 +01:00
}
2020-01-14 14:20:43 +01:00
else if ( initialts . length == 1 && finalts . length == 1 ) {
2020-01-06 14:35:29 +01:00
this . type . Value = this . type | excitationTypes . Single
2019-12-03 11:32:14 +01:00
}
2019-12-13 10:32:25 +01:00
if ( initialts . includes ( "n" ) && finalts . includes ( String . raw ` \p i^ \s tar ` ) ) {
2020-01-06 14:35:29 +01:00
this . type . Value = this . type | excitationTypes . nPis
2020-01-07 09:28:41 +01:00
} else if ( initialts . includes ( String . raw ` \p i ` ) && finalts . includes ( String . raw ` \p i^ \s tar ` ) ) {
2020-01-06 14:35:29 +01:00
this . type . Value = this . type | excitationTypes . PiPis
2019-12-01 18:14:45 +01:00
}
2020-01-06 14:35:29 +01:00
} else if ( ty . includes ( String . raw ` \m athrm{R} ` ) ) {
2020-03-20 11:09:48 +01:00
this . type . Value = this . type | excitationTypes . Rydberg
2020-01-06 14:35:29 +01:00
} else if ( ty . includes ( String . raw ` \m athrm{V} ` ) ) {
2020-03-20 11:09:48 +01:00
this . type . Value = this . type | excitationTypes . Valence
2020-07-24 13:56:17 +02:00
} else if ( ty . toLowerCase ( ) === excitationTypes . Double . description . string . toLowerCase ( ) ) {
this . type . Value = this . type | excitationTypes . Double
2019-12-01 18:14:45 +01:00
}
}
}
2020-06-01 14:06:42 +02:00
var m = new Map ( [
2020-06-10 15:18:39 +02:00
[ JSON . stringify ( [ 1 , 1 ] ) , excitationTypes . SingletSinglet ] ,
[ JSON . stringify ( [ 2 , 2 ] ) , excitationTypes . DoubletDoublet ] ,
[ JSON . stringify ( [ 1 , 3 ] ) , excitationTypes . SingletTriplet ] ,
2020-06-01 14:06:42 +02:00
] )
2020-06-10 15:18:39 +02:00
const marray = JSON . stringify ( [ initial . multiplicity , final . multiplicity ] )
2020-06-01 14:06:42 +02:00
if ( m . has ( marray ) ) {
2020-06-10 15:18:39 +02:00
this . type . Value = this . type . Value | m . get ( marray )
2020-01-07 11:42:44 +01:00
}
2020-06-10 15:18:39 +02:00
if ( this . type . Value == 0 ) {
this . type . Value = excitationTypes . Others . Value ;
2020-01-06 21:03:06 +01:00
}
2019-12-01 18:14:45 +01:00
this . T1 = T1
2019-09-26 09:32:03 +02:00
}
}
2019-09-26 20:25:51 +02:00
class excitationValue extends excitationBase {
2020-01-06 14:35:29 +01:00
constructor ( initial , final , type , value , oscilatorForces = null , T1 = null , isUnsafe = false ) {
2019-12-10 13:55:32 +01:00
super ( initial , final , type , T1 )
2019-09-26 20:25:51 +02:00
this . value = value
2019-11-25 14:49:40 +01:00
this . oscilatorForces = oscilatorForces
2019-12-17 09:59:57 +01:00
this . isUnsafe = isUnsafe
2019-11-20 20:15:53 +01:00
}
}
2019-09-26 09:32:03 +02:00
class dataFileBase {
2019-09-26 20:25:51 +02:00
constructor ( ) {
this . molecule = ''
2019-11-28 15:55:05 +01:00
this . comment = ""
2019-09-26 20:25:51 +02:00
this . code = null
this . method = null
this . excitations = [ ]
2020-09-09 14:39:46 +02:00
this . article = null
2020-01-06 14:35:29 +01:00
this . sourceFile = null
2019-08-28 11:59:18 +02:00
}
2020-01-27 11:09:35 +01:00
static _GetMetaRexEx ( ) {
//metadata RegExp (start with #; maybe somme spaces; : ; maybe somme space; datas)
return /^#\s*([A-Za-z_]+)\s*:\s*(.*)$/ ;
}
2020-01-15 13:10:21 +01:00
CopyExcitationsTypeFrom ( data ) {
for ( const ex of this . excitations ) {
2020-06-10 15:18:39 +02:00
const ex2 = data . excitations . find ( ( e ) => {
return ( JSON . stringify ( e . initial ) === JSON . stringify ( ex . initial ) ) && ( JSON . stringify ( e . final ) === JSON . stringify ( ex . final ) )
2020-01-15 13:10:21 +01:00
} )
2020-06-10 15:18:39 +02:00
if ( ex2 !== undefined ) {
if ( DebugMode . Enabled ) {
console . assert ( ex . type == 0 || ( ex2 . type ^ ( excitationTypes . Rydberg | excitationTypes . Valence ) == ex . type ^ ( excitationTypes . Rydberg | excitationTypes . Valence ) ) , "Excitation type error" , [ ex , ex2 , data . sourceFile ] )
}
ex . type = ex2 . type
2020-01-15 13:10:21 +01:00
}
}
}
2020-06-10 15:18:39 +02:00
static async loadAsync ( file , kind = undefined ) {
2019-10-02 19:20:37 +02:00
switch ( trueTypeOf ( file ) ) {
2019-11-02 16:21:11 +01:00
case String . name :
2020-01-06 14:35:29 +01:00
file = getFullDataPath ( file )
var str = await getTextFromFileUrlAsync ( file )
2019-10-02 19:20:37 +02:00
break ;
2019-11-02 16:21:11 +01:00
case File . name :
2020-01-06 14:35:29 +01:00
var str = await getTextFromUploadedFileAsync ( file )
2019-10-02 19:20:37 +02:00
break
}
2020-06-10 15:18:39 +02:00
var dat = this . loadString ( str , kind ) ;
2020-01-06 14:35:29 +01:00
dat . sourceFile = new websiteFile ( file )
2019-09-30 10:53:13 +02:00
return dat
2019-09-26 09:32:03 +02:00
}
2020-01-27 11:09:35 +01:00
_OnReadMetaPair ( key , value ) {
2019-09-26 20:25:51 +02:00
switch ( key ) {
2019-09-26 09:32:03 +02:00
case "molecule" :
2020-01-27 11:09:35 +01:00
this . molecule = value
2019-09-26 09:32:03 +02:00
break ;
case "comment" :
2020-01-27 11:09:35 +01:00
this . comment = value
2019-09-26 09:32:03 +02:00
break ;
case "code" :
2020-01-27 11:09:35 +01:00
this . code = code . fromString ( value )
2019-09-26 09:32:03 +02:00
break ;
case "method" :
2020-01-27 11:09:35 +01:00
this . method = method . fromString ( value )
2019-09-26 20:25:51 +02:00
break ;
2020-09-09 14:39:46 +02:00
case "article" :
this . article = value
2019-09-26 09:32:03 +02:00
break ;
}
2019-08-28 11:59:18 +02:00
}
2020-01-27 11:09:35 +01:00
_OnReadRow ( line ) {
var vals = line . match ( /\([^\)]+\)|\S+/g )
var start = new state ( parseInt ( vals [ 0 ] , 10 ) , parseInt ( vals [ 1 ] , 10 ) , vals [ 2 ] ) ;
2020-06-10 15:18:39 +02:00
var end = new state ( parseInt ( vals [ 3 ] , 10 ) , parseInt ( vals [ 4 ] , 10 ) , vals [ 5 ] ) ;
2020-09-11 16:55:53 +02:00
var type = ( ( vals . length >= 7 ) ? vals [ 6 ] : null )
2020-06-10 15:18:39 +02:00
if ( type === "_" ) {
type = null
2020-03-31 14:24:01 +02:00
}
2020-01-27 11:09:35 +01:00
if ( type ) {
const m = type . match ( /^\(([^\)]*)\)$/ )
if ( m ) {
type = m [ 1 ]
2019-08-28 11:59:18 +02:00
}
}
2020-09-11 16:55:53 +02:00
var val = ( ( vals . length >= 8 ) ? new stringNumber ( vals [ 7 ] ) : NaN )
var T1 = ( ( vals . length >= 9 ) ? new stringNumber ( vals [ 8 ] ) : NaN )
var oscilatorForces = ( ( vals . length >= 10 ) ? new stringNumber ( vals [ 9 ] ) : NaN )
var isUnsafe = ( ( vals . length >= 11 ) ? vals [ 10 ] === true . toString ( ) : false )
2020-01-27 11:09:35 +01:00
var ex = new excitationValue ( start , end , type , val , oscilatorForces , T1 , isUnsafe ) ;
if ( this . VertExcitationKind ) {
2020-06-10 15:18:39 +02:00
ex . VertExcitationKind = this . VertExcitationKind
2020-01-27 11:09:35 +01:00
}
return ex ;
} ;
_OnReadMeta ( line ) {
// get key value
var match = line . match ( dataFileBase . _GetMetaRexEx ( ) )
// normalize key to lower
var key = match [ 1 ] . toLowerCase ( )
//if data has value
if ( match . length == 3 && match [ 2 ] ) {
var val = match [ 2 ]
2020-06-10 15:18:39 +02:00
this . _OnReadMetaPair ( key , val )
2020-01-27 11:09:35 +01:00
}
}
2020-06-10 15:18:39 +02:00
static loadString ( text , kind = null ) {
2020-01-27 11:09:35 +01:00
// for each line with metadata
var ismetaArea = true ;
var dat = new VertDataFile ( )
2019-09-26 20:25:51 +02:00
for ( var line of text . split ( "\n" ) ) {
2019-08-28 11:59:18 +02:00
//if it's not empty line
2019-09-26 20:25:51 +02:00
line = line . trim ( ) ;
if ( line ) {
2019-08-28 11:59:18 +02:00
//if # may be metadata or comment
2019-09-26 20:25:51 +02:00
if ( line . charAt ( 0 ) == "#" ) {
2019-08-28 11:59:18 +02:00
//if it's metadata
2020-01-27 11:09:35 +01:00
if ( ismetaArea && dataFileBase . _GetMetaRexEx ( ) . test ( line ) ) {
dat . _OnReadMeta ( line ) ;
2019-09-26 20:25:51 +02:00
}
2019-08-28 11:59:18 +02:00
} else { //else its row
2019-09-26 20:25:51 +02:00
ismetaArea = false ;
2020-06-10 15:18:39 +02:00
dat . excitations . push ( dat . _OnReadRow ( line , kind ) ) ;
2019-08-28 11:59:18 +02:00
}
}
2019-09-26 20:25:51 +02:00
}
2020-06-10 15:18:39 +02:00
if ( DebugMode . Enabled ) {
var stfy = dat . excitations . map ( e => JSON . stringify ( [ e . initial , e . final ] ) )
var double = [ ]
stfy . forEach ( function ( element , i ) {
// Find if there is a duplicate or not
if ( stfy . indexOf ( element , i + 1 ) >= 0 ) {
// Find if the element is already in the result array or not
if ( double . indexOf ( element ) === - 1 ) {
double . push ( dat . excitations [ i ] )
}
}
} ) ;
console . assert ( double . length === 0 , "Double found" , double , dat . molecule , dat . method . toString ( ) )
2020-09-09 14:39:46 +02:00
if ( dat . article !== null && dat . article !== "10.1021/acs.jctc.8b01205" ) {
2020-06-10 15:18:39 +02:00
for ( const ex of dat . excitations ) {
console . assert ( Number . isNaN ( ex . T1 . valueOf ( ) ) | ex . T1 > 50 | ex . isUnsafe == true , "Must be unsafe" , dat , ex )
2020-03-14 17:29:47 +01:00
}
2020-03-30 15:41:25 +02:00
}
2020-03-17 13:48:42 +01:00
}
2019-08-28 11:59:18 +02:00
return dat
}
2019-08-22 10:34:07 +02:00
}
2020-06-10 15:18:39 +02:00
class VertExcitationKinds {
static get Absorbtion ( ) { return new VertExcitationKind ( 1 , new description ( "Absorption" ) ) }
static get Fluorescence ( ) { return new VertExcitationKind ( 1 << 1 , new description ( "Fluorescence" ) ) }
static get All ( ) { return EnumUltils . getAll ( this , VertExcitationKind ) }
static GetFlags ( value ) { return EnumUltils . GetFlags ( value , this , VertExcitationKind ) }
2020-01-27 11:09:35 +01:00
}
class VertDataFile extends dataFileBase {
constructor ( VertExcitationKind ) {
2019-09-26 09:32:03 +02:00
super ( )
2020-06-10 15:18:39 +02:00
this . VertExcitationKind = VertExcitationKind
2019-09-26 20:25:51 +02:00
this . geometry = null
2019-09-26 09:32:03 +02:00
}
2020-06-10 15:18:39 +02:00
_OnReadMetaPair ( key , value ) {
2019-09-26 20:25:51 +02:00
if ( key == "geom" ) {
2020-01-27 11:09:35 +01:00
this . geometry = method . fromString ( value )
2019-09-26 09:32:03 +02:00
}
2019-09-26 20:25:51 +02:00
else {
2020-01-27 11:09:35 +01:00
super . _OnReadMetaPair ( key , value )
2019-09-26 09:32:03 +02:00
}
}
2020-06-10 15:18:39 +02:00
_OnReadRow ( line , kind ) {
var ex = super . _OnReadRow ( line )
ex . VertExcitationKind = kind
2020-01-27 11:09:35 +01:00
return ex
2019-09-26 09:32:03 +02:00
}
}