// Geant4 simulation for MuSR // AUTHOR: Toni SHIROKA, Paul Scherrer Institut, PSI // DATE : 2008-05 // #include "lem4TabulatedElementField3D.hh" #include "lem4Parameters.hh" #include "G4UnitsTable.hh" #include lem4TabulatedElementField3D::lem4TabulatedElementField3D(const char* filename, const char fieldType, G4double fieldValue, G4LogicalVolume* logVolume, G4ThreeVector positionOfTheCenter) : F04ElementField(positionOfTheCenter, logVolume), fldType(fieldType), ffieldValue(fieldValue) { G4cout << "\n-----------------------------------------------------------"; // The DEFAULT user-defined field units for E and B (kilovolt/mm and tesla) // NOTE: Should be the same as EMfieldUnit defined in DetectorConstruction.cc! if (fldType == 'E') {G4cout << ("\n Electric field 3D"); fUnit = "kV/mm"; fieUnit= kilovolt/mm;} else if (fldType == 'B') {G4cout << ("\n Magnetic field 3D"); fUnit = "T"; fieUnit = tesla;} G4cout << "\n-----------------------------------------------------------" << G4endl; G4cout << "\n ---> Reading the "<< fldType <<"-field map from " << filename << " ... " << G4endl; // Open the file for reading std::ifstream file( filename ); // Read the first line of the file header (contains the metadata) char buffer[256]; file.getline(buffer,256); //G4cout << "The first line of file "<< filename << " is:\n"<< buffer << G4endl; // Read the file header ///file >> nx >> ny >> nz >> lUnit >> fieldNormalisation; // OLD VERSION // Read the number of arguments and decide filetype - 3 or 6 columns int n_arg = sscanf (buffer,"%d %d %d %s %lf %lf %lf %lf %lf %lf %lf", &nx, &ny, &nz, lUnit, &fieldNormalisation, &minimumx, &maximumx, &minimumy, &maximumy, &minimumz, &maximumz); // Add manually the length unit and norm. factor in the field-map file if missing! //printf ("The following data were read in: \n"); //printf ("nx = %d, ny = %d, nz = %d, Unit = %s, Norm = %f,\n minx = %f, maxx = %f, miny = %f, maxy = %f, minz = %f, maxz = %f\n",nx,ny,nz,lUnit,fieldNormalisation,minimumx, maximumx, minimumy, maximumy, minimumz, maximumz); ///printf ("nx = %d, ny = %d, nz = %d, Unit = %s, Norm = %f,\n minx = %f\n",nx,ny,nz,lUnit,fieldNormalisation,minimumx); //printf ("Number of args read: %d\n", n_arg); G4cout << " The grid consists of [" << nx << " x " << ny << " x " << nz << "] x, y, z values" << G4endl; // Get the field map LENGTH unit and its value in G4 native units. lenUnit = G4UnitDefinition::GetValueOf(lUnit); G4cout << " Field length unit = " << lUnit << ", in G4 native units = " << lenUnit << G4endl; G4cout << " Field map normalisation factor = " << fieldNormalisation << G4endl; // Set up storage space for the 3D table: notice the order! xField.resize(nx); yField.resize(nx); zField.resize(nx); int ix, iy, iz; for (ix=0; ix> xval >> yval >> zval >> fx >> fy >> fz; //fileout << fx <<" \t"<< fy << " \t"<< fz << std::endl; // for rewriting files if ( ix==0 && iy==0 && iz==0 ) { minimumx = xval * lenUnit; minimumy = yval * lenUnit; minimumz = zval * lenUnit; } } else if (n_arg == 11) { file >> fx >> fy >> fz; // Read ONLY field values } xField[ix][iy][iz] = fx*fieldNormalisation; yField[ix][iy][iz] = fy*fieldNormalisation; zField[ix][iy][iz] = fz*fieldNormalisation; } } } //fileout.close(); // for rewriting files file.close(); if (n_arg == 5) { maximumx = xval * lenUnit; maximumy = yval * lenUnit; maximumz = zval * lenUnit; } else if (n_arg == 11) { minimumx = minimumx * lenUnit; minimumy = minimumy * lenUnit; minimumz = minimumz * lenUnit; maximumx = maximumx * lenUnit; maximumy = maximumy * lenUnit; maximumz = maximumz * lenUnit; } G4String volumeName = logVolume->GetName().substr(4); G4cout << " ... done reading " << G4endl; G4cout << "\n ---> " << fldType << "-field in volume "<< volumeName << " set to: " << fieldValue/fieUnit << " " << fUnit << G4endl; if (n_arg == 5) { G4cout << "\n ---> Assumed order (6 col.): x, y, z, ";} else if (n_arg == 11) { G4cout << "\n ---> Assumed order (3 col.): ";} G4cout << fldType <<"x, "<< fldType <<"y, "<< fldType <<"z " << "\n Min values x, y, z: " << minimumx/cm << " " << minimumy/cm << " " << minimumz/cm << " cm " << "\n Max values x, y, z: " << maximumx/cm << " " << maximumy/cm << " " << maximumz/cm << " cm" << G4endl; // Should really check that the limits are not the wrong way around. if (maximumx < minimumx) {Invert("x");} if (maximumy < minimumy) {Invert("y");} if (maximumz < minimumz) {Invert("z");} if ((maximumx < minimumx) || (maximumy < minimumy)|| (maximumz < minimumz)) { G4cout << "\n ---> After reordering:" << "\n Min values x, y, z: " << minimumx/cm << " " << minimumy/cm << " " << minimumz/cm << " cm " << "\n Max values x, y, z: " << maximumx/cm << " " << maximumy/cm << " " << maximumz/cm << " cm " << G4endl; } dx = maximumx - minimumx; dy = maximumy - minimumy; dz = maximumz - minimumz; G4cout << " Range of values: " << dx/cm << " cm (in x), " << dy/cm << " cm (in y) and " << dz/cm << " cm (in z)." << "\n-----------------------------------------------------------\n" << G4endl; } void lem4TabulatedElementField3D::addFieldValue(const G4double point[4], G4double *field ) const { G4double EMf[3]; // EM field value obtained from the field map G4ThreeVector global(point[0],point[1],point[2]); G4ThreeVector local; local = global2local.TransformPoint(global); double x = local.x(); double y = local.y(); double z = local.z(); // G4cout<<"Global points= "<minimumx && xminimumy && yminimumz && z(xdindex); int yindex = static_cast(ydindex); 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="<