Loading...
Searching...
No Matches
RelaxEngineAbi.cpp File Reference
#include "eon/relax/eon_relax_engine.h"
#include "eon/Eigen.h"
#include "eon/Matter.h"
#include "eon/MinModeSaddleSearch.h"
#include "eon/NudgedElasticBand.h"
#include "eon/Optimizer.h"
#include "eon/Parameters.h"
#include "eon_relax_engine.capnp.h"
#include "relax/HostSurfacePotential.h"
#include "version.h"
#include <capnp/serialize.h>
#include <kj/array.h>
#include <kj/common.h>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <memory>
#include <new>
#include <stdexcept>
#include <string>
#include <vector>

Go to the source code of this file.

Classes

struct  EonRelaxEngine
class  Matter
class  MinModeSaddleSearch
class  NEBObjectiveFunction
class  NudgedElasticBand
class  Optimizer
 Abstract base of the structure optimizers. More...
class  Parameters
struct  ParametersLoadAccess
 Write hole for INI/JSON loaders and nanobind property setters. More...

Functions

uint64_t eon_relax_version_hash (void)
 64-bit FNV-1a hash of eon_relax_version_hash_str().
static int stamp_rc (EonRelaxEngine *eng, int rc)
static int fail_out (EonRelaxEngine *eng, eon_relax_outcome_t *out, int rc, eon_relax_kind_t kind, uint64_t epoch)
static void clear_stepper (EonRelaxEngine *eng)
int eon_relax_abi_version (void)
 (major << 16) | minor.
int eon_relax_available (void)
int eon_relax_abi_stamp (eon_relax_version_t *out)
const char * eon_relax_version_hash_str (void)
 Immortal dest identity string.
EonRelaxEngine * eon_relax_create (const void *config, size_t config_len, char *errbuf, size_t errlen)
 Create.
int eon_relax_set_surface_epoch (EonRelaxEngine *eng, uint64_t epoch)
int eon_relax_last_error (const EonRelaxEngine *eng)
 Last named create/run/step/reset/set_epoch rc on this handle.
int eon_relax_run (EonRelaxEngine *eng, eon_relax_band_t *band, eon_relax_surface_fn surface, void *user, eon_relax_outcome_t *out)
 Run the bound engine to completion.
int eon_relax_step (EonRelaxEngine *eng, eon_relax_band_t *band, eon_relax_surface_fn surface, void *user, eon_relax_outcome_t *out)
 One band optimizer step (kind=NEB only).
int eon_relax_reset (EonRelaxEngine *eng)
 Drop the stepper's band state and optimizer history; the next eon_relax_step reinitializes from the caller's band.
void eon_relax_destroy (EonRelaxEngine *eng)
const char * eon_relax_status_name (eon_relax_kind_t kind, int status)
 NULL if kind or status is unknown.

Function Documentation

◆ clear_stepper()

void clear_stepper ( EonRelaxEngine * eng)
static

Definition at line 243 of file RelaxEngineAbi.cpp.

243 {
244 eng->step_opt.reset();
245 eng->step_objf.reset();
246 eng->step_neb.reset();
247 eng->step_pot.reset();
248 eng->step_surface = nullptr;
249 eng->step_user = nullptr;
250 eng->step_baseline = 0.0;
251 eng->step_iteration = 0;
252}
std::shared_ptr< eonc::HostSurfacePotential > step_pot
std::shared_ptr< NEBObjectiveFunction > step_objf
eon_relax_surface_fn step_surface
std::unique_ptr< NudgedElasticBand > step_neb
std::unique_ptr< Optimizer > step_opt

◆ eon_relax_abi_stamp()

int eon_relax_abi_stamp ( eon_relax_version_t * out)

Definition at line 262 of file RelaxEngineAbi.cpp.

262 {
263 if (!out) {
265 }
268 return EON_RELAX_OK;
269}
#define EON_RELAX_ABI_MAJOR
#define EON_RELAX_ABI_MINOR
@ EON_RELAX_OK
@ EON_RELAX_INVALID_PARAMETER

◆ eon_relax_abi_version()

int eon_relax_abi_version ( void )

(major << 16) | minor.

Definition at line 256 of file RelaxEngineAbi.cpp.

256 {
257 return static_cast<int>((EON_RELAX_ABI_MAJOR << 16) | EON_RELAX_ABI_MINOR);
258}

◆ eon_relax_available()

int eon_relax_available ( void )

Definition at line 260 of file RelaxEngineAbi.cpp.

260{ return 1; }

◆ eon_relax_create()

EonRelaxEngine * eon_relax_create ( const void * config,
size_t config_len,
char * errbuf,
size_t errlen )

Create.

NULL config && config_len==0 selects Parameters NSDMI defaults and kind=NEB. A non-empty buffer is a Cap'n Proto flat-array whose root is RelaxEngineParams. kind tokens are "neb" and "saddle"; any other token fails closed (EON_RELAX_UNKNOWN_KIND). An unparseable buffer is EON_RELAX_CAPNP_ROOT. config!=NULL && config_len==0 is refused.

Definition at line 282 of file RelaxEngineAbi.cpp.

283 {
284 auto make_engine = [&]() -> std::unique_ptr<EonRelaxEngine> {
285 try {
286 return std::make_unique<EonRelaxEngine>();
287 } catch (const std::bad_alloc &) {
288 set_err(errbuf, errlen, "-19 out of memory");
289 return nullptr;
290 }
291 };
292 if (config == nullptr && config_len == 0) {
293 auto eng = make_engine();
294 if (!eng) {
295 return nullptr;
296 }
297 eng->kind = EON_RELAX_KIND_NEB;
298 return eng.release();
299 }
300 if (config == nullptr || config_len == 0) {
301 set_err(errbuf, errlen, "-13 RelaxEngineParams capnp root");
302 return nullptr;
303 }
304 auto eng = make_engine();
305 if (!eng) {
306 return nullptr;
307 }
308 const int prc = apply_relax_params(eng->params, &eng->kind, &eng->epoch,
309 config, config_len, errbuf, errlen);
310 if (prc != EON_RELAX_OK) {
311 return nullptr;
312 }
313 return eng.release();
314}
static void set_err(char *errbuf, size_t errlen, const char *msg)
@ EON_RELAX_KIND_NEB

◆ eon_relax_destroy()

void eon_relax_destroy ( EonRelaxEngine * eng)

Definition at line 637 of file RelaxEngineAbi.cpp.

637 {
638 std::unique_ptr<EonRelaxEngine> owned(eng);
639}

◆ eon_relax_last_error()

int eon_relax_last_error ( const EonRelaxEngine * eng)

Last named create/run/step/reset/set_epoch rc on this handle.

0 if none.

Definition at line 331 of file RelaxEngineAbi.cpp.

331 {
332 if (!eng) {
334 }
335 return eng->last_rc;
336}
@ EON_RELAX_NULL_ENGINE

◆ eon_relax_reset()

int eon_relax_reset ( EonRelaxEngine * eng)

Drop the stepper's band state and optimizer history; the next eon_relax_step reinitializes from the caller's band.

This is the host's model-update hook: quasi-Newton memory taken on one surface epoch must not survive onto the next.

Definition at line 625 of file RelaxEngineAbi.cpp.

625 {
626 if (!eng) {
628 }
629 if (eng->unusable) {
631 }
632 clear_stepper(eng);
633 eng->last_rc = EON_RELAX_OK;
634 return EON_RELAX_OK;
635}
static int stamp_rc(EonRelaxEngine *eng, int rc)
static void clear_stepper(EonRelaxEngine *eng)
@ EON_RELAX_SURFACE_FATAL

◆ eon_relax_run()

int eon_relax_run ( EonRelaxEngine * eng,
eon_relax_band_t * band,
eon_relax_surface_fn surface,
void * user,
eon_relax_outcome_t * out )

Run the bound engine to completion.

Writes updated interior coordinates into band->positions (caller-owned); endpoints stay in the caller frame. Endpoint minimization stays with the host (NudgedElasticBand::compute does not minimize endpoints). surface may not be NULL. Kind is bound at create (NULL config => NEB). Returns eon_relax_rc_t; on 0, out->status is the dest NEB or saddle table.

Definition at line 338 of file RelaxEngineAbi.cpp.

340 {
341 if (!eng) {
343 }
344 if (eng->unusable) {
345 return fail_out(eng, out, EON_RELAX_SURFACE_FATAL, eng->kind, eng->epoch);
346 }
347 if (!band) {
348 return fail_out(eng, out, EON_RELAX_NULL_BAND, eng->kind, eng->epoch);
349 }
350 if (!surface) {
351 return fail_out(eng, out, EON_RELAX_NULL_SURFACE, eng->kind, eng->epoch);
352 }
353 if (!out) {
354 return stamp_rc(eng, EON_RELAX_NULL_OUTCOME);
355 }
356 clear_stepper(eng);
357 if (band->n_atoms <= 0) {
358 return fail_out(eng, out, EON_RELAX_NATOMS, eng->kind, eng->epoch);
359 }
360 if (!band->positions) {
361 return fail_out(eng, out, EON_RELAX_NULL_POSITIONS, eng->kind, eng->epoch);
362 }
363 if (!band->atomic_nrs) {
364 return fail_out(eng, out, EON_RELAX_NULL_ATOMIC_NRS, eng->kind, eng->epoch);
365 }
366 if (!band->boxes) {
367 return fail_out(eng, out, EON_RELAX_NULL_BOXES, eng->kind, eng->epoch);
368 }
369 if (band->version.major != EON_RELAX_ABI_MAJOR) {
370 return fail_out(eng, out, EON_RELAX_ABI_MISMATCH, eng->kind, eng->epoch);
371 }
372 if (!known_kind(eng->kind)) {
373 return fail_out(eng, out, EON_RELAX_UNKNOWN_KIND, eng->kind, eng->epoch);
374 }
375 const int mass_rc = masses_ok(band);
376 if (mass_rc != EON_RELAX_OK) {
377 return fail_out(eng, out, mass_rc, eng->kind, eng->epoch);
378 }
379 stamp_outcome(out, eng->kind, eng->epoch);
380
381 auto pot =
382 std::make_shared<eonc::HostSurfacePotential>(surface, user, eng->epoch);
383 try {
384 if (eng->kind == EON_RELAX_KIND_NEB) {
385 if (band->n_images < 3) {
386 out->status = -1;
388 }
389 const int64_t want =
390 static_cast<int64_t>(eng->params.neb_options().image_count) + 2;
391 if (band->n_images != want) {
392 out->status = -1;
393 return stamp_rc(eng, EON_RELAX_BAND_SIZE);
394 }
395 std::vector<Matter> path;
396 path.reserve(static_cast<size_t>(band->n_images));
397 for (int64_t i = 0; i < band->n_images; ++i) {
398 Matter img(pot, eng->params);
399 fill_matter(img, band, static_cast<long>(i), eng->epoch);
400 path.push_back(std::move(img));
401 }
402 auto neb = std::make_unique<NudgedElasticBand>(std::move(path),
403 eng->params, pot);
404 pot->bindPath(neb->path);
405 dirty_endpoints(*neb);
406 const auto st = neb->compute();
407 if (st == NudgedElasticBand::NEBStatus::INIT ||
408 st == NudgedElasticBand::NEBStatus::RUNNING) {
409 out->status = neb_status(st);
411 }
412 out->status = neb_status(st);
413 NEBObjectiveFunction ranked(neb.get(), eng->params);
414 if (ranked.isUncertain()) {
416 }
417 out->iterations = neb->lastIteration();
418 out->climbing_image = neb->climbingImage;
419 out->max_force = neb->convergenceForce();
420 out->surface_epoch = pot->surfaceEpoch();
421 for (int64_t i = 1; i + 1 < band->n_images; ++i) {
422 write_image(band->positions + i * 3 * band->n_atoms,
423 *neb->path[static_cast<size_t>(i)],
424 static_cast<long>(band->n_atoms));
425 }
426 return stamp_rc(eng, EON_RELAX_OK);
427 }
428
429 if (band->n_images != 1) {
430 out->status = -1;
432 }
433 if (!band->mode) {
434 out->status = -1;
435 return stamp_rc(eng, EON_RELAX_NULL_MODE);
436 }
437 auto matter = std::make_shared<Matter>(pot, eng->params);
438 fill_matter(*matter, band, 0, eng->epoch);
439 AtomMatrix mode(band->n_atoms, 3);
440 Eigen::Map<const AtomMatrix> mmap(band->mode, band->n_atoms, 3);
441 mode = mmap;
442 const double reactant_e = matter->getPotentialEnergy();
443 MinModeSaddleSearch search(matter, mode, reactant_e, eng->params, pot);
444 const int sst = search.run();
445 write_image(band->positions, *matter, static_cast<long>(band->n_atoms));
446 out->iterations = search.getIterationCount();
447 out->surface_epoch = pot->surfaceEpoch();
448 out->status = sst;
449 return stamp_rc(eng, EON_RELAX_OK);
450 } catch (const eonc::SurfaceRecoverable &rec) {
451 out->status = -1;
452 return stamp_rc(eng, rec.rc);
453 } catch (const std::exception &) {
454 out->status = -1;
455 eng->unusable = true;
457 }
458}
Eigen::Matrix< double, Eigen::Dynamic, 3, eOnStorageOrder > AtomMatrix
Definition Eigen.h:37
static int fail_out(EonRelaxEngine *eng, eon_relax_outcome_t *out, int rc, eon_relax_kind_t kind, uint64_t epoch)
const neb_options_t & neb_options() const
@ EON_RELAX_NEB_MAX_UNCERTAINTY
@ EON_RELAX_NULL_BAND
@ EON_RELAX_BAND_SIZE
@ EON_RELAX_NULL_ATOMIC_NRS
@ EON_RELAX_NULL_POSITIONS
@ EON_RELAX_NULL_BOXES
@ EON_RELAX_NULL_SURFACE
@ EON_RELAX_UNKNOWN_STATUS
@ EON_RELAX_ABI_MISMATCH
@ EON_RELAX_UNKNOWN_KIND
@ EON_RELAX_SADDLE_NIMAGES
@ EON_RELAX_BAND_TOO_SHORT
@ EON_RELAX_NULL_OUTCOME
@ EON_RELAX_NATOMS
@ EON_RELAX_NULL_MODE
eon_relax_kind_t kind
eon_relax_version_t version
const int32_t * atomic_nrs
const double * boxes
const double * mode

◆ eon_relax_set_surface_epoch()

int eon_relax_set_surface_epoch ( EonRelaxEngine * eng,
uint64_t epoch )

Definition at line 316 of file RelaxEngineAbi.cpp.

316 {
317 if (!eng) {
319 }
320 if (eng->unusable) {
322 }
323 eng->epoch = epoch;
324 if (eng->step_pot) {
325 eng->step_pot->setEpoch(epoch);
326 }
327 eng->last_rc = EON_RELAX_OK;
328 return EON_RELAX_OK;
329}
void setEpoch(std::uint64_t epoch)

◆ eon_relax_status_name()

const char * eon_relax_status_name ( eon_relax_kind_t kind,
int status )

NULL if kind or status is unknown.

Definition at line 641 of file RelaxEngineAbi.cpp.

641 {
642 if (kind == EON_RELAX_KIND_NEB) {
643 switch (status) {
645 return "GOOD";
647 return "INIT";
649 return "BAD_MAX_ITERATIONS";
651 return "RUNNING";
653 return "MAX_UNCERTAINTY";
654 default:
655 return nullptr;
656 }
657 }
658 if (kind == EON_RELAX_KIND_SADDLE) {
659 const auto msg = MinModeSaddleSearch::statusMessage(status);
660 if (msg == "Unknown status") {
661 return nullptr;
662 }
663 return msg.data();
664 }
665 return nullptr;
666}
static constexpr std::string_view statusMessage(int status)
Human-readable message for a status code.
@ EON_RELAX_NEB_GOOD
@ EON_RELAX_NEB_BAD_MAX_ITERATIONS
@ EON_RELAX_NEB_RUNNING
@ EON_RELAX_NEB_INIT
@ EON_RELAX_KIND_SADDLE

◆ eon_relax_step()

int eon_relax_step ( EonRelaxEngine * eng,
eon_relax_band_t * band,
eon_relax_surface_fn surface,
void * user,
eon_relax_outcome_t * out )

One band optimizer step (kind=NEB only).

The first call on a fresh or reset engine initializes the band state from the caller's positions and captures the baseline force; every call syncs band->positions in (the host may have moved images between steps), assembles NEB forces on the host surface, takes ONE optimizer step, and writes the stepped INTERIOR positions back (endpoints are the caller's and are never rewritten, so the caller's frame survives eOn's own cell wrapping). Climbing-image activation follows the engine's own trigger rule; saddle POLICY (MMF bursts, resampling, acquisition) stays with the host. outcome.status is RUNNING until convergenceForce() reaches the configured tolerance (GOOD), host variance exceeds the GP-surrogate threshold (MAX_UNCERTAINTY), or neb.max_iterations is hit (BAD_MAX_ITERATIONS). surface and user must not change across steps without an eon_relax_reset.

Definition at line 460 of file RelaxEngineAbi.cpp.

462 {
463 if (!eng) {
465 }
466 if (eng->unusable) {
467 return fail_out(eng, out, EON_RELAX_SURFACE_FATAL, eng->kind, eng->epoch);
468 }
469 if (!band) {
470 return fail_out(eng, out, EON_RELAX_NULL_BAND, eng->kind, eng->epoch);
471 }
472 if (!surface) {
473 return fail_out(eng, out, EON_RELAX_NULL_SURFACE, eng->kind, eng->epoch);
474 }
475 if (!out) {
476 return stamp_rc(eng, EON_RELAX_NULL_OUTCOME);
477 }
478 if (eng->kind == EON_RELAX_KIND_SADDLE) {
479 return fail_out(eng, out, EON_RELAX_INVALID_PARAMETER, eng->kind,
480 eng->epoch);
481 }
482 if (eng->kind != EON_RELAX_KIND_NEB) {
483 return fail_out(eng, out, EON_RELAX_UNKNOWN_KIND, eng->kind, eng->epoch);
484 }
485 if (band->n_atoms <= 0) {
486 return fail_out(eng, out, EON_RELAX_NATOMS, EON_RELAX_KIND_NEB, eng->epoch);
487 }
488 if (!band->positions) {
490 eng->epoch);
491 }
492 if (!band->atomic_nrs) {
494 eng->epoch);
495 }
496 if (!band->boxes) {
498 eng->epoch);
499 }
500 if (band->version.major != EON_RELAX_ABI_MAJOR) {
502 eng->epoch);
503 }
504 const int mass_rc = masses_ok(band);
505 if (mass_rc != EON_RELAX_OK) {
506 return fail_out(eng, out, mass_rc, EON_RELAX_KIND_NEB, eng->epoch);
507 }
508 stamp_outcome(out, EON_RELAX_KIND_NEB, eng->epoch);
509 if (eng->step_neb && (band->n_atoms != eng->step_neb->atoms ||
510 band->n_images != eng->step_neb->numImages + 2)) {
511 out->status = -1;
513 }
514 if (band->n_images < 3) {
515 out->status = -1;
517 }
518 const int64_t want =
519 static_cast<int64_t>(eng->params.neb_options().image_count) + 2;
520 if (band->n_images != want) {
521 out->status = -1;
522 return stamp_rc(eng, EON_RELAX_BAND_SIZE);
523 }
524 if (eng->step_neb &&
525 (eng->step_surface != surface || eng->step_user != user)) {
526 out->status = -1;
528 }
529
530 try {
531 if (!eng->step_neb) {
532 eng->step_pot = std::make_shared<eonc::HostSurfacePotential>(
533 surface, user, eng->epoch);
534 std::vector<Matter> path;
535 path.reserve(static_cast<size_t>(band->n_images));
536 for (int64_t i = 0; i < band->n_images; ++i) {
537 Matter img(eng->step_pot, eng->params);
538 fill_matter(img, band, static_cast<long>(i), eng->epoch);
539 path.push_back(std::move(img));
540 }
541 eng->step_neb = std::make_unique<NudgedElasticBand>(
542 std::move(path), eng->params, eng->step_pot);
543 eng->step_pot->bindPath(eng->step_neb->path);
544 dirty_endpoints(*eng->step_neb);
545 eng->step_neb->E_ref =
546 std::min(eng->step_neb->path[0]->getPotentialEnergy(),
547 eng->step_neb->path[eng->step_neb->numImages + 1]
548 ->getPotentialEnergy());
549 eng->step_neb->updateForces();
550 eng->step_objf = std::make_shared<NEBObjectiveFunction>(
551 eng->step_neb.get(), eng->params);
553 eng->step_objf, eng->params.neb_options().opt_method, eng->params);
554 eng->step_surface = surface;
555 eng->step_user = user;
556 eng->step_baseline = eng->step_neb->convergenceForce();
557 eng->step_iteration = 0;
558 } else {
559 // The host may have moved images between steps (acquisition,
560 // reparameterization); resync and mark the band dirty.
561 for (int64_t i = 0; i < band->n_images; ++i) {
562 fill_matter(*eng->step_neb->path[static_cast<size_t>(i)], band,
563 static_cast<long>(i), eng->epoch);
564 }
565 eng->step_neb->movedAfterForceCall = true;
566 eng->step_neb->updateForces();
567 }
568
569 NudgedElasticBand &neb = *eng->step_neb;
570 const double convForce = neb.convergenceForce();
571 const auto &ci_opt = eng->params.neb_options().climbing_image;
572 const bool ci_active =
573 ci_opt.enabled &&
574 (convForce < eng->step_baseline * ci_opt.trigger_factor ||
575 convForce < ci_opt.trigger_force);
576 neb.setCIEnabled(ci_active);
577
578 const double force_tol = eng->params.neb_options().force_tolerance;
579 const long max_iter = eng->params.neb_options().max_iterations;
580 int status = EON_RELAX_NEB_RUNNING;
581 if (eng->step_objf && eng->step_objf->isUncertain()) {
583 } else if (convForce <= force_tol) {
584 status = EON_RELAX_NEB_GOOD;
585 } else if (eng->step_iteration >= max_iter) {
587 } else {
588 eng->step_opt->step(eng->params.optimizer_options().max_move);
589 ++eng->step_iteration;
590 neb.updateForces();
591 if (eng->step_objf && eng->step_objf->isUncertain()) {
593 } else if (neb.convergenceForce() <= force_tol) {
594 status = EON_RELAX_NEB_GOOD;
595 } else if (eng->step_iteration >= max_iter) {
597 }
598 }
599
600 // Interior images only: eOn never moves the endpoints, and Matter
601 // wraps positions into the cell, so writing them back would hand
602 // the caller a different frame than the one it supplied.
603 for (int64_t i = 1; i + 1 < band->n_images; ++i) {
604 write_image(band->positions + i * 3 * band->n_atoms,
605 *neb.path[static_cast<size_t>(i)],
606 static_cast<long>(band->n_atoms));
607 }
608 out->status = status;
609 out->iterations = eng->step_iteration;
610 out->climbing_image = neb.climbingImage;
611 out->max_force = neb.convergenceForce();
612 out->surface_epoch = eng->step_pot->surfaceEpoch();
613 return stamp_rc(eng, EON_RELAX_OK);
614 } catch (const eonc::SurfaceRecoverable &rec) {
615 out->status = -1;
616 clear_stepper(eng);
617 return stamp_rc(eng, rec.rc);
618 } catch (const std::exception &) {
619 out->status = -1;
620 eng->unusable = true;
622 }
623}
void bindPath(const std::vector< std::shared_ptr< Matter > > &path)
unsigned long long surfaceEpoch() const noexcept override
Host-visible surface generation.
void updateForces(bool ci_active)
std::vector< std::shared_ptr< Matter > > path
void setCIEnabled(bool enabled)
const optimizer_options_t & optimizer_options() const
std::unique_ptr< Optimizer > mkOptim(std::shared_ptr< ObjectiveFunction > a_objf, OptType a_otype, const Parameters &a_params)
Definition Optimizer.cpp:55
struct eonc::neb_options_t::climbing_image_options_t climbing_image

◆ eon_relax_version_hash()

uint64_t eon_relax_version_hash ( void )

64-bit FNV-1a hash of eon_relax_version_hash_str().

Copied to outcome.version_hash.

Definition at line 278 of file RelaxEngineAbi.cpp.

278 {
279 return fnv1a64(eon_relax_version_hash_str());
280}
const char * eon_relax_version_hash_str(void)
Immortal dest identity string.

◆ eon_relax_version_hash_str()

const char * eon_relax_version_hash_str ( void )

Immortal dest identity string.

Never NULL.

Definition at line 271 of file RelaxEngineAbi.cpp.

271 {
272 static const std::string id =
273 VERSION + "+git." + GIT_HASH_FULL + "+feat." +
274 std::to_string(fnv1a64(FEATURES_STRING.c_str()));
275 return id.c_str();
276}

◆ fail_out()

int fail_out ( EonRelaxEngine * eng,
eon_relax_outcome_t * out,
int rc,
eon_relax_kind_t kind,
uint64_t epoch )
static

Definition at line 234 of file RelaxEngineAbi.cpp.

235 {
236 if (out) {
237 stamp_outcome(out, kind, epoch);
238 out->status = -1;
239 }
240 return stamp_rc(eng, rc);
241}

◆ stamp_rc()

int stamp_rc ( EonRelaxEngine * eng,
int rc )
static

Definition at line 227 of file RelaxEngineAbi.cpp.

227 {
228 if (eng) {
229 eng->last_rc = rc;
230 }
231 return rc;
232}