def setup(self): """ Launch the first calculation for the input structure, and a second calculation for a shifted volume (increased by 4 angstrom^3) Store the outputs of the two calcs in r0 and r1 """ print "Workchain node identifiers: {}".format(self.calc) inputs0 = generate_scf_input_params(self.inputs.structure, str(self.inputs.code), self.inputs.pseudo_family) initial_volume = self.inputs.structure.get_cell_volume() new_volume = initial_volume + 4. # In ang^3 scaled_structure = get_structure(self.inputs.structure, new_volume) inputs1 = generate_scf_input_params(scaled_structure, str(self.inputs.code), self.inputs.pseudo_family) self.ctx.last_structure = scaled_structure # Run PW future0 = submit(PwProcess, **inputs0) future1 = submit(PwProcess, **inputs1) # Wait to complete before next step return ToContext(r0=future0, r1=future1)
def move_next_step(self, ctx): """ Main routine that reads the two previous calculations r0 and r1, uses the Newton's algorithm on the pressure (i.e., fits the results with a parabola and sets the next point to calculate to the parabola minimum). r0 gets replaced with r1, r1 will get replaced by the results of the new calculation. """ ddE = get_second_derivative(ctx.r0['output_parameters'], ctx.r1['output_parameters']) V, E, dE = get_volume_energy_and_derivative(ctx.r1['output_parameters']) a,b,c = get_abc(V,E,dE,ddE) new_step_data = {'V': V, 'E': E, 'dE': dE, 'ddE': ddE, 'a': a, 'b': b, 'c': c} ctx.steps.append(new_step_data) # Minimum of a parabola new_volume = -b/2./a # remove older step ctx.r0 = ctx.r1 scaled_structure = get_structure(self.inputs.structure, new_volume) ctx.last_structure = scaled_structure inputs = generate_scf_input_params( scaled_structure, str(self.inputs.code), str(self.inputs.pseudo_family)) # Run PW future = self.submit(PwProcess, inputs) # Replace r1 return ResultToContext(r1=future)
def run_eos_wf(codename, pseudo_family, element): print "Workfunction node identifiers: {}".format(Process.current().calc) s0 = create_diamond_fcc(Str(element)) calcs = {} for label, factor in zip(labels, scale_facs): s = rescale(s0, Float(factor)) inputs = generate_scf_input_params(s, str(codename), Str(pseudo_family)) print "Running a scf for {} with scale factor {}".format( element, factor) result = run(PwCalculation, **inputs) print "RESULT: {}".format(result) calcs[label] = get_info(result) eos = [] for label in labels: eos.append(calcs[label]) # Return information to plot the EOS ParameterData = DataFactory('parameter') retdict = { 'initial_structure': s0, 'result': ParameterData(dict={'eos_data': eos}) } return retdict
def setup(self): """Launch the first calculation for the input structure, and a second calculation for a shifted volume.""" scaled_structure = get_structure(self.inputs.structure) self.ctx.last_structure = scaled_structure inputs0 = generate_scf_input_params(self.inputs.structure, self.inputs.code, self.inputs.pseudo_family) inputs1 = generate_scf_input_params(scaled_structure, self.inputs.code, self.inputs.pseudo_family) # Run two `PwCalculations` future0 = self.submit(PwCalculation, **inputs0) future1 = self.submit(PwCalculation, **inputs1) # Wait for them to complete before going to the next step return ToContext(r0=future0, r1=future1)
def init(self, ctx): """ Launch the first calculation for the input structure, and a second calculation for a shifted volume (increased by 4 angstrom^3) Store the outputs of the two calcs in r0 and r1 """ inputs0 = generate_scf_input_params( self.inputs.structure, str(self.inputs.code), str(self.inputs.pseudo_family)) initial_volume = self.inputs.structure.get_cell_volume() new_volume = initial_volume + 4. # In ang^3 scaled_structure = get_structure(self.inputs.structure, new_volume) inputs1 = generate_scf_input_params( scaled_structure, str(self.inputs.code), str(self.inputs.pseudo_family)) ctx.last_structure = scaled_structure # Run PW future0 = self.submit(PwProcess, inputs0) future1 = self.submit(PwProcess, inputs1) # Wait to complete before next step return ResultToContext(r0=future0, r1=future1)
def run_eos_wf(codename, pseudo_family, element): print "Workfunction node pk: {}".format(registry.current_calc_node) #Instantiate a JobCalc process and create basic structure JobCalc = PwCalculation.process() s0 = create_diamond_fcc(Str(element)) eos=[] scale_facs = (0.98, 0.99, 1.0, 1.02, 1.04) for factor in scale_facs: s = rescale(s0,Float(factor)) inputs = generate_scf_input_params( s, str(codename), str(pseudo_family)) print "Running a scf for {} with scale factor {}".format( element, factor) calc_results = run(JobCalc,**inputs) eos.append(get_info(calc_results)) #Return information to plot the EOS ParameterData = DataFactory("parameter") return {'initial_structure': s0,'result': ParameterData(dict={'eos_data': eos})}
def move_next_step(self): """ Main routine that reads the two previous calculations r0 and r1, uses the Newton's algorithm on the pressure (i.e., fits the results with a parabola and sets the next point to calculate to the parabola minimum). r0 gets replaced with r1, r1 will get replaced by the results of the new calculation. """ r0_out = self.ctx.r0.get_outputs_dict() r1_out = self.ctx.r1.get_outputs_dict() ddE = get_second_derivative(r0_out['output_parameters'], r1_out['output_parameters']) V, E, dE = get_volume_energy_and_derivative( r1_out['output_parameters']) a, b, c = get_abc(V, E, dE, ddE) new_step_data = { 'V': V, 'E': E, 'dE': dE, 'ddE': ddE, 'a': a, 'b': b, 'c': c } self.ctx.steps.append(new_step_data) # Minimum of a parabola new_volume = -b / 2. / a # remove older step self.ctx.r0 = self.ctx.r1 scaled_structure = get_structure(self.inputs.structure, new_volume) self.ctx.last_structure = scaled_structure inputs = generate_scf_input_params(scaled_structure, str(self.inputs.code), self.inputs.pseudo_family) # Run PW future = submit(PwProcess, **inputs) # Replace r1 return ToContext(r1=future)
def run_pw(self): print "Workchain node identifiers: {}".format(self.calc) #Instantiate a JobCalc process and create basic structure JobCalc = PwCalculation.process() self.ctx.s0 = create_diamond_fcc(Str(self.inputs.element)) self.ctx.eos_names = [] calcs = {} for label, factor in zip(labels, scale_facs): s = rescale(self.ctx.s0, Float(factor)) inputs = generate_scf_input_params(s, str(self.inputs.code), self.inputs.pseudo_family) print "Running a scf for {} with scale factor {}".format( self.inputs.element, factor) future = submit(JobCalc, **inputs) calcs[label] = future # Ask the workflow to continue when the results are ready and store them # in the context return ToContext(**calcs)
def run_eos_wf(code, pseudo_family, element): """Run an equation of state of a bulk crystal structure for the given element.""" # This will print the pk of the work function print('Running run_eos_wf<{}>'.format(Process.current().pid)) scale_factors = (0.96, 0.98, 1.0, 1.02, 1.04) labels = ['c1', 'c2', 'c3', 'c4', 'c5'] calculations = {} # Create an initial bulk crystal structure for the given element, using the calculation function defined earlier initial_structure = create_diamond_fcc(element) # Loop over the label and scale_factor pairs for label, factor in list(zip(labels, scale_factors)): # Generated the scaled structure from the initial structure structure = rescale(initial_structure, Float(factor)) # Generate the inputs for the `PwCalculation` inputs = generate_scf_input_params(structure, code, pseudo_family) # Launch a `PwCalculation` for each scaled structure print('Running a scf for {} with scale factor {}'.format( element, factor)) calculations[label] = run(PwCalculation, **inputs) # Bundle the individual results from each `PwCalculation` in a single dictionary node. # Note: since we are 'creating' new data from existing data, we *have* to go through a `calcfunction`, otherwise # the provenance would be lost! inputs = { label: result['output_parameters'] for label, result in calculations.items() } eos = create_eos_dictionary(**inputs) # Finally, return the results of this work function result = {'initial_structure': initial_structure, 'eos': eos} return result
def run_eos(self): """Run calculations for equation of state.""" # Create basic structure and attach it as an output initial_structure = create_diamond_fcc(self.inputs.element) self.out('initial_structure', initial_structure) calculations = {} for label, factor in zip(labels, scale_facs): structure = rescale(initial_structure, Float(factor)) inputs = generate_scf_input_params(structure, self.inputs.code, self.inputs.pseudo_family) self.report( 'Running an SCF calculation for {} with scale factor {}'. format(self.inputs.element, factor)) future = self.submit(PwCalculation, **inputs) calculations[label] = future # Ask the workflow to continue when the results are ready and store them in the context return ToContext(**calculations)
def run_pw(self, ctx): PwProcess = PwCalculation.process() ctx.s0 = create_diamond_fcc(Str(self.inputs.element)) ctx.eos_names = [] calcs = {} for label, factor in zip(labels, scale_facs): s = rescale(ctx.s0,Float(factor)) inputs = generate_scf_input_params( s, str(self.inputs.code), str(self.inputs.pseudo_family)) print "Running a scf for {} with scale factor {}".format( self.inputs.element, factor) # Launch the code future = self.submit(PwProcess, inputs) # Store the future calcs[label] = future # Ask the workflow to continue when the results are ready and store them # in the context return ResultToContext(**calcs)
def move_next_step(self): """Main part of the algorithm. Compare the results of two consecutive calculations and use Newton's algorithm on the pressure by fitting the results with a parabola and setting the next volume to calculate to the parabola minimum. The oldest calculation gets replaced by the most recent and a new calculation is launched that will replace the most recent. """ # Computer the new Volume using Newton's algorithm and create the new corresponding structure by scaling it new_step_data = get_step_data(self.ctx.r0.outputs.output_parameters, self.ctx.r1.outputs.output_parameters) scaled_structure = get_structure(self.inputs.structure, new_step_data) self.ctx.steps.append(new_step_data) # Replace the older step with the latest and set the current structure self.ctx.r0 = self.ctx.r1 self.ctx.last_structure = scaled_structure inputs = generate_scf_input_params(scaled_structure, self.inputs.code, self.inputs.pseudo_family) future = self.submit(PwCalculation, **inputs) return ToContext(r1=future)