void ps_control_check_input(char *command, int argc) { ps_command_info_t const *command_info = ps_command_infos; while (command_info->name) { if (strcmp(command_info->name, command) != 0) { command_info++; continue; } if (command_info->needs_root) { if (getuid() != 0) ps_log(EXIT_FAILURE, LOG_ERROR("The command [%s] requires root permission"), command); } if ((argc < command_info->argc_min) || (argc > command_info->argc_max)) ps_log(EXIT_FAILURE, LOG_ERROR("Invallid number of parameters for command [%s]"), command); return; } ps_log(EXIT_FAILURE, LOG_ERROR("Unknown command [%s]"), command); }
void ps_control_run_program(int argc, char *argv[]) { int i; char *p; struct winsize windowsize; if (argc <= 0) ps_log(EXIT_FAILURE, LOG_ERROR("invallid number of arguments [%d]"), argc); if (isatty(STDIN_FILENO)) { if (ioctl(STDIN_FILENO, TIOCGWINSZ, &windowsize) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("failed to determine window size")); } else { windowsize.ws_col=80; windowsize.ws_row=25; } p=ps_buffer; *p++=PS_MSG_RUN_PROGRAM; sprintf(p,"%d",windowsize.ws_col); p+=strlen(p)+1; sprintf(p,"%d",windowsize.ws_row); p+=strlen(p)+1; sprintf(p,"%d",argc); p+=strlen(p)+1; int arg_size; int buffer_size_left=sizeof(ps_buffer)-(p-ps_buffer); for (i=0; i < argc; i++) { arg_size=strlen(argv[i])+1; if (arg_size > buffer_size_left) ps_log(EXIT_FAILURE, LOG_ERROR("size of --run parameters too large for buffer.")); sprintf(p,"%s",argv[i]); p+=arg_size; buffer_size_left-=arg_size; } if ((write(ps_fd_control, ps_buffer, p-ps_buffer)) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("failed to send PS_MSG_RUN_PROGRAM - error [%s]"), strerror(errno)); ps_control_io_loop(); }
void ps_log_open(const char* filename) { umask(0); if ((ps_fd_log=open(filename, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH)) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("failed to open logfile [%s] - error [%s]"), filename, strerror(errno)); }
void ps_control_connect_daemon() { ps_fd_control=socket(AF_UNIX, SOCK_SEQPACKET, 0); if (ps_fd_control == -1) ps_log(0, LOG_ERROR("failed to create socket - error [%s]"), strerror(errno)); else { if (connect(ps_fd_control, (struct sockaddr *) &ps_daemon_address, sizeof(ps_daemon_address)) == -1) { ps_log(0, LOG_ERROR("failed to connect to daemon - error [%s]"), strerror(errno)); close(ps_fd_control); ps_fd_control=-1; } } }
void ps_create_directory(char *path) { char *dir_start, *dir_end, *path_end; umask(0); path_end=path+strlen(path); dir_start=path+1; while (dir_start < path_end) { dir_end=strstr(dir_start,"/"); if (dir_end) *dir_end=0; if (mkdir(path, 0755) == -1) if (errno != EEXIST) ps_log(EXIT_FAILURE, LOG_ERROR("unable to create directory [%s] - error [%s]"), path, strerror(errno)); if (dir_end == NULL) break; *dir_end='/'; dir_start=dir_end+1; } }
void ps_terminal_send_exitcode(int fd_control, int exitcode) { ps_buffer[0]=PS_MSG_EXIT_STATUS; sprintf(ps_buffer+1,"%d", exitcode); if (write(fd_control, ps_buffer, strlen(ps_buffer)) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("failed to send exitcode to controller - error [%s]"), strerror(errno)); }
void ps_control_set_terminal_raw_mode(void) { struct termios terminal_attributes_raw = ps_saved_terminal_attributes; terminal_attributes_raw.c_lflag &= ~(ICANON | ISIG | IEXTEN |ECHO); terminal_attributes_raw.c_iflag &= ~(BRKINT | ICRNL |IGNBRK | IGNCR | IGNCR | INPCK | ISTRIP | IXON | PARMRK); terminal_attributes_raw.c_oflag &= ~OPOST; terminal_attributes_raw.c_cc[VMIN] = 1; terminal_attributes_raw.c_cc[VTIME] =0; if (tcsetattr(STDIN_FILENO, TCSAFLUSH /*TCSANOW*/ , &terminal_attributes_raw) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("unable to put terminal in raw mode - error [%s]"), strerror(errno)); }
void ps_set_name(const char* name) { if (strlen(name)+1 > sizeof(ps_name)) ps_log(EXIT_FAILURE, LOG_ERROR("program space name [%s] is too long, max length is [%d]"), name, sizeof(ps_name)-1); strcpy(ps_name, name); ps_name[sizeof(ps_name)-1]=0; memset(&ps_daemon_address, 0, sizeof(ps_daemon_address)); ps_daemon_address.sun_family=AF_UNIX; // name is for an abstract unix socket, ie sun_path[0] == 0 thanks to memset sprintf(ps_daemon_address.sun_path+1,"ps_daemon_%s", ps_name); }
void ps_log_hex_dump(const char* function_name, int line_number, char *description, void* address, int count) { ps_log(0, "Hex ps [%s] fn [%s] ln [%d] description [%s]\n", ps_name, function_name, line_number, description); char hex_buffer[16*3+1]; char ascii_buffer[16*2+1]; char *hex_pos=hex_buffer; char *hex_pos_max=hex_buffer+15*3; char *ascii_pos=ascii_buffer; char *c = (char *) address; while (count--) { sprintf(hex_pos,"%.2x ",(unsigned char) *c); if (isprint(*c)) sprintf(ascii_pos,"%c ",*c); else sprintf(ascii_pos,". "); c++; if (hex_pos < hex_pos_max) { hex_pos+=3; ascii_pos+=2; continue; } ps_log(0, "Hex %s- %s\n", hex_buffer, ascii_buffer); hex_pos=hex_buffer; ascii_pos=ascii_buffer; } if (hex_pos != hex_buffer) ps_log(0, "Hex %s - %s\n", hex_buffer, ascii_buffer); }
void ps_daemon_run_program(int fd_listen, int fd_control, char *arguments) { struct sigaction sa_sigchld; // fork a terminal program that creates a pseudoterminal and takes care of running the program int pid_terminal=fork(); if (pid_terminal == -1) ps_log(EXIT_FAILURE, LOG_ERROR("failed to create terminal program - error [%s]"), strerror(errno)); if (pid_terminal == 0) { close(fd_listen); if (ps_safe_to_change_name) { ps_program_name[2]='t'; prctl(PR_SET_NAME, (unsigned long) ps_program_name, 0, 0, 0); } // remove inherited SIGCHLD handler sigemptyset(&sa_sigchld.sa_mask); sa_sigchld.sa_handler = SIG_DFL; sa_sigchld.sa_flags = 0; if (sigaction(SIGCHLD, &sa_sigchld, 0) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("failed to set SIGCHLD handler - error [%s]"), strerror(errno)); ps_terminal_run_program(fd_control, arguments); exit(EXIT_SUCCESS); } // NOTE: the daemon does not wait on pid_terminal }
int ps_terminal_set_user(int uid) { if (getuid() == uid) return 0; struct passwd *password_entry; // a program space can have a completely different rootfs, one in which some // users are not in the passwd file. do not allow these users to enter if ((password_entry= getpwuid(uid)) == 0) { ps_log(0, LOG_ERROR("getpwuid failed - error [%s]"), strerror(errno)); return EXIT_FAILURE; } if (setgid(password_entry->pw_gid)) { ps_log(0, LOG_ERROR("setgid failed - error [%s]"), strerror(errno)); return EXIT_FAILURE; } if (setuid(uid)) { ps_log(0, LOG_ERROR("setuid failed - error [%s]"), strerror(errno)); return EXIT_FAILURE; } // modify environment ps_terminal_set_environment("HOME", password_entry->pw_dir); ps_terminal_set_environment("SHELL", password_entry->pw_shell); ps_terminal_set_environment("USER", password_entry->pw_name); ps_terminal_set_environment("LOGNAME", password_entry->pw_name); return EXIT_SUCCESS; }
int ps_control_send_receive(int size) { int read_count=0; if (ps_fd_control == -1) return -1; if (write(ps_fd_control, ps_buffer, size) == -1) { ps_log(0, LOG_ERROR("failed to send message of type [%c] - error [%s]"), ps_buffer, strerror(errno)); return -1; } while (1) { read_count=read(ps_fd_control, ps_buffer, sizeof(ps_buffer)); if (read_count != -1) break; if (errno == EINTR) continue; ps_log(0, LOG_ERROR("failed to read response - error [%s]"), strerror(errno)); break; } if (ps_buffer[0] == PS_MSG_EXIT_STATUS) { ps_buffer[read_count]=0; ps_log(0, LOG_INFO("received exit status [%s]"), ps_buffer+1); exit(strtol(ps_buffer+1, 0, 10)); } return read_count; }
/* // // Solve for the bound energies given by the potential. // energies is a buffer of energies to test. // bound_energies is where the actual bound energies will be stored. It should be the same size as energies. // both buffers should be of size buf_size. // returns the number of bound energies found, 0 or negative for error // //////////////////////// //Solving the 1D TISE // //////////////////////// // //(0) H * Psi = E * Psi // //E is the eignenvalue //H is the hamiltonian operator: H = T + V = p^2/(2m) + V // ... where p is the momentum operator, p = h/i * Div // //Moving to the effective mass regime we no longer solve for the wavefunction //but instead we sove for an envelope function. Careful consideration shows that //if mass is allowed to vary with positon, m -> m(x), then simple subsitution of //m(x) for m in H causes H to become non-Hermitian. //Fortunately that can be worked around, the result is: // //(1) T * F = -h_bar^2/2 * Div * ( m_eff(x,y,E)^-1 * Div * F ) // ...note: F is the envelope function that is replacing the role of Psi // //Put it all together to get the effective mass equation that we are going to //use: // +--------------------------------------------------------------+ //(2) | -h_bar^2/2 * Div * (1/m_eff * Div * F) + V * F = E * F | // +--------------------------------------------------------------+----> This is the main equation // //Note: Skip to equations (14) & (15) to see how we are going to proceed in the actual solver we are implenting. // //Rearranging (2): //(3) Div * (M * Div * F) = 2*(V-E)*F/h_bar^2 // ... note: Let 1/m_eff(x,y,E) = M (For compactness of these notes only, it is still the effective mass that is position dependant) //take the coordinate system to be cartesisian and Div becomes: Div = d/dx + d/dy --> Div*F = dF/dx + dF/dy //(4) Div * { M(dF/dx) + M(dF/dy) } = 2*(V-E)*F/h_bar^2 // //The LHS of (4) has a (2D) divergance of 2 terms that each have a product of two functions (M, dF), both of which depend on x and y. //The chain rule will get invoked and there will be quite a few terms after we expand this //(5) Div*(M(dF/dx)) + Div*(M(dF/dy)) = ... ...note: I am leaving off the RHS for awhile //(6) (d/dx + d/dy)*(M(dF/dx)) + (d/dx + d/dy)*(M(dF/dy)) = ... //(7) (d/dx)*(M(dF/dx)) + (d/dy)*(M(dF/dx)) + (d/dx)*(M(dF/dy)) + (d/dy)*(M(dF/dy))= ... //(8) (M)(d^2F/dx^2) + (dF/dx)(dM/dx) + (M)(d^2F/(dxdy)) + (dF/dx)(dM/dy) + (M)(d^2F/(dydx)) + (dF/dy)(dM/dx) + (M)(d^2F/dy^2) + (dF/dy)(dM/dy) = ... //(9) (M)(d^2F/dx^2) + (M)(d^2F/dy^2) + 2(M)(d^2F/(dxdy)) + (dF/dx)(dM/dx) + (dF/dx)(dM/dy) + (dF/dy)(dM/dx) + (dF/dy)(dM/dy) = ... // //The next step is to expand (9) out in terms of finite differences, here are some pieces that will be used: //(10) dF/dx = (F[x+dx]-F[x-dx])/(2dx) //(11) d^2F/dx^2 = ((F[x+dx+dx]-F[x+dx-dx])/(2dx) - (F[x-dx+dx]-F[x-dx-dx])/(2dx)) / (2dx) // = (F[x+2dx] - 2F[x] + F[x-2dx])*(2dx)^-2 //(12) d^2F/(dxdy) = (d/dy) * dF/dx // = (d/dy) * (F[x+dx]-F[x-dx])/(2dx) // = ((F[x+dx,y+dy]-F[x-dx,y+dy])/(2dx) - (F[x+dx,y-dy]-F[x-dx,y-dy])/(2dx)) / (2dy) // = ((F[x+dx,y+dy]-F[x-dx,y+dy]) - (F[x+dx,y-dy]-F[x-dx,y-dy])) / (2dx2dy) // //Using the finite differencing versions (10)-(12) of the derivatives in (9) and making M & F explcit functions of x & y: //(9) (M)(d^2F/dx^2) + --> (13) M[x,y] * (F[x+2dx,y] - 2F[x,y] + F[x-2dx,y])*(2dx)^-2 + // (M)(d^2F/dy^2) + --> M[x,y] * (F[x,y+2dy] - 2F[x,y] + F[x,y-2dy])*(2dy)^-2 + // 2(M)(d^2F/(dxdy)) + --> 2*M[x,y] * ((F[x+dx,y+dy]-F[x-dx,y+dy])-(F[x+dx,y-dy]-F[x-dx,y-dy]))/(2dx2dy) + // (dF/dx)(dM/dx) + --> (F[x+dx,y]-F[x-dx,y])/(2dx) * (M[x+dx,y]-M[x-dx,y])/(2dx) + // (dF/dx)(dM/dy) + --> (F[x+dx,y]-F[x-dx,y])/(2dx) * (M[x,y+dy]-M[x,y-dy])/(2dy) + // (dF/dy)(dM/dx) + --> (F[x,y+dy]-F[x,y-dy])/(2dy) * (M[x+dx,y]-M[x-dx,y])/(2dx) + // (dF/dy)(dM/dy) = ... --> (F[x,y+dy]-F[x,y-dy])/(2dy) * (M[x,y+dy]-M[x,y-dy])/(2dy) = 2*(V[x,y]-E)*F[x,y]/h_bar^2 // //The form in (13) can be rearranged so that you can use the shooting method. // //Instead of proceeding directly with that we are going to first write the //orginal 2nd order differential equation (3) as a system of coupled ODEs //(3) Div * (1/m_eff * Div * F) = 2*(V-E)*F/h_bar^2 // //Choose simplifying units, such as: // hbar = 1 // m_electron = 1/2 ...note: 1/m_eff = 1/(m_electron * m_relative) = 2/m_relative // //The equation in (3) becomes simpler: // Div * (1/m_r * Div * F) = (V-E)*F // ...note that m_relative has been shortened to m_r // //Let: //(14) G = (1/m_r) * Div * F //Then (3) becomes: //(15) Div * G = (V-E)*F // //Rearranging (14) and (15) slightly: // +--------------------------------------------------------------+ //(16) | Div*F = G * m_r | //(17) | Div*G = F * (V-E) | // +--------------------------------------------------------------+----> These are the useful equations the solver will implement // //Expanding (16) with finite differencing: // Div*F = G*m_r // = dF/dx + dF/dy = G*m_r //(18) = (F[x+dx,y]-F[x-dx,y])/(2dx) + (F[x,y+dy]-F[x,y-dy])/(2dy) = G[x,y]*m_r[x,y] // //Expanding (17) with finite differencing: // Div*G = F * (V-E) // = dG/dx + dG/dy = F * (V-E) //(19) = (G[x+dx,y]-G[x-dx,y])/(2dx) + (G[x,y+dy]-G[x,y-dy])/(2dy) = F[x,y]*(V[x,y]-E) // // ///////////////////// //Initial Conditons// ///////////////////// // //Take the structure to start in a barrier high enough enough to warrant using: //(20) F[0,0] = 0 // //As for the initial value of G: G is porportional to the slope of F (the envelope function) //solutions for the envelope function will be approx. exponentials inside barrier regions. //Exponentials are fast functions so any reasonable value of G will get the value of F going //to where it is going to converge too. i.e. the overall tragectory will not be sensitive to //the intial value of G if we are starting deep enough inside a tall barrier. // //(21) G[0,0] = 1 // //additional FD notes: ///////////////////////////////////////////////////////////////////////////////////////// //Consider three points on the x axis separated by distance "h" and indexed by "i" ... i.e. i-1, i, i+1 --> x-h, x, x+h //The function F(x) has the values at those positions: F[i-1], F[i], F[i+1] //Taylor expand F(x) at the i-1 and the i+1 point: //(22) F[i-1] = F[i] - dF/dx|i * h + d^2F/dx^2|i * h^2/2! - d^3F/dx^3|i * h^3/3 + ... //(23) F[i+1] = F[i] + dF/dx|i * h + d^2F/dx^2|i * h^2/2! + d^3F/dx^3|i * h^3/3 + ... // ...where dF/dx|i means take the derivative with respect to x at point i //If you add (22) and (23) every other term in the expansions cancel, such that: //(24) F[i-1] + F[i+1] = 2*F[i] + d^2F/dx^2|i * h^2 + d^4F/dx^4|i + ... //Rearrange (24) to put the seconcd derivative of F with respect to x on the LHS //(25) d^2F/dx^2|i = (F[i+1] - 2*F[i] + F[i-1]) / h^2 - d^4F/dx^4|i + ... //Drop the higher order corrections b/c a second order finite differencing approx of d^2F/dx^2|i is all we should need // +----------------------------------------------------------------+ //(26) | d^2F/dx^2|i = (F[i+1] - 2*F[i] + F[i-1]) / h^2 + O(h^2) | // +----------------------------------------------------------------+--------> //The error contained in O(h^2) is of the order h^2 and therefore will be small. //BTW, subtracting (22) and (23) you can rearrange to get an accurate approx for dF/dx|i // +---------------------------------------------------------+ //(27) | dF/dx|i = (F[i+1] - F[i-1]) / (2h) + O(h^2) | // +---------------------------------------------------------+--------> */ PS_LIST ps_solve_1D(PS_DATA potential, PS_DATA effective_mass, PS_SOLVE_PARAMETERS *params) { char log_message[256]; ps_log("PsiShooter -- a shooting method solver for the time independant Schrodinger equation under the effective mass approximation.\n"); ps_log("Iterate through Energy Eigenvalues to find the lowest bound state.\n"); PS_LIST solution_list = ps_list_create(); // This is a linked list for storing solutions // wavefunction storage. int N = potential->xsize; // used for generating strings with sprintf for sending to ps_log // double dx = potential->xstep; //cm, size of differential length (TODO: Compute dx inside loop) double dx = ps_data_dx_at(potential, 2); // in case 0 to 1 is wierd, this will do 1 to 2 //sanity checks, the effective mass should be on the same grid as the potential if(N != effective_mass->xsize) { //problem sprintf(log_message, "\tThat's wierd... there are %d elements in the x axis mesh for the potential, but %d elements in the effective mass x axis mesh. Check to make sure the files for potential and effective mass have the same mesh. \n", N, effective_mass->xsize); ps_log(log_message); return NULL; } if(dx != ps_data_dx_at(effective_mass, 2)) { //more problems sprintf(log_message, "\tThat's wierd... the step size for the potential x axis is %e nm, and the the step size for the effective mass x axis mesh is %e nm. They need the same meshes to work", dx, ps_data_dx_at(effective_mass, 2)); ps_log(log_message); return NULL; } double F[N]; //the envelope function (wavefunction) double F_endpoint[params->n_iter]; // We save the last value of the envelope for each solution double G[N]; //the aux function //F //intial eqn --> Div*F = G*m_r //convert to finite diff eqn --> (F[x+dx,y]-F[x-dx,y])/(2dx) + (F[x,y+dy]-F[x,y-dy])/(2dy) = G[x,y]/M[x,y] //convert to 1D --> (F[x+dx]-F[x-dx])/(2dx) = G[x]/M[x] //rearrange --> F[x+dx] = (2dx)*G[x]/M[x] + F[x-dx] //convert to c style --> F[i+1] = (2dx)*G[i]*m[i] + F[i-1] // F[i+1] = F_coeff*G[i]*m[i] + F[i-1] double F_coeff = 2*dx; //handy prefactor that would otherwise be for every point evaluated //G //intial eqn --> Div*G = F * 2*(V-E)/h_bar^2 //convert to finite diff eqn --> (G[x+dx,y]-G[x-dx,y])/(2dx) + (G[x,y+dy]-G[x,y-dy])/(2dy) = F[x,y]*2*(V[x,y]-E[x,y])/h_bar^2 //convert to 1D --> G[x+dx]-G[x-dx]/(2dx) = F[x]*2*(V[x]-E)/h_bar^2 //rearrange --> G[x+dx] = (2dx)*F[x]*2*(V[x]-E)/h_bar^2 + G[x-dx] //convert to c style --> G[i+1] = 4*dx/hbar^2 * F[i]*(V[i]-E) + G[i-1] // G[i+1] = G_coeff * F[i]*(V[i]-E) + G[i-1] //double G_coeff = 4*dx/(HBAR_PLANCK_SQ); //handy prefactor that would otherwise be computed for every point evaluated double G_coeff = 4*dx*G_COEFF; // Redefined to use M_ELECTRON/HBAR^2 using assuming units of nm and eV int bound_state_count = 0; int i, iter; double E = params->energy_min; double Estep = (params->energy_max - params->energy_min)/(params->n_iter); double V; //eV, Current potential double m_eff; for (iter = 0; iter < params->n_iter; iter++) { //initial conditions F[0] = 0; G[0] = 1; F[1] = F_coeff * G[0] * m_eff + 0; G[1] = G_coeff * F[0] * (V-E) + G[0]; for(i=1; i<N; i++) { V = ps_data_value(potential, 0,i); //V[i] m_eff = ps_data_value(effective_mass, 0,i); //m_eff[i] //Lets eliminate bad solutions by checking if the forward and backwards solutions overlap F[i+1] = F_coeff * G[i] * m_eff + F[i-1]; //subbed in m_eff for m[i], To Do: support a position dependant G[i+1] = G_coeff * F[i] * (V-E) + G[i-1]; // mass by storing different masses at different locations (add to the PS_DATA structure probably) /* //Mix the bidirectional and forward derivatives to prevent two seperate solutions from forming. This //Makes the upper solutions stable and oscillation free. (Probably only required on the i==1 index -jns) // TODO compare results of this branching statement with IF (1==i) ... ELSE ... if (i%2==1){ F[i+1] = F_coeff * G[i] * m_eff + F[i]; //subbed in m_eff for m[i], To Do: support a position dependant // mass by storing different masses at different locations (add to the PS_DATA structure probably) G[i+1] = G_coeff * F[i] * (V-E) + G[i]; } if (i%2==0){ F[i+1] = 2*F_coeff * G[i] * m_eff + F[i-1]; //subbed in m_eff for m[i], To Do: support a position dependant // mass by storing different masses at different locations (add to the PS_DATA structure probably) G[i+1] = 2*G_coeff * F[i] * (V-E) + G[i-1]; } */ } F_endpoint[iter] = F[N-1]; //store the last point of the solution in an array, use this to bracket roots by looking for sign changes (zero crossings) //Try to detect which solutions are eigen states (bound states) if((iter > 0) && ((F_endpoint[iter] > 0 && F_endpoint[iter-1] < 0) || (F_endpoint[iter] < 0 && F_endpoint[iter-1] > 0))) { /* //if there was a change in sign between the last point of the prev and current envelope function then there probably was a zero crossing and there a solution test for a sign crossing //in order to reject solutions that appear to just be amplified/oscillating numerical error run //shoot solutions backwards to see if you get basically the same enevelope function. If they really //are just amplified error then the shots will look like this: // forwards: ----.'.'. increasing amplitude in this direcion--> // backwards: .'.'.---- <--increasing amplitude in this direcion F[N] = 0; G[N] = 1; F[N-1] = F_coeff * G[0] * m_eff + 0; G[N-1] = G_coeff * F[0] * (V-E) + G[0]; //Lets eliminate bad solutions by checking if the forward and backwards solutions overlap for(i=N-1; i>0; i--) { V = ps_data_value(potential, 0,i); //V[i] F[i-1] = F[i+1] - F_coeff * G[i] * m_eff; //subbed in m_eff for m[i], To Do: support a position dependant G[i-1] = G[i+1] + G_coeff * F[i] * (E-V); // mass by storing different masses at different locations (add to the PS_DATA structure probably) } //ToDo: //see if the overlap is about unity. */ // Add the solution to the list of bound states PS_DATA wavefunction = ps_data_copy(potential); // copy the potential to get the x,y coordinate stuff and sizes ps_data_set_data(wavefunction, F); // Overwrite the potential with the wavefunction PS_SOLUTION *solution = (PS_SOLUTION*)malloc(sizeof(PS_SOLUTION)); solution->energy = E; solution->wavefunction = wavefunction; ps_list_add(solution_list, solution); bound_state_count++; // print a log message sprintf(log_message, "\tBoundstate number %d with E=%e found, F[N]=%e\n", bound_state_count, solution->energy, F[N]); ps_log(log_message); } // Consider removing this for speed // sprintf(log_message, "\tE=%g eV\tF[N-1]=%g\n", E, F[N-1]); // ps_log(log_message); E += Estep; // Increment the energy } return solution_list; }
void ps_daemon_main(int fd_initdata) { struct sigaction sa_sigchld, sa_sigterm; int fd; if (ps_safe_to_change_name) { ps_program_name[2]='d'; prctl(PR_SET_NAME, (unsigned long) ps_program_name, 0, 0, 0); } ps_log_stderr_output=0; chdir("/"); umask(0); // close open files for (fd = 0; fd < 256; fd++) if (fd != fd_initdata) close(fd); // sleep(5); /* NOTE: test if controller only returns after daemon up and running */ fd = open("/dev/null", O_RDWR); if (fd != STDIN_FILENO) return; if (dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO) return; if (dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO) return; // NOTE: inherted log already closed.. ps_fd_log=-1; if (strcmp(ps_daemon_logfilename, "none") != 0) ps_log_open(ps_daemon_logfilename); ps_log(0, LOG_INFO("daemon started")); if (read(fd_initdata, &ps_pid, sizeof(ps_pid)) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("did not receive daemon pid - error [%s]"), strerror(errno)); sigemptyset(&sa_sigchld.sa_mask); sa_sigchld.sa_handler = &ps_daemon_sigchld_handler; sa_sigchld.sa_flags = SA_RESTART | SA_NOCLDSTOP; if (sigaction(SIGCHLD, &sa_sigchld, 0) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("failed to set SIGCHLD handler - error [%s]"), strerror(errno)); sigemptyset(&sa_sigterm.sa_mask); sa_sigterm.sa_handler = &ps_daemon_sigterm_handler; sa_sigterm.sa_flags = 0; if (sigaction(SIGTERM, &sa_sigterm, 0) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("failed to set SIGTERM handler - error [%s]"), strerror(errno)); // change hostname snprintf(ps_buffer,sizeof(ps_buffer)-1,"ps_%s", ps_name); ps_buffer[sizeof(ps_buffer)-1]=0; ps_log(0, LOG_INFO("setting hostname to [%s]"), ps_buffer); if (sethostname(ps_buffer, strlen(ps_buffer)) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("failed to change hostname - error [%s]"), strerror(errno)); ps_daemon_io_loop(fd_initdata); ps_log(0, LOG_INFO("daemon stopped")); }
void ps_daemon_io_loop(int fd_initdata) { int fd_listen, fd_control, read_count; // open listening socket if ((fd_listen=socket(AF_UNIX, SOCK_SEQPACKET, 0)) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("failed to create socket - error [%s]"), strerror(errno)); if (bind(fd_listen, (struct sockaddr *) &ps_daemon_address, sizeof(ps_daemon_address)) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("failed to bind socket - error [%s]"), strerror(errno)); if (listen(fd_listen, 5) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("failed to listen on socket - error [%s]"), strerror(errno)); // send ps_pid to process that ceated the daemon if (write(fd_initdata, &ps_pid, sizeof(ps_pid)) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("failed to send ps_pid to controler - error [%s]"), strerror(errno)); close(fd_initdata); while (ps_daemon_run) { fd_control=accept(fd_listen, 0, 0); if (fd_control == -1) { if (errno == EINTR) continue; ps_log(EXIT_FAILURE, LOG_ERROR("failed to accept controller connection - error [%s]"), strerror(errno)); } while ((read_count = read(fd_control, ps_buffer, sizeof(ps_buffer)))) { if (read_count == -1) { if (errno == EINTR) continue; ps_log(0, LOG_INFO("controller disconnected - error [%s]"), strerror(errno)); break; } // process control messages if (ps_buffer[0] == PS_MSG_RUN_PROGRAM) { ps_daemon_run_program(fd_listen, fd_control, ps_buffer+1); break; } if (ps_buffer[0] == PS_MSG_GET_PID) { sprintf(ps_buffer+1,"%d", ps_pid); if (write(fd_control, ps_buffer, strlen(ps_buffer)+1) == -1) ps_log(0, LOG_ERROR("failed to send PID to controller - error [%s]"), strerror(errno)); break; } if (ps_buffer[0] == PS_MSG_CHANGE_WORKINGDIR) { ps_buffer[0]= PS_MSG_EXIT_STATUS; if (chdir(ps_buffer+1) == -1) { ps_log(0, LOG_ERROR("failed to change working dir to [%s] - error [%s]"), ps_buffer+1, strerror(errno)); sprintf(ps_buffer+1,"%d", EXIT_FAILURE); } else sprintf(ps_buffer+1,"%d", EXIT_SUCCESS); if (write(fd_control, ps_buffer, strlen(ps_buffer)+1) == -1) ps_log(0, LOG_ERROR("failed to send resultcode of CWD to controller - error [%s]"), strerror(errno)); break; } if (ps_buffer[0] == PS_MSG_UNSHARE_NETWORK) { ps_buffer[0] = PS_MSG_EXIT_STATUS; if (ps_daemon_network_changed) { ps_log(0, LOG_ERROR("network already unshared")); sprintf(ps_buffer+1,"%d", EXIT_FAILURE); } else { if (unshare(CLONE_NEWNET) == -1) { ps_log(0, LOG_ERROR("failed to unshare network - error [%s]"), strerror(errno)); sprintf(ps_buffer+1,"%d", EXIT_FAILURE); } else { ps_daemon_network_changed=1; sprintf(ps_buffer+1,"%d", EXIT_SUCCESS); } } if (write(fd_control, ps_buffer, strlen(ps_buffer)+1) == -1) ps_log(0, LOG_ERROR("failed to sent resultcode of UNSHARE NETWORK to controller - error [%s]"), strerror(errno)); break; } if (ps_buffer[0] == PS_MSG_UNSHARE_IPC) { ps_buffer[0] = PS_MSG_EXIT_STATUS; if (ps_daemon_ipc_changed) { ps_log(0, LOG_ERROR("ipc already unshared")); sprintf(ps_buffer+1,"%d", EXIT_FAILURE); } else { if (unshare(CLONE_NEWIPC) == -1) { ps_log(0, LOG_ERROR("failed to unshare ipc - error [%s]"), strerror(errno)); sprintf(ps_buffer+1,"%d", EXIT_FAILURE); } else { ps_daemon_ipc_changed=1; sprintf(ps_buffer+1,"%d", EXIT_SUCCESS); } } if (write(fd_control, ps_buffer, strlen(ps_buffer)+1) == -1) ps_log(0, LOG_ERROR("failed to sent resultcode of UNSHARE IPC to controller - error [%s]"), strerror(errno)); break; } if (ps_buffer[0] == PS_MSG_CHANGE_ROOTFS) { ps_buffer[0] = PS_MSG_EXIT_STATUS; sprintf(ps_buffer+1,"%d", ps_daemon_change_rootfs(ps_buffer+1)); if (write(fd_control, ps_buffer, strlen(ps_buffer)+1) == -1) ps_log(0, LOG_ERROR("failed to sent resultcode of CHROOTFS to controller - error [%s]"), strerror(errno)); break; } } close(fd_control); } }
int ps_daemon_change_rootfs(char *newroot) { ps_log(0, LOG_INFO("change root dir to [%s]"), newroot); if (ps_daemon_rootfs_changed) { ps_log(0, LOG_ERROR("rootfs already changed!")); return EXIT_FAILURE; } if (chdir(newroot) == -1) { ps_log(0, LOG_ERROR("failed to change rootdir to [%s] - error [%s]"), newroot, strerror(errno)); return EXIT_FAILURE; } // create a directory where pivot_root can attach us_root if (mkdir("./us_rootfs", 0755) == -1) { if (errno != EEXIST) { ps_log(0, LOG_ERROR("failed to create directory /us_rootfs - error [%s]"), strerror(errno)); return EXIT_FAILURE; } } if (unshare(CLONE_NEWNS) == -1) { ps_log(0, LOG_ERROR("unable to unshare mount namespace - error [%s]"), strerror(errno)); return EXIT_FAILURE; } if (pivot_root(".", "./us_rootfs") == -1) { ps_log(0, LOG_ERROR("pivot_root failed - error [%s]"), strerror(errno)); return EXIT_FAILURE; } // unmount user space rootfs if (mount("", "/us_rootfs", "none", MS_REC | MS_PRIVATE, "") == -1) { ps_log(0, LOG_ERROR("failed to re-mount /us_rootfs as private - error [%s]"), strerror(errno)); return EXIT_FAILURE; } if (umount2("/us_rootfs", MNT_DETACH) == -1) { ps_log(0, LOG_ERROR("failed to unmount /us_rootfs - error [%s]"), strerror(errno)); return EXIT_FAILURE; } if (rmdir("/us_rootfs") == -1) ps_log(0, LOG_ERROR("failed to remove directory /us_rootfs - error [%s]"), strerror(errno)); if (chdir("/") == -1) { ps_log(0, LOG_ERROR("failed to change to / - error [%s]"), strerror(errno)); return EXIT_FAILURE; } if (mkdir("/proc", 0755) == -1); if (errno != EEXIST) { ps_log(0, LOG_ERROR("failed to create /proc directory - error [%s]"), strerror(errno)); return EXIT_FAILURE; } if (mount("", "/proc","proc", MS_NODEV | MS_NOEXEC | MS_NOSUID,"") == -1) { ps_log(0, LOG_ERROR("failed to re-mount /proc - error [%s]"), strerror(errno)); return EXIT_FAILURE; } if (mkdir("/dev", 0755) == -1); if (errno != EEXIST) { ps_log(0, LOG_ERROR("failed to create /dev directory - error [%s]"), strerror(errno)); return EXIT_FAILURE; } if (mkdir("/dev/pts", 0755) == -1); if (errno != EEXIST) { ps_log(0, LOG_ERROR("failed to create /dev/pts directory - error [%s]"), strerror(errno)); return EXIT_FAILURE; } if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL , "newinstance,ptmxmode=0666") == -1) { ps_log(0, LOG_ERROR("unable to mount /dev/pts - error [%s]"), strerror(errno)); return EXIT_FAILURE; } if (access("/dev/ptmx", F_OK) == -1) { if (symlink("/dev/pts/ptmx", "/dev/ptmx") == -1) ps_log(0, LOG_ERROR("unable to create /dev/ptmx symlink - error [%s]"), strerror(errno)); } ps_daemon_rootfs_changed=1; return EXIT_SUCCESS; }
void ps_terminal_run_program(int fd_control, char *arguments) { int fd_master, pid_program, exit_status; socklen_t sizeof_credentials; struct ucred credentials; // run the program under the uid of the user that connected to the server sizeof_credentials = sizeof(credentials); if(getsockopt(fd_control, SOL_SOCKET, SO_PEERCRED, &credentials, &sizeof_credentials) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("failed to get uid of controlling user - error [%s]"), strerror(errno)); if (ps_terminal_set_user(credentials.uid) == EXIT_FAILURE) { ps_terminal_send_exitcode(fd_control, EXIT_FAILURE); return; } // create a pseudoterminal fd_master = posix_openpt(O_RDWR | O_NOCTTY); if (fd_master == -1) ps_log(EXIT_FAILURE, LOG_ERROR("posix_openpt() failed -error [%s]"), strerror(errno)); if (grantpt(fd_master) == -1) ps_log(0 /*EXIT_FAILURE*/, LOG_ERROR("grantpt() failed - error [%s]"), strerror(errno)); if (unlockpt(fd_master) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("unlockpt() failed - error [%s]"), strerror(errno)); // fork a new process to run the program pid_program=fork(); if (pid_program == -1) ps_log(EXIT_FAILURE, LOG_ERROR("unable to fork - error [%s]"), strerror(errno)); if (pid_program == 0) { close(fd_control); ps_program_exec(fd_master, arguments); ps_log(EXIT_FAILURE, LOG_ERROR("trespassing error!")); } // TEST for a problem with bash. It seems that bash disables cntl-d (eof) handling // in the pseudo terminal if there is input before it outputs its prompt. This requires // us to use the exit statement in a script that is inside a here-document. The sh shell // does not have this behaviour. Needs further investigation... //sleep(1); ps_terminal_io_loop(fd_control, fd_master); if (waitpid(pid_program, &exit_status, 0) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("waitpid failed - error [%s]"), strerror(errno)); // return status to controller ps_log(0, LOG_INFO("after wait - exit_status [%d]"), exit_status); ps_terminal_send_exitcode(fd_control, exit_status); close(fd_master); close(fd_control); }
void ps_control_io_loop() { // read from STDIN -> fd_control // read from fd_control -> STDOUT // stop if fd_control closed fd_set fdset; int read_count, write_count, count, stdin_closed; stdin_closed=0; while (1) { FD_ZERO(&fdset); FD_SET(ps_fd_control, &fdset); if (!stdin_closed) FD_SET(STDIN_FILENO, &fdset); if (select(ps_fd_control+1, &fdset, 0,0,0) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("select failed - error [%s]"), strerror(errno)); memset(ps_buffer,0,sizeof(ps_buffer)); if (FD_ISSET(ps_fd_control, &fdset)) { read_count=read(ps_fd_control, ps_buffer, sizeof(ps_buffer)); if (read_count == 0) // EOF break; if (read_count == -1) { if (errno == EINTR) continue; ps_log(0, LOG_ERROR("failed to read from control socket - error [%s]"), strerror(errno)); break; } if (ps_buffer[0] == PS_MSG_EXIT_STATUS) { ps_buffer[read_count]=0; ps_log(0, LOG_INFO("received exit status [%s]"), ps_buffer+1); exit(strtol(ps_buffer+1, 0, 10)); } if (ps_buffer[0] == PS_MSG_GET_PID) { ps_log(0, LOG_INFO("received pid [%s]"), ps_buffer+1); write(STDOUT_FILENO, ps_buffer+1, strlen(ps_buffer+1)); write(STDOUT_FILENO, "\n", 1); exit(EXIT_SUCCESS); } write_count=1; while (write_count != read_count) { count=write(STDOUT_FILENO, ps_buffer+write_count, read_count-write_count); if (count == 0) continue; if (count == -1) { if (errno == EINTR) continue; ps_log(0, LOG_ERROR("failed to write to stdout - error [%s]"), strerror(errno)); break; } write_count+=count; } } if (FD_ISSET(STDIN_FILENO, &fdset)) { ps_buffer[0]=PS_MSG_DATA; read_count=read(STDIN_FILENO, ps_buffer+1, sizeof(ps_buffer)-1); if (read_count == 0) // EOF { stdin_closed=1; // send cntrl-d to the program space terminal ps_buffer[0]=PS_MSG_DATA; ps_buffer[1]=4; if (write(ps_fd_control, ps_buffer, 2) == -1) ps_log(0, LOG_ERROR("failed to write cntrl-d to pst - error [%s]"), strerror(errno)); continue; } if (read_count == -1) { if (errno == EINTR) continue; ps_log(EXIT_FAILURE, LOG_ERROR("failed to read from terminal stdin - error [%s]"), strerror(errno)); } read_count++; write_count=0; while (write_count != read_count) { count=write(ps_fd_control, ps_buffer+write_count, read_count-write_count); //LOG_BUFFER_HEX("sending data", ps_buffer, count); if (count == 0) continue; if (count == -1) { if (errno == EINTR) continue; ps_log(EXIT_FAILURE, LOG_ERROR("failed to write to control socket - error [%s]"), strerror(errno)); } write_count+=count; } } } }
void ps_terminal_io_loop(int fd_control, int fd_master) { fd_set fdset; int fd_max, read_count, write_count, count; ps_buffer[0]=PS_MSG_DATA; fd_max=(fd_control > fd_master) ? fd_control : fd_master; while (1) { FD_ZERO(&fdset); FD_SET(fd_control, &fdset); FD_SET(fd_master, &fdset); if (select(fd_max+1, &fdset, 0, 0, 0) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("select failed - error [%s]"), strerror(errno)); // handle data comming from pseudo terminal if (FD_ISSET(fd_master, &fdset)) { ps_buffer[0]=PS_MSG_DATA; read_count=read(fd_master, ps_buffer+1, sizeof(ps_buffer)-1); if (read_count == 0) { ps_log(0, LOG_INFO("fd_master closed")); break; } if (read_count == -1) { if (errno == EINTR) continue; if (errno == EIO) { // not an error, program running in terminal has stopped ps_log(0, LOG_INFO("got EIO")); break; } ps_log(EXIT_FAILURE, LOG_ERROR("failed to read from terminal - error [%s]"), strerror(errno)); } count=read_count+1; while (1) { write_count=write(fd_control, ps_buffer, count); if (write_count == 0) continue; if (write_count == -1) { if (errno == EINTR) continue; ps_log(EXIT_FAILURE, LOG_ERROR("failed to write to control socket - error [%s]"), strerror(errno)); } if (write_count != count) // write must be atomic ps_log(EXIT_FAILURE, LOG_ERROR("partial write to control socket")); break; } } // handle data comming from users terminal if (FD_ISSET(fd_control, &fdset)) { read_count=read(fd_control, ps_buffer, sizeof(ps_buffer)); if (read_count == 0) break; if (read_count == -1) { if (errno == EINTR) continue; ps_log(EXIT_FAILURE, LOG_ERROR("failed to read from control socket - error [%s]"), strerror(errno)); } // TODO check for control messages, eg change terminal attributes // for now assume only data messages write_count=1; while (write_count != read_count) { count=write(fd_master, ps_buffer+write_count, read_count-write_count); //LOG_BUFFER_HEX("write to terminal", ps_buffer+write_count, count); if (count == 0) continue; if (count == -1) { if (errno == EINTR) continue; ps_log(EXIT_FAILURE, LOG_ERROR("failed to write to terminal - error [%s]"), strerror(errno)); } write_count+=count; } } } }
void ps_program_exec(int fd_master, char *arguments) { struct winsize windowsize; char *argv[64]; char *p; int i, n, fd_slave; if (setsid() == -1) ps_log(EXIT_FAILURE, LOG_ERROR("setsid failed - error [%s]"), strerror(errno)); fd_slave=open(ptsname(fd_master), O_RDWR); if (fd_slave == -1) ps_log(EXIT_FAILURE, LOG_ERROR("unable to open slave with name [%s] - error [%s]"), ptsname(fd_master), strerror(errno)); ps_log(0, LOG_INFO("fd_master [%d] fd_slave [%d] ptsname [%s]"), fd_master, fd_slave, ptsname(fd_master)); if (dup2(fd_slave, STDIN_FILENO) != STDIN_FILENO) ps_log(EXIT_FAILURE, LOG_ERROR("failed to set STDIN_FILENO - error [%s]"), strerror(errno)); if (dup2(fd_slave, STDOUT_FILENO) != STDOUT_FILENO) ps_log(EXIT_FAILURE, LOG_ERROR("failed to set STDOUT_FILENO - error [%s]"), strerror(errno)); if (dup2(fd_slave, STDERR_FILENO) != STDERR_FILENO) ps_log(EXIT_FAILURE, LOG_ERROR("failed to set STDERR_FILENO - error [%s]"), strerror(errno)); if (fd_slave > STDERR_FILENO) close(fd_slave); close(fd_master); // get terminal columns and rows memset(&windowsize, 0, sizeof(windowsize)); p=arguments; windowsize.ws_col=atoi(p); p+=strlen(p)+1; windowsize.ws_row=atoi(p); p+=strlen(p)+1; if (ioctl(STDOUT_FILENO, TIOCSWINSZ, &windowsize) == -1) ps_log(0, LOG_INFO("failed to set window size to w [%d] h [%d] - error [%s]"), windowsize.ws_col, windowsize.ws_row, strerror(errno)); // program arguments n=atoi(p); p+=strlen(p)+1; for (i=0; i < n; i++) { argv[i]=p; p+=strlen(p)+1; } argv[i]=0; execvp(argv[0], argv); // this code only executes if execvp failes ps_log(EXIT_FAILURE, LOG_ERROR("failed to run program [%s] - error [%s]"), argv[0], strerror(errno)); }
/* // //The 2D version of the solving engine. // //intial eqn //--> Div*F = G/M // //convert to finite diff eqn, use a uniform mesh, Let, dx = dy = d and Let P[x,y] = G[x,y]/M[x,y] = G*m //--> (F[x+d,y]-2F[x,y]+F[x-d,y])/d^2 + (F[x,y+d]-2F[x,y]+F[x,y-d])/d^2 = P[x,y] // //rearrange: //--> F[x+d,y] + F[x-d,y] + F[x,y+d] + F[x,y-d] - 4F[x,y] = d^2 * P[x,y] // //convert to c style: Let x = x0+j*d and y = y0+l*d // where j = 0,1,2...J and l = 0,1,2...L //--> F[j+1,l] + F[j-1,l] + F[j,l+1] + F[j,l-1] - 4F[j,l] = d^2 * P[j,l]y // //Goal: make a linear system of eqns in matrix form -- firstly we make a vector out of F. i.e. map j,l to a linear index 'i' // Let, i = j(L+1) + l ...where j = 0,1,...J and l = 0,1,...L //--> F[i+L+1] + F[i-(L+1)] + F[i+1] + F[i-1] - 4F[i] = d^2 * P[i] // ...where this eqn holds for the interior points: j = 1,2,...,J and l = 1,2,...,L // //On the boundries F should be specified, i.e. where: // j = 0 or i = 0, 1, 2, ..,L // j = J or i = J(L+1), J(L+1)+1, J(L+1)+2, ...,J(L+1)+L // l = 0 or i = 0, (L+1), 2(L+1), ..., J(L+1) // l = L or i = L, (L+1)+L, 2(L+1)+L, ..., J(L+1)+L */ PS_LIST ps_solve_2D(PS_DATA potential, PS_SOLVE_PARAMETERS *params) { char log_message[256]; ps_log("PsiShooter -- a shooting method solver for the time independant Schrodinger equation under the effective mass approximation.\n"); // This is a linked list for storing solutions PS_LIST solution_list = ps_list_create(); ps_log("Iterate through Energy Eigenvalues to find the lowest bound state.\n"); // wavefunction storage. int Nx = potential->xsize; // used for generating strings with sprintf for sending to ps_log int Ny = potential->ysize; // used for generating strings with sprintf for sending to ps_log // double dx = potential->xstep; //cm, size of differential length //(TODO: Compute dx inside loop in order to support meshes with non-uniform differential steps) double dx = ps_data_dx_at(potential, 2); double dy = ps_data_dy_at(potential, 2); // 0 to 1 is wierd, maybe. double dx_dy = dx/dy; double dy_dx = dy/dx; //F //intial eqn --> Div*F = G * m_eff //convert to finite diff eqn --> (F[x+dx,y]-F[x,y])/dx + (F[x,y]-F[x,y-dy])/dy = G[x,y]M[x,y] //rearrange --> F[x+dx,y]-F[x,y] + dx*(F[x,y]-F[x,y-dy])/dy = dx*G[x,y]/M[x,y] // --> F[x+dx,y] = dx*G[x,y]/M[x,y]+F[x,y]-dx/dy*(F[x,y]-F[x,y-dy]) // What does this mean for our 2D simulations? The more closely spaced the y // Coordinate mesh points are, the more significant their effects will be. That // Is pretty terrible for us. // // We need to decouple the coordinates so we don't need to know future F and G from // from future calculated y mesh points... // Is there some other way we can decouple them? We can't just look back instead of forward. // // How about we fill the array with 1D shots across the 1 direction, and then refill // with the 2D shots? Then the array will have some approximate knowledge of the future // and the algorithm might work. //convert to c style --> F[x+dx,y] = F[i][j+1] // *****README******* --> (NOTE: x is iterated over with j index. x=columns, i=rows) -jns //in 2D --> F[i][j+1] = dx*G[i][j]/M[i][j] + F[i][j] - dx/dy*(F[i][j]-F[i-1][j]) //convert to 1D --> (F[x+dx]-F[x-dx])/(2dx) = G[x]/M[x] //rearrange --> F[x+dx] = (2dx)*G[x]/M[x] + F[x-dx] //convert to c style --> F[i+1] = (2dx)*G[i]*m[i] + F[i-1] // F[i+1] = F_coeff*G[i]*m[i] + F[i-1] double F_coeff = dx; //handy prefactor that would otherwise be for every point evaluated //from dx to 2*dx jh sometime in may //G //intial eqn --> Div*G = F * 2*(V-E)/h_bar^2 //convert to finite diff eqn --> (G[x+dx,y]-G[x-dx,y])/(2dx) + (G[x,y+dy]-G[x,y-dy])/(2dy) = F[x,y]*2*(V[x,y]-E[x,y])/h_bar^2 //in 2d: --> G[x+dx,y] = (2dx)*F[x,y]*2*(V[x,y]-e[x,y])/h_bar^2+G[x-dx][y]-(2dx)/(2dy)(G[x,y+dy]-G[x,y-dy]) // --> G[i][j+1] = G_coeff * F[i][j]*(V[i][j]-E) + G[i][j-1] - dx/dy(G[i+1][j] + G[i-1][j]) // // The equivalent FWD DIFFEQ --> G[x+dx][y] = dx*F[x,y]*2*(V[x,y] - e[x,y])/h_bar^2 + G[x,y] - dx/dy(G[x,y] - G[x,y-dy]) // --> G[i][j+1] = dx*F[i][j]*2*(V[i][j] - e[i][j])/h_bar^2 + G[i][j] - dx/dy(G[i][j] - G[i-1][j]) //convert to 1D --> G[x+dx]-G[x-dx]/(2dx) = F[x]*2*(V[x]-E)/h_bar^2 //rearrange --> G[x+dx] = (2dx)*F[x]*2*(V[x]-E)/h_bar^2 + G[x-dx] //convert to c style --> G[i+1] = 4*dx/hbar^2 * F[i]*(V[i]-E) + G[i-1] // G[i+1] = G_coeff * F[i]*(V[i]-E) + G[i-1] // double G_coeff = 2*dx/(HBAR_PLANCK_SQ); //handy prefactor that would otherwise be computed for every point evaluated //from 4*dx to 2*dx jh sometime in may double G_coeff = 2*dx*G_COEFF; //dx = dy here. double F[Nx][Ny]; //the envelope function (wavefunction) double f_cache[params->n_iter]; // We cache the last value of the envelope for each solution double G[Nx][Ny]; //the aux function int bound_state_count = 0; int threshold_set_flag = 0; double F_threshold = 0; int i, j, iter; double E = params->energy_min; double Estep = (params->energy_max - params->energy_min)/(params->n_iter); double V; //meV, Current potential // double m_eff = MASS_ELECTRON*M_EFF_GAAS; double m_eff = M_EFF_GAAS; // To Do: make the electron mass be part of the structure that we are simulating. i.e. //in general it can be a position dependant quantity just like the potential //(think heterostructures with different band edge curvatures) for (iter = 0; iter < params->n_iter; iter++) { //Going to try filling the array with y-direction shots and then running the 2D shots based on those. //initial conditions for (j=0; j<Nx; j++){ F[0][j] = 0; G[0][j] = 1; F[1][j] = 1; G[1][j] = 1; } for(i=1; i<Ny-1; i++) { for(j=1; j<Nx-1; j++) { V = ps_data_value(potential, i,j); //V[i][j] // 5-point stencil in X and Y F[i+1][j] = dx*dx*m_eff*G[i][j] - F[i][j+1] - F[i][j-1] - F[i-1][j] + 4*F[i][j]; G[i+1][j] = 2*dx*dx*G_COEFF*(V-E)*F[i][j] - G[i][j+1] - G[i][j-1] - G[i-1][j] + 4*G[i][j]; } // For First and last point, Compute slope in x direction for F and G directly // F[x+3] = F[x] + 3h*F'[x] + (3h)^2/2!*F''[x] (Taylor Expansion) // F'[x] = 1/(12*h)*[-F[x+2] + 8*F[x+1] - 8*F[x-1] + F[x-2]] (5-point stencil) // F''[x] = 1/(12*h*h)*[-F[x+2] + 16*F[x+1] -30*F[x] +16*F[x+1] - F[x-2]] (5-point stencil) G[i+1][j] = G[i+1][j-3] + 0.25*(-G[i+1][j-1] + 8*G[i+1][j-2] - 8*G[i+1][j-4] + G[i+1][j-5]) + 9.0/24.0*(-G[i+1][j-5] + 16*G[i+1][j-4] - 30*G[i+1][j-3] + 16*G[i+1][j-2] - G[i+1][j-1]); F[i+1][j] = F[i+1][j-3] + 0.25*(-F[i+1][j-1] + 8*F[i+1][j-2] - 8*F[i+1][j-4] + F[i+1][j-5]) + 9.0/24.0*(-F[i+1][j-5] + 16*F[i+1][j-4] - 30*F[i+1][j-3] + 16*F[i+1][j-2] - F[i+1][j-1]); // F[x-3] = F[x] - 3h*F'[x] + (3h)^2/2!*F''[x] (Taylor Expansion) // F'[x] = 1/(12*h)*[-F[x+2] + 8*F[x+1] - 8*F[x-1] + F[x-2]] // F''[x] = 1/(12*h*h)*[-F[x+2] + 16*F[x+1] -30*F[x] +16*F[x+1] - F[x-2]] G[i+1][0] = G[i+1][3] - 0.25*(-G[i+1][5] + 8*G[i+1][4] - 8*G[i+1][2] + G[i+1][1]) + 9.0/24.0*(-G[i+1][5] + 16*G[i+1][4] - 30*G[i+1][3] + 16*G[i+1][2] - G[i+1][1]); F[i+1][0] = F[i+1][3] - 0.25*(-F[i+1][5] + 8*F[i+1][4] - 8*F[i+1][2] + F[i+1][1]) + 9.0/24.0*(-F[i+1][5] + 16*F[i+1][4] - 30*F[i+1][3] + 16*F[i+1][2] - F[i+1][1]); } //Why not just look at the change on the very last point? This definitely won't be representative, but it //might be useful during debugging. // It needs to check the entire boundary. (jns) f_cache[iter] = F[Nx-1][Ny-1]; // Consider removing this for speed // sprintf(log_message, "\tE=%g eV\tF[N-1]=%g\n", E/EV_TO_ERGS, F[N-1]); // ps_log(log_message); //Try to detect which solutions are eigen states (bound states) //if((iter > 0) && ((f_cache[iter] > 0 && f_cache[iter-1] < 0) || (f_cache[iter] < 0 && f_cache[iter-1] > 0))) { //if there was a change in sign between the last point of the prev // and current envelope function then there was a zero crossing and there a solution // test for a sign crossing PS_DATA wavefunction = ps_data_copy(potential); // copy the potential ps_data_set_data(wavefunction, (double*)F); // Overwrite the potential with the wavefunction PS_SOLUTION *solution = (PS_SOLUTION*)malloc(sizeof(PS_SOLUTION)); solution->energy = E; solution->wavefunction = wavefunction; // Add the solution to the list of bound states ps_list_add(solution_list, solution); // Save the g solutions PS_DATA g = ps_data_copy(potential); ps_data_set_data(g, (double*)G); PS_SOLUTION *gsolution = (PS_SOLUTION*)malloc(sizeof(PS_SOLUTION)); gsolution->energy = E; gsolution->wavefunction = g; ps_list_add(g_solutions, gsolution); // print a log message sprintf(log_message, "\tBoundstate number %d with E=%e found, F[Nx][Ny]=%e < F_threshold=%e\n", ++bound_state_count, solution->energy/EV_TO_ERGS, F[Nx][Ny], F_threshold); ps_log(log_message); //} // Increment the energy E += Estep; } return solution_list; }
void ps_control_save_terminal_attributes(void) { if (tcgetattr(STDIN_FILENO, &ps_saved_terminal_attributes) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("unable to save terminal attributes - error [%s]"), strerror(errno)); }
int main(int argc, char *argv[]) { ps_program_name=argv[0]; ps_control_open_logfile(); if (argc == 2) if ( (strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) { printf("%s", ps_control_options); return EXIT_SUCCESS; } if (argc < 3) ps_log(EXIT_FAILURE, LOG_ERROR("too few parameters")); ps_init(); ps_set_name(argv[1]); ps_control_check_input(argv[2], argc-3); ps_log(0, LOG_INFO("creating controller")); if (strcmp(argv[2],"--create") == 0) { ps_control_prepare_daemon_logfile((argc == 4) ? argv[3] : "none"); ps_control_create_daemon(); } else { ps_control_connect_daemon(); if (strcmp(argv[2],"--pid") == 0) { ps_pid=ps_control_get_daemon_pid(); printf("%d\n",(ps_pid == -1) ? 0 : ps_pid); if (ps_pid == -1) ps_log(EXIT_FAILURE, LOG_ERROR("--pid: failed to receive daemon PID")); } if (strcmp(argv[2],"--kill") == 0) { ps_pid=ps_control_get_daemon_pid(); if (ps_pid <= 1) ps_log(EXIT_FAILURE, LOG_ERROR("--kill : could not determine daemon PID")); if (kill(ps_pid, SIGTERM) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("--kill : failed to kill daemon - error [%s]"), strerror(errno)); } if (ps_fd_control == -1) return EXIT_FAILURE; if (strcmp(argv[2],"--net") == 0) ps_control_unshare_network(); if (strcmp(argv[2],"--ipc") == 0) ps_control_unshare_ipc(); if (strcmp(argv[2],"--chrootfs") == 0) ps_control_change_rootfs(argv[3]); if (strcmp(argv[2],"--cwd") == 0) ps_control_change_workingdir(argv[3]); if (strcmp(argv[2],"--run") == 0) { if (isatty(STDIN_FILENO)) { ps_control_save_terminal_attributes(); atexit(ps_control_restore_terminal_attributes); ps_control_set_terminal_raw_mode(); } ps_control_run_program(argc-3, argv+3); } } ps_log(0, LOG_INFO("closing controller")); return EXIT_SUCCESS; }
void ps_control_restore_terminal_attributes(void) { if (tcsetattr(STDIN_FILENO, TCSANOW, &ps_saved_terminal_attributes) == -1) ps_log(0, LOG_ERROR("unable to restore terminal attributes - error [%s]"), strerror(errno)); }
// // PsiShooter program entry point int main(int argc, char **argv) { char msg[256]; PS_DATA potential; PS_DATA effective_mass; int solver_dimension; PS_SOLUTION *s; if (1 == argc) { solver_dimension = 1; sprintf(msg, "No file specified. Using builtin potential.\n"); ps_log(msg); //get a 1D test potential potential = test_potential_2D(); FILE *f = fopen("V_2d.dat", "w"); ps_data_write_bin(potential, f); fclose(f); } else if (3 == argc) { solver_dimension = 1; // Interpret argument as file to process FILE *infile_potential = fopen(argv[1], "r"); if (infile_potential == NULL) { sprintf(msg, "Error opening file '%s'\n", argv[1]); ps_log(msg); return PS_ERROR_FILE_NOT_FOUND; // Exit abnormally } else { sprintf(msg, "Using potential from file '%s'\n", argv[1]); ps_log(msg); potential = ps_data_read_bin(infile_potential); fclose(infile_potential); } FILE *infile_mass = fopen(argv[2], "r"); if (infile_mass == NULL) { sprintf(msg, "Error opening file '%s'\n", argv[2]); ps_log(msg); return PS_ERROR_FILE_NOT_FOUND; // Exit abnormally } else { sprintf(msg, "Using effective mass from file '%s'\n", argv[2]); ps_log(msg); effective_mass = ps_data_read_bin(infile_mass); fclose(infile_mass); solver_dimension = 1; } } else if (4 == argc) { // lets say that if there is a 4th argument, it is a 2d request. // Interpret argument as file to process FILE *infile = fopen(argv[1], "r"); if (infile == NULL) { sprintf(msg, "Error opening file '%s'\n", argv[1]); ps_log(msg); return PS_ERROR_FILE_NOT_FOUND; // Exit abnormally } else { sprintf(msg, "Using *2D* potential from file '%s'\n", argv[1]); ps_log(msg); potential = ps_data_read_bin(infile); fclose(infile); solver_dimension = 2; } } else { //unrecognized combination of arguements. Show usage. sprintf(msg, "Arguements not understood. Usage:\npsi_shooter potential_file.in effective_mass_file.in\n"); ps_log(msg); } // Setup solution parameters PS_SOLVE_PARAMETERS params; params.energy_min = ps_data_min_value(potential); params.energy_max = ps_data_max_value(potential); params.n_iter = 100; // The number of energies to try double e_step = (params.energy_max - params.energy_min)/(params.n_iter); sprintf(msg,"Testing energies from %g to %g in %g increments\n", params.energy_min/EV_TO_ERGS, params.energy_max/EV_TO_ERGS, e_step/EV_TO_ERGS); ps_log(msg); // Create a list for solutions PS_LIST solutions = ps_list_create(); g_solutions = ps_list_create(); // 1st pass coarse Solver if (1 == solver_dimension) { // 1d solver with coarse/fine pass PS_LIST coarse_solutions = ps_solve_1D(potential, effective_mass, ¶ms); // For each solution, do a second pass with finer grained energy steps s = ps_list_front(coarse_solutions); while (s != NULL) { // I know that ps_solve_1d looks for a sign crossing as it increases // the test energy E and saves the solution for the larger energy params.energy_min = s->energy - e_step; params.energy_max = s->energy; params.n_iter = 100; // Add the fine grain solutions to the final list PS_LIST e_solutions = ps_solve_1D(potential, effective_mass, ¶ms); ps_list_add_all(solutions, e_solutions); ps_list_destroy(e_solutions); // Destroy the list without destroying the data. // Next loop iteration s = ps_list_next(coarse_solutions); } ps_list_destroy_all(coarse_solutions); } else { // 2d solver PS_LIST coarse_solutions = ps_solve_2D(potential, ¶ms); ps_list_add_all(solutions, coarse_solutions); ps_list_destroy(coarse_solutions); } // Write out solutions sprintf(msg, "Found %i solutions. Writing to E.txt and BS.dat\n", ps_list_size(solutions)); ps_log(msg); FILE *efile = fopen("E.txt", "w"); fprintf(efile, "# Bound State Energies [eV]\n"); FILE *bsfile = fopen("BS.dat", "w"); s = ps_list_front(solutions); while (s != NULL) { // Write the energies to the energy file fprintf(efile, "%g\n", s->energy/EV_TO_ERGS); // Write the wavefunctions to the solutino file ps_data_write_bin(s->wavefunction, bsfile); s = ps_list_next(solutions); } fclose(bsfile); fclose(efile); FILE *gfile = fopen("G.dat", "w"); s = ps_list_front(g_solutions); while (s != NULL) { ps_data_write_bin(s->wavefunction, gfile); s = ps_list_next(g_solutions); } fclose(gfile); ps_list_destroy_all(g_solutions); //clean up ps_data_destroy(potential); ps_list_destroy_all(solutions); return PS_OK; }
void ps_control_create_daemon(void) { int fd_initdata[2]; ps_log(0, LOG_INFO("creating daemon")); ps_safe_to_change_name=(strcmp(ps_program_name,"psc") == 0) ? 1 : 0; if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fd_initdata) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("failed to create socketpair for daemon initialization - error [%s]"), strerror(errno)); // become a child of the init process by forking and closing the parent process. switch (fork()) { case -1: ps_log(EXIT_FAILURE, LOG_ERROR("unable to create daemon - fork 1")); case 0: // become the leader of new session if (setsid() == -1) return; // do another fork to prevent the daemon to open a controlling terminal in the future. // use the clone() function to create new PID and UTS namespaces for the child. long stack_size = 4*sysconf(_SC_PAGESIZE); char *stack; int pid_daemon; if (!(stack = malloc(stack_size))) ps_log(EXIT_FAILURE, LOG_ERROR("failed to allocate stack")); pid_daemon=clone(ps_daemon_main_wrapper, stack+stack_size, CLONE_NEWPID | CLONE_NEWUTS | SIGCHLD, (void *) (fd_initdata+1)); close(fd_initdata[1]); if (pid_daemon == -1) ps_log(EXIT_FAILURE, LOG_ERROR("unable to create daemon - fork 2")); // send a message to the newly created daemon if (write(fd_initdata[0], &pid_daemon, sizeof(pid_daemon)) == -1) ps_log(EXIT_FAILURE, LOG_ERROR("failed to send daemon pid to daemon - error [%s]"), strerror(errno)); _exit(EXIT_SUCCESS); default: // wait for daemon response close(fd_initdata[1]); int read_count=read(fd_initdata[0], &ps_pid, sizeof(ps_pid)); if (read_count < sizeof(ps_pid)) ps_pid=0; sprintf(ps_buffer,"%d\n", ps_pid); write(STDOUT_FILENO, ps_buffer, strlen(ps_buffer)); if (read_count < sizeof(ps_pid)) ps_log(EXIT_FAILURE, LOG_ERROR("did not receive daemon pid")); // daemon created and ready to accept connections ps_log(0, LOG_INFO("ps_pid [%d]"), ps_pid); } }