/*************************************************************************** * musrSim - the program for the simulation of (mainly) muSR instruments. * * More info on http://lmu.web.psi.ch/simulation/index.html . * * musrSim is based od Geant4 (http://geant4.web.cern.ch/geant4/) * * * * Copyright (C) 2009 by Paul Scherrer Institut, 5232 Villigen PSI, * * Switzerland * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * ***************************************************************************/ #include "musrTabulatedElementField.hh" #include "musrParameters.hh" #include "musrErrorMessage.hh" #include "G4UnitsTable.hh" musrTabulatedElementField::musrTabulatedElementField( const char* filename, const char* fldTableType, G4double fieldValue, G4LogicalVolume* logVolume, G4ThreeVector positionOfTheCenter) : F04ElementField(positionOfTheCenter, logVolume), ffieldValue(fieldValue) { // The following posibilities of the format of the field map are distinguieshed: // 3DBOpera = 3D ... 3D field , magnetic, Opera format (Kamil-like) // 3DEOpera = 3D ... 3D field , electric, Opera format (Kamil-like) // 3DE ... 3D field , electric, Toni-like (3DE WAS TESTED) // 3DB ... 3D field , magnetic, Toni-like // 2DBOpera = 2D .... 2D field, magnetic, Opera format (Kamil-like), X and Z components (2D WAS TESTED) // 2DBOperaXY = 2D_OperaXY .... 2D field, magnetic, Opera format with (Kamil-like), X and Y components // 2DE ... 2D field , electric, Toni-like (2DE WAS TESTED) // 2DB ... 2D field , magnetic, Toni-like // 3DBQuadVrankovic ... 3D field of a quadrupole magnet asymmetric in z but with the symmetric octants in (x,y) plane G4double lenUnit = 1*m; // length unit of the field map grid coordinates G4double fieldNormalisation = 1.; // Normalisation factor by which the the field map has to be multiplied // in order to get 1T (in the case of magnetic field) // "lenUnit" and "fieldNormalisation" are needed only if not specified // inside the fieldmap file; strcpy(fieldTableType,fldTableType); fldType = 'B'; fUnit = "T"; fieUnit = tesla; if (fieldTableType[2]=='E') { fldType = 'E'; fUnit = "kV/mm"; fieUnit= kilovolt/mm; } symmetryType=0; strcpy(variableIncreasingOrder,"zyx"); jx=-1; jy=0; jz=0; fldDim = (fieldTableType[0]=='3') ? 3:2; if (fldDim==2) ny=1; G4cout << "\n-----------------------------------------------------------" << G4endl; G4cout << " Field (of type "< " "Reading the field grid from " << filename << " ... " << G4endl; std::ifstream file( filename ); // Open the file for reading. if (!(file.is_open())) { G4cout << "Fieldmap file \""<< filename << "\" not opened (found) !!!"<musrError(FATAL,"musrTabulatedElementField: Field map file not found !",false); } char buffer[256]; char tmpString1[100]="Unset"; char tmpString2[100]="Unset"; float fvalue; int ivalue; G4bool boolMinimaAndMaximaDefinedInTheFile = false; if (fldType=='E') G4cout<<" Electric field "; if (fldType=='B') G4cout<<" Magnetic field "; if ((strcmp(fieldTableType,"3DE")==0)||(strcmp(fieldTableType,"3DB")==0)) { // File is in Toni Shiroka format: // Read the number of arguments and decide filetype - 3 or 6 columns G4cout << "3D, field-map file format by Toni Shiroka" << G4endl; char lenUnitFromFile[50]; double fieldNormalisationFromFile; file.getline(buffer,256); int n_arg = sscanf (buffer,"%d %d %d %s %lf %lf %lf %lf %lf %lf %lf", &nx, &ny, &nz, lenUnitFromFile, &fieldNormalisationFromFile, &minimumx, &maximumx, &minimumy, &maximumy, &minimumz, &maximumz); lenUnit = G4UnitDefinition::GetValueOf(lenUnitFromFile); fieldNormalisation = fieldNormalisationFromFile; if (n_arg==11) { // The length unit and norm. factor have to be manually added to the field-map file! G4cout << " ---> Assumed order (3 col.): "< Assumed order (6 col.): x, y, z, "< Assumed order (7 col.): x, y, z, "< Assumed order (4 col.): r, z, "<> nx >> nz >> lenUnitFromFile >> fieldNormalisation; lenUnit = G4UnitDefinition::GetValueOf(lenUnitFromFile); // Ignore header information. All lines whose first character // is '%' are considered to be part of the header. do { file.ignore(256, '\n'); } while (file.peek() == '%'); } else if ((strcmp(fieldTableType,"2D_OperaXY")==0)||(strcmp(fieldTableType,"2DBOperaXY")==0)) { int nDummy; lenUnit = 1*cm; fieldNormalisation = 0.00001; G4cout << "2D, field-map file format from OPERA with X,Y components (Kamil)" << G4endl; G4cout << " ---> Assumed order (6 col.): r, z, dummy, "<> nx >> nz >> nDummy; do { file.getline(buffer,256); sscanf(&buffer[0],"%s %g",tmpString1,&fvalue); if (strcmp(tmpString1,"fieldNormalisation")==0) { fieldNormalisation = fvalue; G4cout << "DEBUG: musrTabulatedElementField: fieldNormalisation set to "< Assumed order (6 col.): r, dummy, z, "<> nx >> nDummy >> nz; // G4cout << nx <<" "<< nDummy <<" "<< nz< S T O P " << G4endl; musrErrorMessage::GetInstance()->musrError(FATAL,"musrTabulatedElementField: Unknown field required!",false); } // SET UP STORAGE SPACE FOR THE TABLE int ix, iy, iz; if (fldDim==3) { G4cout << " The grid consists of [" << nx << " x " << ny << " x " << nz << "] x, y, z values" << G4endl; G4cout << " Field map length unit = " << lenUnit/mm<<" mm"<< G4endl; G4cout << " Field map normalisation factor = " << fieldNormalisation << G4endl; // Set up storage space for the table xField.resize( nx ); yField.resize( nx ); zField.resize( nx ); for (ix=0; ixmusrError(WARNING,eMessage,false); } // Set up storage space for the table xField2D.resize( nx ); zField2D.resize( nx ); for (ix=0; ix> bx >> by >> bz; // Read ONLY field values } else { file >> xval >> yval >> zval >> bx >> by >> bz; } } else if ((strcmp(fieldTableType,"3D")==0)||(strcmp(fieldTableType,"3DBOpera")==0)||(strcmp(fieldTableType,"3DEOpera")==0)) { file >> xval >> yval >> zval >> bx >> by >> bz >> permeability; // G4cout<< xval <<" "<< yval <<" "<< zval <<" "<< bx <<" "<< by <<" "<< bz <> xval >> yval >> zval >> bx >> by >> bz; } else if ((strcmp(fieldTableType,"2DE")==0)||(strcmp(fieldTableType,"2DB")==0)||(strcmp(fieldTableType,"2DEf")==0)) { file >> xval >> zval >> bx >> bz; } else if ((strcmp(fieldTableType,"2D")==0)||(strcmp(fieldTableType,"2DBOpera")==0)) { file >> xval >> yval >> zval >> bx >> bz >> permeability; // G4cout<< xval <<" "<< yval <<" "<< zval <<" "<< bx <<" "<< bz <> xval >> zval >> yval >> bx >> bz >> permeability; } else { G4cout << " musrTabulatedElementField::musrTabulatedElementField: Undefined field required!" << " ("< S T O P " << G4endl; musrErrorMessage::GetInstance()->musrError(FATAL,"musrTabulatedElementField: Undefined field required!",false); } if (fldDim==3) { // 3D field if ((!boolMinimaAndMaximaDefinedInTheFile) && ( ix==0 && iy==0 && iz==0 ) ) { minimumx = xval * lenUnit; minimumy = yval * lenUnit; minimumz = zval * lenUnit; } if (strcmp(variableIncreasingOrder,"xyz")==0) { // The order of how the x,y,z variables increase in the field map file is non-standard. // Recalculate the indexes of the fieldmap array for this special case: jx++; if (jx==nx) { jx=0; jy++; if (jy==ny) { jy=0; jz++; if (jz==nz) { // this should never happen - problem! musrErrorMessage::GetInstance()->musrError(FATAL,"musrTabulatedElementField: too many lines found in the field map file !",false); } } } xField[jx][jy][jz] = bx*fieldNormalisation; yField[jx][jy][jz] = by*fieldNormalisation; zField[jx][jy][jz] = bz*fieldNormalisation; // if ((jx==nx-1)&&(jy==ny-1)&&(jz==nz-1)) { // G4cout<<" jx="< UNDERSTAND THE PROBLEM BEFORE PROCEEDING FURTHER!"< S T O P " << G4endl; musrErrorMessage::GetInstance()->musrError(FATAL,"musrTabulatedElementField: non-zero symmetryType for field that does not start at (0,0,0)",false); } } // if ((!boolMinimaAndMaximaDefinedInTheFile)&&(strcmp(variableIncreasingOrder,"xyz")!=0)) { if (!boolMinimaAndMaximaDefinedInTheFile) { maximumx = xval * lenUnit; maximumz = zval * lenUnit; if (fldDim==3) maximumy = yval * lenUnit; } G4cout << " ---> ... reading of the field map finished." << G4endl; if (fldDim==3) G4cout<<" ---> Min values of x,y,z: "; else G4cout<<" ---> Min values of R,z: "; G4cout << minimumx/cm << ", "; if (fldDim==3) G4cout<< minimumy/cm << ", " ; G4cout << minimumz/cm << " cm "< Max values of x,y,z: "; else G4cout<<" ---> Max values of R,z: "; G4cout << maximumx/cm << ", "; if (fldDim==3) G4cout<< maximumy/cm << ", " ; G4cout << maximumz/cm << " cm " << G4endl; // Should really check that the limits are not the wrong way around. G4bool reorderingDone = false; if (maximumx < minimumx) {Invert("x"); reorderingDone=true;} if (fldDim==3) {if (maximumy < minimumy) {Invert("y"); reorderingDone=true;} } if (maximumz < minimumz) {Invert("z"); reorderingDone=true;} if (reorderingDone) { G4cout << "\n Reordering of the field grid was neccessary - after reordering:"< Min values of x,y,z: "; else G4cout<<" ---> Min values of R,z: "; G4cout << minimumx/cm << ", "; if (fldDim==3) G4cout<< minimumy/cm << ", " ; G4cout << minimumz/cm << " cm "< Max values of x,y,z: "; else G4cout<<" ---> Max values of R,z: "; G4cout << maximumx/cm << ", "; if (fldDim==3) G4cout<< maximumy/cm << ", " ; G4cout << maximumz/cm << " cm " << G4endl; } dx = maximumx - minimumx; if (fldDim==3) dy = maximumy - minimumy; dz = maximumz - minimumz; if (fldDim==3) G4cout << "\n ---> Dif values x,y,z (range): "; else G4cout << "\n ---> Dif values R,z (range): "; G4cout << dx/cm << ", "; if (fldDim==3) G4cout << dy/cm << ", "; G4cout << dz/cm << " cm."< 1*dz would be fine for symmetric (in z) case, but 2*dz is safe for z going eg. from -80 to 20 cm. else if (symmetryType>0) {maximumWidth = 2*dx; maximumHeight = 2*dy; maximumLength = 2*dz;} else {maximumWidth = dx; maximumHeight = dy; maximumLength = dz;} } } void musrTabulatedElementField::addFieldValue(const G4double point[4], G4double *field ) const { // G4cout<<"musrTabulatedElementField::addFieldValue"<0) ? 1.:-1.; y_sign = (y>0) ? 1.:-1.; z_sign = (z>0) ? 1.:-1.; switch(symmetryType) { case (1): case (2): x=fabs(x); y=fabs(y); z=fabs(z); break; case (101): x=fabs(x); y=fabs(y); if (y>x) {xySwap=true; double xtmp=x; x=y; y=xtmp;} break; default : G4cout<<" musrTabulatedElementField: unsupported symmetryType (="<=minimumx && x=minimumy && y=minimumz && z(xdindex); int yindex = static_cast(ydindex); int zindex = static_cast(zdindex); // The following is not neede (it should be treated by the code several lines above). // if (symmetryType==101) { // if (yindex>(ny-2)) return; // field not defined in this region for the quadrupole // } //cks The following check is necessary - even though xindex and zindex should never be out of range, // it may happen (due to some rounding error ?). It is better to leave the check here. if ((xindex<0)||(xindex>(nx-2))) { std::cout<<"SERIOUS PROBLEM: xindex out of range! xindex="<0) ? 1.:-1.; } else { // Field is defined along the whole range of the z axis (i.e. asymmetric field is expected) x = sqrt(local.x()*local.x()+local.y()*local.y()); z = local.z(); z_sign = 1; } // Check that the point is within the defined region if ( xevNrKriz) std::cout<<"bol som tu"<(xdindex); int zindex = static_cast(zdindex); //cks The following check is necessary - even though xindex and zindex should never be out of range, // it may happen (due to some rounding error ?). It is better to leave the check here. if ((xindex<0)||(xindex>(nx-2))) { std::cout<<"SERIOUS PROBLEM: xindex out of range! xindex="< > > xFieldTemp(xField); std::vector< std::vector< std::vector< double > > > yFieldTemp(yField); std::vector< std::vector< std::vector< double > > > zFieldTemp(zField); G4bool invertX=false; G4bool invertY=false; G4bool invertZ=false; G4cout<<"Check that the musrTabulatedElementField::Invert() function works properly!"<